@rufous/ui 0.1.98 → 0.1.100

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
@@ -13002,6 +13002,12 @@ var STATUS_IMAGES = {
13002
13002
  blocked: "https://storage.googleapis.com/rufous-com-bucket-1/static/images/blocked.svg",
13003
13003
  resolved: "https://storage.googleapis.com/rufous-com-bucket-1/static/images/closed.svg"
13004
13004
  };
13005
+ var STATUS_LABELS = {
13006
+ todo: "Todo",
13007
+ working: "Working",
13008
+ blocked: "Blocked",
13009
+ resolved: "Resolved"
13010
+ };
13005
13011
  var STATUS_COLORS = {
13006
13012
  todo: { border: "#dc2626", bg: "#fff", color: "#dc2626" },
13007
13013
  working: { border: "#2563eb", bg: "#eff6ff", color: "#2563eb" },
@@ -13045,14 +13051,16 @@ var CustomTaskItem = TaskItem.extend({
13045
13051
  if (afterContent.size > 0) {
13046
13052
  tr.delete(cursorPos, paraEnd);
13047
13053
  }
13048
- const newPara = afterContent.size > 0 ? schema.nodes.paragraph.create(null, afterContent) : schema.nodes.paragraph.create();
13054
+ const statusLabel = STATUS_LABELS[status] || STATUS_LABELS.todo;
13055
+ const newPara = afterContent.size > 0 ? schema.nodes.paragraph.create(null, afterContent) : schema.nodes.paragraph.create(null, schema.text(statusLabel));
13049
13056
  const newItem = schema.nodes.taskItem.create(
13050
13057
  { status, checked: false },
13051
13058
  newPara
13052
13059
  );
13053
13060
  const insertPos = tr.mapping.map($from.after(taskDepth));
13054
13061
  tr.insert(insertPos, newItem);
13055
- tr.setSelection(TextSelection.near(tr.doc.resolve(insertPos + 2)));
13062
+ const textLen = afterContent.size > 0 ? 0 : statusLabel.length;
13063
+ tr.setSelection(TextSelection.near(tr.doc.resolve(insertPos + 2 + textLen)));
13056
13064
  this.editor.view.dispatch(tr);
13057
13065
  return true;
13058
13066
  },
@@ -13092,10 +13100,35 @@ var CustomTaskItem = TaskItem.extend({
13092
13100
  const from = $from.before(taskItemDepth);
13093
13101
  const to = $from.after(taskItemDepth);
13094
13102
  tr.delete(from, to);
13095
- tr.setSelection(TextSelection.near(tr.doc.resolve(Math.max(0, from))));
13103
+ tr.setSelection(TextSelection.near(tr.doc.resolve(Math.max(0, from)), -1));
13096
13104
  this.editor.view.dispatch(tr);
13097
13105
  return true;
13098
13106
  }
13107
+ const indexInList = taskListDepth !== -1 ? $from.index(taskListDepth) : -1;
13108
+ if (indexInList > 0 && taskListDepth !== -1) {
13109
+ const tr = state.tr;
13110
+ const itemStart = $from.before(taskItemDepth);
13111
+ const itemEnd = $from.after(taskItemDepth);
13112
+ const posBefore = itemStart;
13113
+ if (tr.doc.resolve(posBefore).nodeBefore) {
13114
+ const textContent = taskItem.textContent;
13115
+ const contentSlice = taskItem.content;
13116
+ tr.delete(itemStart, itemEnd);
13117
+ const prevItemEndPos = Math.max(0, itemStart - 1);
13118
+ const $prevEnd = tr.doc.resolve(prevItemEndPos);
13119
+ const prevParaEnd = $prevEnd.end($prevEnd.depth);
13120
+ let insertAt = prevParaEnd;
13121
+ contentSlice.forEach((child) => {
13122
+ child.content.forEach((inline) => {
13123
+ tr.insert(insertAt, inline);
13124
+ insertAt += inline.nodeSize;
13125
+ });
13126
+ });
13127
+ tr.setSelection(TextSelection.create(tr.doc, prevParaEnd));
13128
+ this.editor.view.dispatch(tr);
13129
+ return true;
13130
+ }
13131
+ }
13099
13132
  return this.editor.commands.liftListItem(this.name);
13100
13133
  },
13101
13134
  "Shift-Tab": () => this.editor.commands.liftListItem(this.name),
@@ -13211,6 +13244,7 @@ var IconFullscreen = () => /* @__PURE__ */ React112.createElement("svg", { ...s
13211
13244
  var IconTranslate = () => /* @__PURE__ */ React112.createElement("svg", { ...s }, /* @__PURE__ */ React112.createElement("path", { d: "M12.87 15.07l-2.54-2.51.03-.03A17.52 17.52 0 0014.07 6H17V4h-7V2H8v2H1v1.99h11.17C11.5 7.92 10.44 9.75 9 11.35 8.07 10.32 7.3 9.19 6.69 8h-2.02c.73 1.63 1.73 3.17 2.98 4.56l-5.09 5.02L4 19l5-5 3.11 3.11.76-2.04zM18.5 10h-2L12 22h2l1.12-3h4.75L21 22h2l-4.5-12zm-2.62 7l1.62-4.33L19.12 17h-3.24z" }));
13212
13245
  var IconTaskList = () => /* @__PURE__ */ React112.createElement("svg", { ...s }, /* @__PURE__ */ React112.createElement("path", { d: "M22 8c0-.55-.45-1-1-1h-7c-.55 0-1 .45-1 1s.45 1 1 1h7c.55 0 1-.45 1-1zm0 8c0-.55-.45-1-1-1h-7c-.55 0-1 .45-1 1s.45 1 1 1h7c.55 0 1-.45 1-1zM5.54 11L2 7.46l1.41-1.41 2.12 2.12 4.24-4.24 1.41 1.41L5.54 11zm0 8L2 15.46l1.41-1.41 2.12 2.12 4.24-4.24 1.41 1.41L5.54 19z" }));
13213
13246
  var IconCheck = () => /* @__PURE__ */ React112.createElement("svg", { ...s }, /* @__PURE__ */ React112.createElement("path", { d: "M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z" }));
13247
+ var IconPaste = () => /* @__PURE__ */ React112.createElement("svg", { ...s }, /* @__PURE__ */ React112.createElement("path", { d: "M19 2h-4.18C14.4.84 13.3 0 12 0c-1.3 0-2.4.84-2.82 2H5c-1.1 0-2 .9-2 2v16c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2zm-7 0c.55 0 1 .45 1 1s-.45 1-1 1-1-.45-1-1 .45-1 1-1zm7 18H5V4h2v3h10V4h2v16z" }));
13214
13248
 
13215
13249
  // lib/RufousTextEditor/Toolbar.tsx
13216
13250
  var COLOR_PALETTE = [
@@ -13676,6 +13710,15 @@ var Toolbar = ({ editor, setLink, onAICommand, onTranslate, onSpeechToText, onTe
13676
13710
  setTimeout(() => setCopySuccess(false), 2e3);
13677
13711
  }
13678
13712
  }, [editor]);
13713
+ const handlePaste = useCallback12(async () => {
13714
+ if (!editor) return;
13715
+ try {
13716
+ const text = await navigator.clipboard.readText();
13717
+ if (text) editor.chain().focus().insertContent(text).run();
13718
+ } catch {
13719
+ document.execCommand("paste");
13720
+ }
13721
+ }, [editor]);
13679
13722
  const handleQuickTranslate = useCallback12(async () => {
13680
13723
  if (!editor) return;
13681
13724
  const { from, to, empty } = editor.state.selection;
@@ -14106,6 +14149,14 @@ var Toolbar = ({ editor, setLink, onAICommand, onTranslate, onSpeechToText, onTe
14106
14149
  title: "Copy selected text"
14107
14150
  },
14108
14151
  copySuccess ? /* @__PURE__ */ React113.createElement(IconCheck, null) : /* @__PURE__ */ React113.createElement(IconCopy, null)
14152
+ ), /* @__PURE__ */ React113.createElement(
14153
+ "button",
14154
+ {
14155
+ className: "toolbar-btn",
14156
+ onClick: handlePaste,
14157
+ title: "Paste (Ctrl+V)"
14158
+ },
14159
+ /* @__PURE__ */ React113.createElement(IconPaste, null)
14109
14160
  ), /* @__PURE__ */ React113.createElement(Dropdown, { trigger: { label: "\u03A9", title: "Special characters", className: "special-characters-btn" } }, /* @__PURE__ */ React113.createElement("div", { className: "char-grid" }, SPECIAL_CHARS.map((char) => /* @__PURE__ */ React113.createElement(
14110
14161
  "button",
14111
14162
  {
@@ -14117,10 +14168,26 @@ var Toolbar = ({ editor, setLink, onAICommand, onTranslate, onSpeechToText, onTe
14117
14168
  )))), /* @__PURE__ */ React113.createElement(
14118
14169
  Dropdown,
14119
14170
  {
14120
- trigger: { label: /* @__PURE__ */ React113.createElement(IconCode, null), title: "Code", className: editor.isActive("code") ? "is-active" : "" }
14171
+ trigger: { label: /* @__PURE__ */ React113.createElement(IconCode, null), title: "Code", className: editor.isActive("code") || editor.isActive("codeBlock") ? "is-active" : "" }
14121
14172
  },
14122
14173
  /* @__PURE__ */ React113.createElement("button", { className: "dropdown-item", onClick: () => editor.chain().focus().toggleCode().run() }, "</>", " Inline Code"),
14123
- /* @__PURE__ */ React113.createElement("button", { className: "dropdown-item", onClick: () => editor.chain().focus().toggleCodeBlock().run() }, "{ }", " Code Block")
14174
+ /* @__PURE__ */ React113.createElement("button", { className: "dropdown-item", onClick: () => editor.chain().focus().toggleCodeBlock().run() }, "{ }", " Code Block"),
14175
+ editor.isActive("codeBlock") && /* @__PURE__ */ React113.createElement("button", { className: "dropdown-item", onClick: () => {
14176
+ const text = (() => {
14177
+ const { $from } = editor.state.selection;
14178
+ for (let d = $from.depth; d > 0; d--) {
14179
+ if ($from.node(d).type.name === "codeBlock") return $from.node(d).textContent;
14180
+ }
14181
+ return "";
14182
+ })();
14183
+ if (text) {
14184
+ editor.chain().focus().toggleCodeBlock().run();
14185
+ const { from } = editor.state.selection;
14186
+ editor.chain().focus().setTextSelection({ from, to: from + text.length }).toggleCode().run();
14187
+ } else {
14188
+ editor.chain().focus().toggleCodeBlock().run();
14189
+ }
14190
+ } }, "</> \u2190", " Convert to Inline Code")
14124
14191
  ), /* @__PURE__ */ React113.createElement(
14125
14192
  "button",
14126
14193
  {
@@ -14137,52 +14204,73 @@ var Toolbar = ({ editor, setLink, onAICommand, onTranslate, onSpeechToText, onTe
14137
14204
  title: "Translate selected text"
14138
14205
  },
14139
14206
  /* @__PURE__ */ React113.createElement(IconTranslate, null)
14140
- ), /* @__PURE__ */ React113.createElement(Dropdown, { trigger: { label: "", title: "Translate options", className: "translate-arrow-btn" } }, /* @__PURE__ */ React113.createElement("button", { className: "dropdown-item", onClick: () => setShowTranslateModal(true) }, "Options")), translateStatus && /* @__PURE__ */ React113.createElement("span", { className: `translate-toast-popup ${translateStatus === "Please select the text" || translateStatus === "Translation failed" ? "error" : ""}` }, translateStatus)), /* @__PURE__ */ React113.createElement(
14141
- Dropdown,
14207
+ ), /* @__PURE__ */ React113.createElement(Dropdown, { trigger: { label: "", title: "Translate options", className: "translate-arrow-btn" } }, /* @__PURE__ */ React113.createElement("button", { className: "dropdown-item", onClick: () => setShowTranslateModal(true) }, "Options")), translateStatus && /* @__PURE__ */ React113.createElement("span", { className: `translate-toast-popup ${translateStatus === "Please select the text" || translateStatus === "Translation failed" ? "error" : ""}` }, translateStatus)), /* @__PURE__ */ React113.createElement("div", { className: "todo-split-btn" }, /* @__PURE__ */ React113.createElement(
14208
+ "button",
14142
14209
  {
14143
- trigger: { label: /* @__PURE__ */ React113.createElement(IconTaskList, null), title: "Task list", className: editor.isActive("taskList") ? "is-active" : "" },
14144
- keepOpen: true
14145
- },
14146
- ["todo", "working", "blocked", "resolved"].map((status) => {
14147
- const symbols = { todo: "\u2610", working: "\u27F3", blocked: "\u25A0", resolved: "\u2611" };
14148
- const images = { todo: "https://storage.googleapis.com/rufous-com-bucket-1/static/images/todo-blank.svg", working: "https://storage.googleapis.com/rufous-com-bucket-1/static/images/working.svg", blocked: "https://storage.googleapis.com/rufous-com-bucket-1/static/images/blocked.svg", resolved: "https://storage.googleapis.com/rufous-com-bucket-1/static/images/closed.svg" };
14149
- const labels = { todo: "Todo", working: "Working", blocked: "Blocked", resolved: "Resolved" };
14150
- return /* @__PURE__ */ React113.createElement("button", { key: status, className: `dropdown-item task-status-item`, onClick: () => {
14151
- const { state } = editor;
14152
- const { schema } = state;
14153
- const taskItemType = schema.nodes.taskItem;
14154
- const taskListType = schema.nodes.taskList;
14155
- if (!taskItemType || !taskListType) return;
14156
- const statusText = schema.text(labels[status]);
14157
- const newTaskItem = taskItemType.create({ status, checked: false }, schema.nodes.paragraph.create(null, statusText));
14158
- editor.chain().focus().command(({ tr, dispatch, state: cmdState }) => {
14159
- if (!dispatch) return true;
14160
- const { $from } = tr.selection;
14161
- let taskItemDepth = -1;
14162
- for (let d = $from.depth; d > 0; d--) {
14163
- if ($from.node(d).type.name === "taskItem") {
14164
- taskItemDepth = d;
14165
- break;
14166
- }
14167
- }
14168
- const textLen = labels[status].length;
14169
- if (taskItemDepth !== -1) {
14170
- const afterPos = $from.after(taskItemDepth);
14171
- tr.insert(afterPos, newTaskItem);
14172
- const resolvedPos = tr.doc.resolve(afterPos + 2 + textLen);
14173
- tr.setSelection(cmdState.selection.constructor.near(resolvedPos));
14174
- } else {
14175
- const newTaskList = taskListType.create(null, newTaskItem);
14210
+ className: `toolbar-btn ${editor.isActive("taskList") ? "is-active" : ""}`,
14211
+ onClick: () => {
14212
+ if (editor.isActive("taskList")) {
14213
+ editor.chain().focus().liftListItem("taskItem").run();
14214
+ } else {
14215
+ const { state } = editor;
14216
+ const { schema } = state;
14217
+ const taskItemType = schema.nodes.taskItem;
14218
+ const taskListType = schema.nodes.taskList;
14219
+ if (!taskItemType || !taskListType) return;
14220
+ const statusText = schema.text("Todo");
14221
+ const newTaskItem = taskItemType.create({ status: "todo", checked: false }, schema.nodes.paragraph.create(null, statusText));
14222
+ const newTaskList = taskListType.create(null, newTaskItem);
14223
+ editor.chain().focus().command(({ tr, dispatch, state: cmdState }) => {
14224
+ if (!dispatch) return true;
14176
14225
  const pos = tr.selection.from;
14177
14226
  tr.replaceSelectionWith(newTaskList);
14178
- const resolvedPos = tr.doc.resolve(pos + 2 + textLen);
14227
+ const resolvedPos = tr.doc.resolve(pos + 2 + 4);
14179
14228
  tr.setSelection(cmdState.selection.constructor.near(resolvedPos));
14229
+ return true;
14230
+ }).run();
14231
+ }
14232
+ },
14233
+ title: editor.isActive("taskList") ? "Disable Task List" : "Enable Task List"
14234
+ },
14235
+ /* @__PURE__ */ React113.createElement(IconTaskList, null)
14236
+ ), /* @__PURE__ */ React113.createElement(Dropdown, { trigger: { label: "", title: "Task status", className: "todo-arrow-btn" }, keepOpen: true }, ["todo", "working", "blocked", "resolved"].map((status) => {
14237
+ const images = { todo: "https://storage.googleapis.com/rufous-com-bucket-1/static/images/todo-blank.svg", working: "https://storage.googleapis.com/rufous-com-bucket-1/static/images/working.svg", blocked: "https://storage.googleapis.com/rufous-com-bucket-1/static/images/blocked.svg", resolved: "https://storage.googleapis.com/rufous-com-bucket-1/static/images/closed.svg" };
14238
+ const labels = { todo: "Todo", working: "Working", blocked: "Blocked", resolved: "Resolved" };
14239
+ return /* @__PURE__ */ React113.createElement("button", { key: status, className: "dropdown-item task-status-item", onClick: () => {
14240
+ const { state } = editor;
14241
+ const { schema } = state;
14242
+ const taskItemType = schema.nodes.taskItem;
14243
+ const taskListType = schema.nodes.taskList;
14244
+ if (!taskItemType || !taskListType) return;
14245
+ const statusText = schema.text(labels[status]);
14246
+ const newTaskItem = taskItemType.create({ status, checked: false }, schema.nodes.paragraph.create(null, statusText));
14247
+ editor.chain().focus().command(({ tr, dispatch, state: cmdState }) => {
14248
+ if (!dispatch) return true;
14249
+ const { $from } = tr.selection;
14250
+ let taskItemDepth = -1;
14251
+ for (let d = $from.depth; d > 0; d--) {
14252
+ if ($from.node(d).type.name === "taskItem") {
14253
+ taskItemDepth = d;
14254
+ break;
14180
14255
  }
14181
- return true;
14182
- }).run();
14183
- } }, /* @__PURE__ */ React113.createElement("span", { className: `task-icon task-${status}` }, /* @__PURE__ */ React113.createElement("img", { src: images[status], alt: status })), " ", labels[status]);
14184
- })
14185
- )), onClose && /* @__PURE__ */ React113.createElement("div", { className: "toolbar-row-right" }, /* @__PURE__ */ React113.createElement(
14256
+ }
14257
+ const textLen = labels[status].length;
14258
+ if (taskItemDepth !== -1) {
14259
+ const afterPos = $from.after(taskItemDepth);
14260
+ tr.insert(afterPos, newTaskItem);
14261
+ const resolvedPos = tr.doc.resolve(afterPos + 2 + textLen);
14262
+ tr.setSelection(cmdState.selection.constructor.near(resolvedPos));
14263
+ } else {
14264
+ const newTaskList = taskListType.create(null, newTaskItem);
14265
+ const pos = tr.selection.from;
14266
+ tr.replaceSelectionWith(newTaskList);
14267
+ const resolvedPos = tr.doc.resolve(pos + 2 + textLen);
14268
+ tr.setSelection(cmdState.selection.constructor.near(resolvedPos));
14269
+ }
14270
+ return true;
14271
+ }).run();
14272
+ } }, /* @__PURE__ */ React113.createElement("span", { className: `task-icon task-${status}` }, /* @__PURE__ */ React113.createElement("img", { src: images[status], alt: status })), " ", labels[status]);
14273
+ })))), onClose && /* @__PURE__ */ React113.createElement("div", { className: "toolbar-row-right" }, /* @__PURE__ */ React113.createElement(
14186
14274
  "button",
14187
14275
  {
14188
14276
  className: "toolbar-btn btn-cross",
@@ -14744,9 +14832,13 @@ var RufousTextEditor = ({
14744
14832
  onImageUpload,
14745
14833
  onClose,
14746
14834
  mentions,
14835
+ height,
14836
+ resizable = false,
14747
14837
  className,
14748
- style
14838
+ style,
14839
+ sx
14749
14840
  }) => {
14841
+ const sxClass = useSx(sx);
14750
14842
  const mentionSuggestion = useMemo4(() => createMentionSuggestion(mentions), [mentions]);
14751
14843
  const onChangeRef = useRef30(onChange);
14752
14844
  const onBlurRef = useRef30(onBlur);
@@ -14869,8 +14961,31 @@ var RufousTextEditor = ({
14869
14961
  if (!editor) return;
14870
14962
  const attrs = editor.getAttributes("link");
14871
14963
  const previousUrl = attrs.href || "";
14872
- const { from, to } = editor.state.selection;
14873
- const selectedText = editor.state.doc.textBetween(from, to, "");
14964
+ let { from, to } = editor.state.selection;
14965
+ let selectedText = editor.state.doc.textBetween(from, to, "");
14966
+ if (!selectedText && editor.isActive("link")) {
14967
+ const $pos = editor.state.selection.$from;
14968
+ const linkMark = editor.state.schema.marks.link;
14969
+ const parent = $pos.parent;
14970
+ let offset2 = $pos.parentOffset;
14971
+ let start = 0, end = 0, found2 = false;
14972
+ parent.forEach((child, childOffset) => {
14973
+ if (child.isText && child.marks.some((m) => m.type === linkMark)) {
14974
+ const childStart = childOffset;
14975
+ const childEnd = childOffset + child.nodeSize;
14976
+ if (childStart <= offset2 && childEnd >= offset2) {
14977
+ start = $pos.start() + childStart;
14978
+ end = $pos.start() + childEnd;
14979
+ found2 = true;
14980
+ }
14981
+ }
14982
+ });
14983
+ if (found2) {
14984
+ from = start;
14985
+ to = end;
14986
+ selectedText = editor.state.doc.textBetween(from, to, "");
14987
+ }
14988
+ }
14874
14989
  setLinkUrl(previousUrl);
14875
14990
  setLinkText(selectedText || previousUrl);
14876
14991
  setLinkClassName(attrs.class && attrs.class !== "editor-link" ? attrs.class : "");
@@ -14951,201 +15066,214 @@ var RufousTextEditor = ({
14951
15066
  }
14952
15067
  }, [editor]);
14953
15068
  const providerValue = useMemo4(() => ({ editor }), [editor]);
14954
- return /* @__PURE__ */ React116.createElement("div", { className: `rf-rte-wrapper editor-wrapper ${className || ""}`, style }, /* @__PURE__ */ React116.createElement(EditorContext.Provider, { value: providerValue }, /* @__PURE__ */ React116.createElement(
14955
- Toolbar_default,
14956
- {
14957
- editor,
14958
- setLink,
14959
- onAICommand,
14960
- onTranslate,
14961
- onSpeechToText,
14962
- onTextToSpeech,
14963
- onImageUpload,
14964
- onClose
14965
- }
14966
- ), /* @__PURE__ */ React116.createElement(EditorContent, { editor, className: "editor-content-wrapper" }), /* @__PURE__ */ React116.createElement(ImageToolbar_default, { editor }), /* @__PURE__ */ React116.createElement(VideoToolbar_default, { editor }), editor && /* @__PURE__ */ React116.createElement(
14967
- BubbleMenu,
15069
+ return /* @__PURE__ */ React116.createElement(
15070
+ "div",
14968
15071
  {
14969
- editor,
14970
- className: "bubble-menu",
14971
- shouldShow: ({ editor: e }) => {
14972
- if (!e || e.isDestroyed) return false;
14973
- try {
14974
- const { selection } = e.state;
14975
- if (selection?.node?.type.name === "image") return false;
14976
- if (selection?.node?.type.name === "youtube") return false;
14977
- if (selection?.node?.type.name === "video") return false;
14978
- return !selection.empty;
14979
- } catch {
14980
- return false;
14981
- }
15072
+ className: `rf-rte-wrapper editor-wrapper ${resizable ? "rf-rte-resizable" : ""} ${sxClass} ${className || ""}`,
15073
+ style: {
15074
+ ...style,
15075
+ ...height ? { height: typeof height === "number" ? `${height}px` : height } : {}
14982
15076
  }
14983
15077
  },
14984
- /* @__PURE__ */ React116.createElement(
14985
- "button",
15078
+ /* @__PURE__ */ React116.createElement(EditorContext.Provider, { value: providerValue }, /* @__PURE__ */ React116.createElement(
15079
+ Toolbar_default,
14986
15080
  {
14987
- onClick: () => editor?.chain().focus().toggleBold().run(),
14988
- className: editor?.isActive("bold") ? "is-active" : ""
14989
- },
14990
- /* @__PURE__ */ React116.createElement("strong", null, "B")
14991
- ),
14992
- /* @__PURE__ */ React116.createElement(
14993
- "button",
15081
+ editor,
15082
+ setLink,
15083
+ onAICommand,
15084
+ onTranslate,
15085
+ onSpeechToText,
15086
+ onTextToSpeech,
15087
+ onImageUpload,
15088
+ onClose
15089
+ }
15090
+ ), /* @__PURE__ */ React116.createElement(EditorContent, { editor, className: "editor-content-wrapper" }), /* @__PURE__ */ React116.createElement(ImageToolbar_default, { editor }), /* @__PURE__ */ React116.createElement(VideoToolbar_default, { editor }), editor && /* @__PURE__ */ React116.createElement(
15091
+ BubbleMenu,
14994
15092
  {
14995
- onClick: () => editor?.chain().focus().toggleItalic().run(),
14996
- className: editor?.isActive("italic") ? "is-active" : ""
15093
+ editor,
15094
+ className: "bubble-menu",
15095
+ shouldShow: ({ editor: e }) => {
15096
+ if (!e || e.isDestroyed) return false;
15097
+ try {
15098
+ const { selection } = e.state;
15099
+ if (selection?.node?.type.name === "image") return false;
15100
+ if (selection?.node?.type.name === "youtube") return false;
15101
+ if (selection?.node?.type.name === "video") return false;
15102
+ return !selection.empty;
15103
+ } catch {
15104
+ return false;
15105
+ }
15106
+ }
14997
15107
  },
14998
- /* @__PURE__ */ React116.createElement("em", null, "I")
14999
- ),
15000
- /* @__PURE__ */ React116.createElement(
15001
- "button",
15108
+ /* @__PURE__ */ React116.createElement(
15109
+ "button",
15110
+ {
15111
+ onClick: () => editor?.chain().focus().toggleBold().run(),
15112
+ className: editor?.isActive("bold") ? "is-active" : ""
15113
+ },
15114
+ /* @__PURE__ */ React116.createElement("strong", null, "B")
15115
+ ),
15116
+ /* @__PURE__ */ React116.createElement(
15117
+ "button",
15118
+ {
15119
+ onClick: () => editor?.chain().focus().toggleItalic().run(),
15120
+ className: editor?.isActive("italic") ? "is-active" : ""
15121
+ },
15122
+ /* @__PURE__ */ React116.createElement("em", null, "I")
15123
+ ),
15124
+ /* @__PURE__ */ React116.createElement(
15125
+ "button",
15126
+ {
15127
+ onClick: () => editor?.chain().focus().toggleStrike().run(),
15128
+ className: editor?.isActive("strike") ? "is-active" : ""
15129
+ },
15130
+ /* @__PURE__ */ React116.createElement("s", null, "S")
15131
+ ),
15132
+ /* @__PURE__ */ React116.createElement(
15133
+ "button",
15134
+ {
15135
+ onClick: () => editor?.chain().focus().toggleCode().run(),
15136
+ className: editor?.isActive("code") ? "is-active" : ""
15137
+ },
15138
+ "</>"
15139
+ ),
15140
+ /* @__PURE__ */ React116.createElement(
15141
+ "button",
15142
+ {
15143
+ onClick: setLink,
15144
+ className: editor?.isActive("link") ? "is-active" : ""
15145
+ },
15146
+ "\u{1F517}"
15147
+ )
15148
+ ), editor && /* @__PURE__ */ React116.createElement(
15149
+ FloatingMenu,
15002
15150
  {
15003
- onClick: () => editor?.chain().focus().toggleStrike().run(),
15004
- className: editor?.isActive("strike") ? "is-active" : ""
15151
+ editor,
15152
+ className: "floating-menu",
15153
+ shouldShow: ({ editor: e }) => {
15154
+ if (!e || e.isDestroyed) return false;
15155
+ try {
15156
+ const { selection } = e.state;
15157
+ return selection.empty && e.state.doc.textContent.length === 0;
15158
+ } catch {
15159
+ return false;
15160
+ }
15161
+ }
15005
15162
  },
15006
- /* @__PURE__ */ React116.createElement("s", null, "S")
15007
- ),
15008
- /* @__PURE__ */ React116.createElement(
15009
- "button",
15163
+ /* @__PURE__ */ React116.createElement(
15164
+ "button",
15165
+ {
15166
+ onClick: () => editor?.chain().focus().toggleHeading({ level: 1 }).run(),
15167
+ className: editor?.isActive("heading", { level: 1 }) ? "is-active" : ""
15168
+ },
15169
+ "H1"
15170
+ ),
15171
+ /* @__PURE__ */ React116.createElement(
15172
+ "button",
15173
+ {
15174
+ onClick: () => editor?.chain().focus().toggleHeading({ level: 2 }).run(),
15175
+ className: editor?.isActive("heading", { level: 2 }) ? "is-active" : ""
15176
+ },
15177
+ "H2"
15178
+ ),
15179
+ /* @__PURE__ */ React116.createElement(
15180
+ "button",
15181
+ {
15182
+ onClick: () => editor?.chain().focus().toggleBulletList().run(),
15183
+ className: editor?.isActive("bulletList") ? "is-active" : ""
15184
+ },
15185
+ "\u2022 List"
15186
+ ),
15187
+ /* @__PURE__ */ React116.createElement(
15188
+ "button",
15189
+ {
15190
+ onClick: () => editor?.chain().focus().toggleOrderedList().run(),
15191
+ className: editor?.isActive("orderedList") ? "is-active" : ""
15192
+ },
15193
+ "1. List"
15194
+ ),
15195
+ /* @__PURE__ */ React116.createElement(
15196
+ "button",
15197
+ {
15198
+ onClick: () => editor?.chain().focus().toggleBlockquote().run(),
15199
+ className: editor?.isActive("blockquote") ? "is-active" : ""
15200
+ },
15201
+ "\u201C Quote"
15202
+ )
15203
+ ), /* @__PURE__ */ React116.createElement("div", { className: "status-bar" }, /* @__PURE__ */ React116.createElement("div", { className: "status-bar-left" }, /* @__PURE__ */ React116.createElement(
15204
+ "select",
15010
15205
  {
15011
- onClick: () => editor?.chain().focus().toggleCode().run(),
15012
- className: editor?.isActive("code") ? "is-active" : ""
15206
+ value: saveFormat,
15207
+ onChange: (e) => setSaveFormat(e.target.value),
15208
+ className: "format-select"
15013
15209
  },
15014
- "</>"
15015
- ),
15016
- /* @__PURE__ */ React116.createElement(
15017
- "button",
15210
+ /* @__PURE__ */ React116.createElement("option", { value: "html" }, "HTML"),
15211
+ /* @__PURE__ */ React116.createElement("option", { value: "json" }, "JSON")
15212
+ ), 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("button", { onClick: handleClear, className: "status-btn clear-btn" }, "Clear")), /* @__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 && /* @__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(
15213
+ "input",
15018
15214
  {
15019
- onClick: setLink,
15020
- className: editor?.isActive("link") ? "is-active" : ""
15021
- },
15022
- "\u{1F517}"
15023
- )
15024
- ), editor && /* @__PURE__ */ React116.createElement(
15025
- FloatingMenu,
15026
- {
15027
- editor,
15028
- className: "floating-menu",
15029
- shouldShow: ({ editor: e }) => {
15030
- if (!e || e.isDestroyed) return false;
15031
- try {
15032
- const { selection } = e.state;
15033
- return selection.empty && e.state.doc.textContent.length === 0;
15034
- } catch {
15035
- return false;
15036
- }
15215
+ type: "url",
15216
+ className: "link-modal-input",
15217
+ value: linkUrl,
15218
+ onChange: (e) => setLinkUrl(e.target.value),
15219
+ onKeyDown: (e) => {
15220
+ if (e.key === "Enter") handleLinkSubmit();
15221
+ },
15222
+ placeholder: "https://example.com",
15223
+ autoFocus: true
15037
15224
  }
15038
- },
15039
- /* @__PURE__ */ React116.createElement(
15040
- "button",
15041
- {
15042
- onClick: () => editor?.chain().focus().toggleHeading({ level: 1 }).run(),
15043
- className: editor?.isActive("heading", { level: 1 }) ? "is-active" : ""
15044
- },
15045
- "H1"
15046
- ),
15047
- /* @__PURE__ */ React116.createElement(
15048
- "button",
15225
+ )), /* @__PURE__ */ React116.createElement("div", { className: "link-modal-field" }, /* @__PURE__ */ React116.createElement("label", { className: "link-modal-label" }, "Text"), /* @__PURE__ */ React116.createElement(
15226
+ "input",
15049
15227
  {
15050
- onClick: () => editor?.chain().focus().toggleHeading({ level: 2 }).run(),
15051
- className: editor?.isActive("heading", { level: 2 }) ? "is-active" : ""
15052
- },
15053
- "H2"
15054
- ),
15055
- /* @__PURE__ */ React116.createElement(
15056
- "button",
15228
+ type: "text",
15229
+ className: "link-modal-input",
15230
+ value: linkText,
15231
+ onChange: (e) => setLinkText(e.target.value),
15232
+ onKeyDown: (e) => {
15233
+ if (e.key === "Enter") handleLinkSubmit();
15234
+ },
15235
+ placeholder: "Link text"
15236
+ }
15237
+ )), /* @__PURE__ */ React116.createElement("div", { className: "link-modal-field" }, /* @__PURE__ */ React116.createElement("label", { className: "link-modal-label" }, "Class name"), /* @__PURE__ */ React116.createElement(
15238
+ "input",
15057
15239
  {
15058
- onClick: () => editor?.chain().focus().toggleBulletList().run(),
15059
- className: editor?.isActive("bulletList") ? "is-active" : ""
15060
- },
15061
- "\u2022 List"
15062
- ),
15063
- /* @__PURE__ */ React116.createElement(
15064
- "button",
15240
+ type: "text",
15241
+ className: "link-modal-input",
15242
+ value: linkClassName,
15243
+ onChange: (e) => setLinkClassName(e.target.value),
15244
+ onKeyDown: (e) => {
15245
+ if (e.key === "Enter") handleLinkSubmit();
15246
+ },
15247
+ placeholder: ""
15248
+ }
15249
+ )), /* @__PURE__ */ React116.createElement("div", { className: "link-modal-checkboxes" }, /* @__PURE__ */ React116.createElement("label", { className: "link-modal-checkbox" }, /* @__PURE__ */ React116.createElement(
15250
+ "input",
15065
15251
  {
15066
- onClick: () => editor?.chain().focus().toggleOrderedList().run(),
15067
- className: editor?.isActive("orderedList") ? "is-active" : ""
15068
- },
15069
- "1. List"
15070
- ),
15071
- /* @__PURE__ */ React116.createElement(
15072
- "button",
15252
+ type: "checkbox",
15253
+ checked: linkNewTab,
15254
+ onChange: (e) => setLinkNewTab(e.target.checked)
15255
+ }
15256
+ ), "Open in new tab"), /* @__PURE__ */ React116.createElement("label", { className: "link-modal-checkbox" }, /* @__PURE__ */ React116.createElement(
15257
+ "input",
15073
15258
  {
15074
- onClick: () => editor?.chain().focus().toggleBlockquote().run(),
15075
- className: editor?.isActive("blockquote") ? "is-active" : ""
15076
- },
15077
- "\u201C Quote"
15078
- )
15079
- ), /* @__PURE__ */ React116.createElement("div", { className: "status-bar" }, /* @__PURE__ */ React116.createElement("div", { className: "status-bar-left" }, /* @__PURE__ */ React116.createElement(
15080
- "select",
15081
- {
15082
- value: saveFormat,
15083
- onChange: (e) => setSaveFormat(e.target.value),
15084
- className: "format-select"
15085
- },
15086
- /* @__PURE__ */ React116.createElement("option", { value: "html" }, "HTML"),
15087
- /* @__PURE__ */ React116.createElement("option", { value: "json" }, "JSON")
15088
- ), 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("button", { onClick: handleClear, className: "status-btn clear-btn" }, "Clear")), /* @__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 && /* @__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(
15089
- "input",
15090
- {
15091
- type: "url",
15092
- className: "link-modal-input",
15093
- value: linkUrl,
15094
- onChange: (e) => setLinkUrl(e.target.value),
15095
- onKeyDown: (e) => {
15096
- if (e.key === "Enter") handleLinkSubmit();
15097
- },
15098
- placeholder: "https://example.com",
15099
- autoFocus: true
15100
- }
15101
- )), /* @__PURE__ */ React116.createElement("div", { className: "link-modal-field" }, /* @__PURE__ */ React116.createElement("label", { className: "link-modal-label" }, "Text"), /* @__PURE__ */ React116.createElement(
15102
- "input",
15103
- {
15104
- type: "text",
15105
- className: "link-modal-input",
15106
- value: linkText,
15107
- onChange: (e) => setLinkText(e.target.value),
15108
- onKeyDown: (e) => {
15109
- if (e.key === "Enter") handleLinkSubmit();
15110
- },
15111
- placeholder: "Link text"
15112
- }
15113
- )), /* @__PURE__ */ React116.createElement("div", { className: "link-modal-field" }, /* @__PURE__ */ React116.createElement("label", { className: "link-modal-label" }, "Class name"), /* @__PURE__ */ React116.createElement(
15114
- "input",
15115
- {
15116
- type: "text",
15117
- className: "link-modal-input",
15118
- value: linkClassName,
15119
- onChange: (e) => setLinkClassName(e.target.value),
15120
- onKeyDown: (e) => {
15121
- if (e.key === "Enter") handleLinkSubmit();
15122
- },
15123
- placeholder: ""
15124
- }
15125
- )), /* @__PURE__ */ React116.createElement("div", { className: "link-modal-checkboxes" }, /* @__PURE__ */ React116.createElement("label", { className: "link-modal-checkbox" }, /* @__PURE__ */ React116.createElement(
15126
- "input",
15127
- {
15128
- type: "checkbox",
15129
- checked: linkNewTab,
15130
- onChange: (e) => setLinkNewTab(e.target.checked)
15131
- }
15132
- ), "Open in new tab"), /* @__PURE__ */ React116.createElement("label", { className: "link-modal-checkbox" }, /* @__PURE__ */ React116.createElement(
15133
- "input",
15259
+ type: "checkbox",
15260
+ checked: linkNoFollow,
15261
+ onChange: (e) => setLinkNoFollow(e.target.checked)
15262
+ }
15263
+ ), "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")))))
15264
+ );
15265
+ };
15266
+ var RufousTextContent = ({ content, className, style, sx }) => {
15267
+ const sxClass = useSx(sx);
15268
+ return /* @__PURE__ */ React116.createElement(
15269
+ "div",
15134
15270
  {
15135
- type: "checkbox",
15136
- checked: linkNoFollow,
15137
- onChange: (e) => setLinkNoFollow(e.target.checked)
15271
+ className: `rf-rte-content ${sxClass} ${className || ""}`,
15272
+ style,
15273
+ dangerouslySetInnerHTML: { __html: content }
15138
15274
  }
15139
- ), "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"))))));
15275
+ );
15140
15276
  };
15141
- var RufousTextContent = ({ content, className, style }) => /* @__PURE__ */ React116.createElement(
15142
- "div",
15143
- {
15144
- className: `rf-rte-content ${className || ""}`,
15145
- style,
15146
- dangerouslySetInnerHTML: { __html: content }
15147
- }
15148
- );
15149
15277
  export {
15150
15278
  APP_THEMES,
15151
15279
  Accordion,