@overlap/rte 1.0.8 → 1.0.10

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/index.js CHANGED
@@ -87,10 +87,45 @@ const Icon = ({ icon, width = 18, height = 18, className }) => {
87
87
  const Dropdown = ({ icon, label, options, onSelect, currentValue, disabled, showCustomColorInput, }) => {
88
88
  const [isOpen, setIsOpen] = React.useState(false);
89
89
  const [customColor, setCustomColor] = React.useState("#000000");
90
+ const [menuPos, setMenuPos] = React.useState({ top: 0, left: 0 });
90
91
  const dropdownRef = React.useRef(null);
92
+ const menuRef = React.useRef(null);
93
+ const buttonRef = React.useRef(null);
94
+ const updateMenuPosition = React.useCallback(() => {
95
+ if (!buttonRef.current)
96
+ return;
97
+ const rect = buttonRef.current.getBoundingClientRect();
98
+ const pad = 8;
99
+ let top = rect.bottom + 4;
100
+ let left = rect.left;
101
+ const menuEl = menuRef.current;
102
+ if (menuEl) {
103
+ const menuW = menuEl.offsetWidth;
104
+ const menuH = menuEl.offsetHeight;
105
+ if (left + menuW > window.innerWidth - pad) {
106
+ left = window.innerWidth - menuW - pad;
107
+ }
108
+ if (left < pad)
109
+ left = pad;
110
+ if (top + menuH > window.innerHeight - pad) {
111
+ top = rect.top - menuH - 4;
112
+ }
113
+ if (top < pad)
114
+ top = pad;
115
+ }
116
+ setMenuPos({ top, left });
117
+ }, []);
118
+ React.useEffect(() => {
119
+ if (!isOpen)
120
+ return;
121
+ updateMenuPosition();
122
+ requestAnimationFrame(updateMenuPosition);
123
+ }, [isOpen, updateMenuPosition]);
91
124
  React.useEffect(() => {
92
125
  const handleClickOutside = (event) => {
93
- if (dropdownRef.current && !dropdownRef.current.contains(event.target)) {
126
+ const target = event.target;
127
+ if (dropdownRef.current && !dropdownRef.current.contains(target) &&
128
+ (!menuRef.current || !menuRef.current.contains(target))) {
94
129
  setIsOpen(false);
95
130
  }
96
131
  };
@@ -106,7 +141,6 @@ const Dropdown = ({ icon, label, options, onSelect, currentValue, disabled, show
106
141
  setIsOpen(false);
107
142
  };
108
143
  const currentOption = options.find(opt => opt.value === currentValue);
109
- // Close on Escape key
110
144
  React.useEffect(() => {
111
145
  if (!isOpen)
112
146
  return;
@@ -119,21 +153,26 @@ const Dropdown = ({ icon, label, options, onSelect, currentValue, disabled, show
119
153
  document.addEventListener("keydown", handleKeyDown);
120
154
  return () => document.removeEventListener("keydown", handleKeyDown);
121
155
  }, [isOpen]);
122
- return (jsxRuntime.jsxs("div", { className: "rte-dropdown", ref: dropdownRef, onMouseDown: (e) => e.preventDefault(), children: [jsxRuntime.jsxs("button", { type: "button", onClick: () => !disabled && setIsOpen(!isOpen), disabled: disabled, className: `rte-toolbar-button rte-dropdown-button ${currentOption ? 'rte-dropdown-button-has-value' : ''}`, title: label, "aria-label": label, "aria-expanded": isOpen, "aria-haspopup": "listbox", children: [jsxRuntime.jsx(Icon, { icon: icon, width: 18, height: 18 }), currentOption && (jsxRuntime.jsx("span", { className: "rte-dropdown-value", children: currentOption.label }))] }), isOpen && (jsxRuntime.jsxs("div", { className: "rte-dropdown-menu", role: "listbox", "aria-label": label, children: [options.map((option) => (jsxRuntime.jsxs("button", { type: "button", role: "option", "aria-selected": currentValue === option.value, className: `rte-dropdown-item ${currentValue === option.value ? 'rte-dropdown-item-active' : ''}`, onClick: () => handleSelect(option.value), children: [option.color && (jsxRuntime.jsx("span", { className: `rte-dropdown-color-preview ${currentValue === option.value ? 'active' : ''}`, style: { backgroundColor: option.color } })), option.preview && !option.headingPreview && (jsxRuntime.jsx("span", { className: "rte-dropdown-fontsize-preview", style: { fontSize: `${option.preview}px` }, children: "Aa" })), option.headingPreview && (jsxRuntime.jsx("span", { className: `rte-dropdown-heading-preview ${option.headingPreview}`, children: option.headingPreview === 'p' ? 'Normal' : option.headingPreview.toUpperCase() })), option.icon && jsxRuntime.jsx(Icon, { icon: option.icon, width: 16, height: 16 }), jsxRuntime.jsx("span", { style: { flex: 1, fontWeight: currentValue === option.value ? 600 : 400 }, children: option.label })] }, option.value))), showCustomColorInput && (jsxRuntime.jsxs("div", { className: "rte-color-custom-input", onMouseDown: (e) => e.stopPropagation(), children: [jsxRuntime.jsx("input", { type: "color", value: customColor, onChange: (e) => setCustomColor(e.target.value), title: "Pick a color" }), jsxRuntime.jsx("input", { type: "text", value: customColor, onChange: (e) => {
123
- const v = e.target.value;
124
- setCustomColor(v);
125
- }, placeholder: "#000000", maxLength: 7, onKeyDown: (e) => {
126
- if (e.key === "Enter") {
127
- e.preventDefault();
128
- if (/^#[0-9a-fA-F]{3,6}$/.test(customColor)) {
129
- handleSelect(customColor);
130
- }
131
- }
132
- } }), jsxRuntime.jsx("button", { type: "button", className: "rte-color-custom-apply", onClick: () => {
133
- if (/^#[0-9a-fA-F]{3,6}$/.test(customColor)) {
134
- handleSelect(customColor);
135
- }
136
- }, children: "Apply" })] }))] }))] }));
156
+ const menuContent = isOpen ? (jsxRuntime.jsxs("div", { ref: menuRef, className: "rte-dropdown-menu", role: "listbox", "aria-label": label, style: {
157
+ position: 'fixed',
158
+ top: menuPos.top,
159
+ left: menuPos.left,
160
+ }, onMouseDown: (e) => e.preventDefault(), children: [options.map((option) => (jsxRuntime.jsxs("button", { type: "button", role: "option", "aria-selected": currentValue === option.value, className: `rte-dropdown-item ${currentValue === option.value ? 'rte-dropdown-item-active' : ''}`, onClick: () => handleSelect(option.value), children: [option.color && (jsxRuntime.jsx("span", { className: `rte-dropdown-color-preview ${currentValue === option.value ? 'active' : ''}`, style: { backgroundColor: option.color } })), option.preview && !option.headingPreview && (jsxRuntime.jsx("span", { className: "rte-dropdown-fontsize-preview", style: { fontSize: `${option.preview}px` }, children: "Aa" })), option.headingPreview && (jsxRuntime.jsx("span", { className: `rte-dropdown-heading-preview ${option.headingPreview}`, children: option.headingPreview === 'p' ? 'Normal' : option.headingPreview.toUpperCase() })), option.icon && jsxRuntime.jsx(Icon, { icon: option.icon, width: 16, height: 16 }), jsxRuntime.jsx("span", { style: { flex: 1, fontWeight: currentValue === option.value ? 600 : 400 }, children: option.label })] }, option.value))), showCustomColorInput && (jsxRuntime.jsxs("div", { className: "rte-color-custom-input", onMouseDown: (e) => e.stopPropagation(), children: [jsxRuntime.jsx("input", { type: "color", value: customColor, onChange: (e) => setCustomColor(e.target.value), title: "Pick a color" }), jsxRuntime.jsx("input", { type: "text", value: customColor, onChange: (e) => {
161
+ const v = e.target.value;
162
+ setCustomColor(v);
163
+ }, placeholder: "#000000", maxLength: 7, onKeyDown: (e) => {
164
+ if (e.key === "Enter") {
165
+ e.preventDefault();
166
+ if (/^#[0-9a-fA-F]{3,6}$/.test(customColor)) {
167
+ handleSelect(customColor);
168
+ }
169
+ }
170
+ } }), jsxRuntime.jsx("button", { type: "button", className: "rte-color-custom-apply", onClick: () => {
171
+ if (/^#[0-9a-fA-F]{3,6}$/.test(customColor)) {
172
+ handleSelect(customColor);
173
+ }
174
+ }, children: "Apply" })] }))] })) : null;
175
+ return (jsxRuntime.jsxs("div", { className: "rte-dropdown", ref: dropdownRef, onMouseDown: (e) => e.preventDefault(), children: [jsxRuntime.jsxs("button", { ref: buttonRef, type: "button", onClick: () => !disabled && setIsOpen(!isOpen), disabled: disabled, className: `rte-toolbar-button rte-dropdown-button ${currentOption ? 'rte-dropdown-button-has-value' : ''}`, title: label, "aria-label": label, "aria-expanded": isOpen, "aria-haspopup": "listbox", children: [jsxRuntime.jsx(Icon, { icon: icon, width: 18, height: 18 }), currentOption && (jsxRuntime.jsx("span", { className: "rte-dropdown-value", children: currentOption.label }))] }), menuContent && reactDom.createPortal(menuContent, document.body)] }));
137
176
  };
138
177
 
139
178
  /**
@@ -808,7 +847,7 @@ const ALLOWED_CONTENT_TAGS = new Set([
808
847
  "ul", "ol", "li", "a", "strong", "em", "u", "s", "del",
809
848
  "sub", "sup", "code", "pre", "blockquote", "br", "hr",
810
849
  "img", "table", "thead", "tbody", "tr", "th", "td",
811
- "b", "i", "strike",
850
+ "b", "i", "strike", "font",
812
851
  ]);
813
852
  /** Checks if an attribute key is safe to set on a DOM element. */
814
853
  function isSafeAttribute(key) {
@@ -1016,6 +1055,7 @@ function domToContent(element) {
1016
1055
  "sub",
1017
1056
  "sup",
1018
1057
  "code",
1058
+ "font",
1019
1059
  ].includes(tagName)) {
1020
1060
  const children = [];
1021
1061
  Array.from(el.childNodes).forEach((child) => {
@@ -1105,6 +1145,46 @@ function domToContent(element) {
1105
1145
  });
1106
1146
  }
1107
1147
  }
1148
+ // <font> from execCommand('foreColor') or pasted HTML
1149
+ if (tagName === "font") {
1150
+ const fontAttrs = {};
1151
+ const colorAttr = el.getAttribute("color");
1152
+ if (colorAttr)
1153
+ fontAttrs.color = colorAttr;
1154
+ const sizeAttr = el.getAttribute("size");
1155
+ if (sizeAttr) {
1156
+ const sizeMap = {
1157
+ "1": "10px", "2": "13px", "3": "16px", "4": "18px",
1158
+ "5": "24px", "6": "32px", "7": "48px",
1159
+ };
1160
+ const mapped = sizeMap[sizeAttr];
1161
+ if (mapped)
1162
+ fontAttrs.fontSize = mapped;
1163
+ }
1164
+ const style = el.getAttribute("style") || "";
1165
+ if (style) {
1166
+ style.split(";").forEach((rule) => {
1167
+ const [key, value] = rule
1168
+ .split(":")
1169
+ .map((s) => s.trim());
1170
+ if (key && value) {
1171
+ if (key === "font-size")
1172
+ fontAttrs.fontSize = value;
1173
+ else if (key === "color")
1174
+ fontAttrs.color = value;
1175
+ else if (key === "background-color")
1176
+ fontAttrs.backgroundColor = value;
1177
+ }
1178
+ });
1179
+ }
1180
+ return {
1181
+ type: "span",
1182
+ children: children.length > 0 ? children : undefined,
1183
+ attributes: Object.keys(fontAttrs).length > 0
1184
+ ? fontAttrs
1185
+ : undefined,
1186
+ };
1187
+ }
1108
1188
  // Map tag names to semantic types
1109
1189
  const type = tagName === "strong" || tagName === "b"
1110
1190
  ? "bold"
@@ -2123,6 +2203,61 @@ function useEditorEvents({ editorRef, historyRef, isUpdatingRef, mountedRef, not
2123
2203
  }, 0);
2124
2204
  return;
2125
2205
  }
2206
+ // Exit code block: Enter on empty last line escapes <pre>
2207
+ if (e.key === "Enter" &&
2208
+ !e.shiftKey &&
2209
+ !isModifierPressed) {
2210
+ const sel = window.getSelection();
2211
+ if (sel && sel.rangeCount > 0 && sel.isCollapsed) {
2212
+ const range = sel.getRangeAt(0);
2213
+ const node = range.startContainer;
2214
+ const pre = (node instanceof HTMLElement
2215
+ ? node
2216
+ : node.parentElement)?.closest("pre");
2217
+ if (pre && pre.lastChild) {
2218
+ const lastChild = pre.lastChild;
2219
+ const cursorInPre = node === pre &&
2220
+ range.startOffset === pre.childNodes.length;
2221
+ const cursorAtEndOfLastText = node.nodeType === Node.TEXT_NODE &&
2222
+ node === lastChild &&
2223
+ range.startOffset ===
2224
+ (node.textContent?.length ?? 0);
2225
+ const isAtEnd = cursorInPre || cursorAtEndOfLastText;
2226
+ const lastIsBr = lastChild instanceof HTMLElement &&
2227
+ lastChild.tagName === "BR";
2228
+ const endsWithNewline = node.nodeType === Node.TEXT_NODE &&
2229
+ (node.textContent || "").endsWith("\n");
2230
+ if (isAtEnd && (lastIsBr || endsWithNewline)) {
2231
+ e.preventDefault();
2232
+ if (lastIsBr) {
2233
+ pre.removeChild(lastChild);
2234
+ }
2235
+ else if (node.nodeType === Node.TEXT_NODE &&
2236
+ node.textContent) {
2237
+ node.textContent =
2238
+ node.textContent.replace(/\n$/, "");
2239
+ }
2240
+ if (!pre.textContent &&
2241
+ !pre.querySelector("br")) {
2242
+ pre.appendChild(document.createElement("br"));
2243
+ }
2244
+ const p = document.createElement("p");
2245
+ p.appendChild(document.createElement("br"));
2246
+ pre.parentNode?.insertBefore(p, pre.nextSibling);
2247
+ const newRange = document.createRange();
2248
+ newRange.setStart(p, 0);
2249
+ newRange.collapse(true);
2250
+ sel.removeAllRanges();
2251
+ sel.addRange(newRange);
2252
+ const content = domToContent(editor);
2253
+ const serializedSel = serializeSelection(editor);
2254
+ historyRef.current.push(content, serializedSel);
2255
+ notifyChange(content);
2256
+ return;
2257
+ }
2258
+ }
2259
+ }
2260
+ }
2126
2261
  // Auto-link: convert URLs to <a> tags on space/enter
2127
2262
  if (!isModifierPressed && (e.key === " " || e.key === "Enter")) {
2128
2263
  handleAutoLink(editor, e);
@@ -4017,7 +4152,7 @@ function createAdvancedLinkPlugin(options = {}) {
4017
4152
  /** Pre-built link plugin with just target enabled (no custom fields). */
4018
4153
  const advancedLinkPlugin = createAdvancedLinkPlugin();
4019
4154
 
4020
- const InsertTableDialog = ({ onInsert, onClose, }) => {
4155
+ const InsertTableDialog = ({ onInsert, onClose, anchorRect, }) => {
4021
4156
  const [rows, setRows] = React.useState(3);
4022
4157
  const [cols, setCols] = React.useState(3);
4023
4158
  const dialogRef = React.useRef(null);
@@ -4031,7 +4166,25 @@ const InsertTableDialog = ({ onInsert, onClose, }) => {
4031
4166
  document.addEventListener("mousedown", handler);
4032
4167
  return () => document.removeEventListener("mousedown", handler);
4033
4168
  }, [onClose]);
4034
- return (jsxRuntime.jsxs("div", { className: "rte-table-insert-dialog", ref: dialogRef, children: [jsxRuntime.jsx("div", { className: "rte-table-insert-title", children: "Insert Table" }), jsxRuntime.jsxs("div", { className: "rte-table-insert-fields", children: [jsxRuntime.jsxs("label", { className: "rte-table-insert-label", children: [jsxRuntime.jsx("span", { children: "Zeilen" }), jsxRuntime.jsx("input", { type: "number", min: 1, max: 20, value: rows, onChange: (e) => setRows(Math.max(1, Math.min(20, parseInt(e.target.value) || 1))), className: "rte-table-insert-input" })] }), jsxRuntime.jsxs("label", { className: "rte-table-insert-label", children: [jsxRuntime.jsx("span", { children: "Spalten" }), jsxRuntime.jsx("input", { type: "number", min: 1, max: 10, value: cols, onChange: (e) => setCols(Math.max(1, Math.min(10, parseInt(e.target.value) || 1))), className: "rte-table-insert-input" })] })] }), jsxRuntime.jsx("button", { type: "button", className: "rte-table-insert-btn", onClick: () => onInsert(rows, cols), children: "Insert" })] }));
4169
+ const style = { position: "fixed" };
4170
+ if (anchorRect) {
4171
+ const pad = 8;
4172
+ let top = anchorRect.bottom + 4;
4173
+ let left = anchorRect.left;
4174
+ if (left + 220 > window.innerWidth - pad) {
4175
+ left = window.innerWidth - 220 - pad;
4176
+ }
4177
+ if (left < pad)
4178
+ left = pad;
4179
+ if (top + 200 > window.innerHeight - pad) {
4180
+ top = anchorRect.top - 200 - 4;
4181
+ }
4182
+ if (top < pad)
4183
+ top = pad;
4184
+ style.top = top;
4185
+ style.left = left;
4186
+ }
4187
+ return reactDom.createPortal(jsxRuntime.jsxs("div", { className: "rte-table-insert-dialog", ref: dialogRef, style: style, onMouseDown: (e) => e.preventDefault(), children: [jsxRuntime.jsx("div", { className: "rte-table-insert-title", children: "Insert Table" }), jsxRuntime.jsxs("div", { className: "rte-table-insert-fields", children: [jsxRuntime.jsxs("label", { className: "rte-table-insert-label", children: [jsxRuntime.jsx("span", { children: "Zeilen" }), jsxRuntime.jsx("input", { type: "number", min: 1, max: 20, value: rows, onChange: (e) => setRows(Math.max(1, Math.min(20, parseInt(e.target.value) || 1))), className: "rte-table-insert-input", onMouseDown: (e) => e.stopPropagation() })] }), jsxRuntime.jsxs("label", { className: "rte-table-insert-label", children: [jsxRuntime.jsx("span", { children: "Spalten" }), jsxRuntime.jsx("input", { type: "number", min: 1, max: 10, value: cols, onChange: (e) => setCols(Math.max(1, Math.min(10, parseInt(e.target.value) || 1))), className: "rte-table-insert-input", onMouseDown: (e) => e.stopPropagation() })] })] }), jsxRuntime.jsx("button", { type: "button", className: "rte-table-insert-btn", onClick: () => onInsert(rows, cols), children: "Insert" })] }), document.body);
4035
4188
  };
4036
4189
  const TableContextMenu = ({ x, y, onClose, }) => {
4037
4190
  const ref = React.useRef(null);
@@ -4052,6 +4205,14 @@ const TableContextMenu = ({ x, y, onClose, }) => {
4052
4205
  };
4053
4206
  const TableToolbarButton = (props) => {
4054
4207
  const [showDialog, setShowDialog] = React.useState(false);
4208
+ const btnRef = React.useRef(null);
4209
+ const [anchorRect, setAnchorRect] = React.useState(null);
4210
+ const handleToggle = React.useCallback(() => {
4211
+ if (!showDialog && btnRef.current) {
4212
+ setAnchorRect(btnRef.current.getBoundingClientRect());
4213
+ }
4214
+ setShowDialog((v) => !v);
4215
+ }, [showDialog]);
4055
4216
  const handleInsert = React.useCallback((rows, cols) => {
4056
4217
  setShowDialog(false);
4057
4218
  if (!props.editorAPI)
@@ -4060,7 +4221,6 @@ const TableToolbarButton = (props) => {
4060
4221
  if (!sel || sel.rangeCount === 0)
4061
4222
  return;
4062
4223
  const range = sel.getRangeAt(0);
4063
- // Find the editor's contentEditable root
4064
4224
  const container = range.commonAncestorContainer;
4065
4225
  const editorEl = container.nodeType === Node.TEXT_NODE
4066
4226
  ? container.parentElement
@@ -4069,7 +4229,6 @@ const TableToolbarButton = (props) => {
4069
4229
  if (!editorRoot)
4070
4230
  return;
4071
4231
  const table = createTable(rows, cols);
4072
- // Insert after the current block element
4073
4232
  let block = editorEl;
4074
4233
  while (block &&
4075
4234
  block !== editorRoot &&
@@ -4082,11 +4241,9 @@ const TableToolbarButton = (props) => {
4082
4241
  else {
4083
4242
  editorRoot.appendChild(table);
4084
4243
  }
4085
- // Add a paragraph after the table so the user can continue typing
4086
4244
  const p = document.createElement("p");
4087
4245
  p.innerHTML = "<br>";
4088
4246
  table.parentNode?.insertBefore(p, table.nextSibling);
4089
- // Focus the first cell
4090
4247
  const firstCell = table.querySelector("td, th");
4091
4248
  if (firstCell) {
4092
4249
  const newRange = document.createRange();
@@ -4096,7 +4253,7 @@ const TableToolbarButton = (props) => {
4096
4253
  sel.addRange(newRange);
4097
4254
  }
4098
4255
  }, [props.editorAPI]);
4099
- return (jsxRuntime.jsxs("div", { style: { position: "relative" }, children: [jsxRuntime.jsx("button", { type: "button", onClick: () => setShowDialog(!showDialog), disabled: props.disabled, className: `rte-toolbar-button ${props.isActive ? "rte-toolbar-button-active" : ""}`, title: "Table", "aria-label": "Table", children: jsxRuntime.jsx(IconWrapper, { icon: "mdi:table", width: 18, height: 18 }) }), showDialog && (jsxRuntime.jsx(InsertTableDialog, { onInsert: handleInsert, onClose: () => setShowDialog(false) }))] }));
4256
+ return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx("button", { ref: btnRef, type: "button", onClick: handleToggle, disabled: props.disabled, className: `rte-toolbar-button ${props.isActive ? "rte-toolbar-button-active" : ""}`, title: "Table", "aria-label": "Table", children: jsxRuntime.jsx(IconWrapper, { icon: "mdi:table", width: 18, height: 18 }) }), showDialog && (jsxRuntime.jsx(InsertTableDialog, { onInsert: handleInsert, onClose: () => setShowDialog(false), anchorRect: anchorRect }))] }));
4100
4257
  };
4101
4258
  /* ══════════════════════════════════════════════════════════════════════════
4102
4259
  Table Plugin export
@@ -4306,10 +4463,10 @@ const FloatingToolbar = ({ plugins, editorAPI, editorElement, }) => {
4306
4463
  }
4307
4464
  // Center horizontally on the selection, clamp to viewport
4308
4465
  let left = rect.left + rect.width / 2 - toolbarW / 2;
4309
- if (left < pad)
4310
- left = pad;
4311
4466
  if (left + toolbarW > vw - pad)
4312
4467
  left = vw - toolbarW - pad;
4468
+ if (left < pad)
4469
+ left = pad;
4313
4470
  setPos({ top, left, visible: true });
4314
4471
  }, [editorElement]);
4315
4472
  // Debounce via requestAnimationFrame for smooth repositioning
@@ -4354,16 +4511,14 @@ const FloatingToolbar = ({ plugins, editorAPI, editorElement, }) => {
4354
4511
  requestAnimationFrame(() => scheduleUpdate());
4355
4512
  }, [editorAPI, scheduleUpdate]);
4356
4513
  const isHidden = !pos.visible || leftPlugins.length === 0;
4357
- return (jsxRuntime.jsx("div", { ref: toolbarRef, className: "rte-floating-toolbar", style: {
4514
+ return reactDom.createPortal(jsxRuntime.jsx("div", { ref: toolbarRef, className: "rte-floating-toolbar", style: {
4358
4515
  position: "fixed",
4359
4516
  top: pos.top,
4360
4517
  left: pos.left,
4361
4518
  visibility: isHidden ? "hidden" : "visible",
4362
4519
  opacity: isHidden ? 0 : 1,
4363
4520
  pointerEvents: isHidden ? "none" : "auto",
4364
- },
4365
- // Prevent selection loss when clicking toolbar buttons
4366
- onMouseDown: (e) => e.preventDefault(), children: jsxRuntime.jsxs("div", { className: "rte-floating-toolbar-content", children: [jsxRuntime.jsx("div", { className: "rte-toolbar-left", children: leftPlugins.map((plugin) => {
4521
+ }, onMouseDown: (e) => e.preventDefault(), children: jsxRuntime.jsxs("div", { className: "rte-floating-toolbar-content", children: [jsxRuntime.jsx("div", { className: "rte-toolbar-left", children: leftPlugins.map((plugin) => {
4367
4522
  if (!plugin.renderButton)
4368
4523
  return null;
4369
4524
  const isActive = plugin.isActive
@@ -4397,7 +4552,7 @@ const FloatingToolbar = ({ plugins, editorAPI, editorElement, }) => {
4397
4552
  disabled: !canExecute,
4398
4553
  editorAPI,
4399
4554
  });
4400
- })()] }))] }) }));
4555
+ })()] }))] }) }), document.body);
4401
4556
  };
4402
4557
 
4403
4558
  /**