@underverse-ui/underverse 1.0.143 → 1.0.145

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.
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "package": "@underverse-ui/underverse",
3
- "version": "1.0.143",
3
+ "version": "1.0.145",
4
4
  "sourceEntry": "src/index.ts",
5
5
  "totalExports": 232,
6
6
  "exports": [
package/dist/index.cjs CHANGED
@@ -25896,6 +25896,99 @@ function getImageFiles(dataTransfer) {
25896
25896
  }
25897
25897
  return Array.from(byKey.values());
25898
25898
  }
25899
+ function getClipboardData(dataTransfer, type) {
25900
+ try {
25901
+ return dataTransfer.getData(type) ?? "";
25902
+ } catch {
25903
+ return "";
25904
+ }
25905
+ }
25906
+ function extractClipboardHtmlFragment(html) {
25907
+ const startMarker = "<!--StartFragment-->";
25908
+ const endMarker = "<!--EndFragment-->";
25909
+ const start = html.indexOf(startMarker);
25910
+ const end = html.indexOf(endMarker);
25911
+ if (start >= 0 && end > start) {
25912
+ return html.slice(start + startMarker.length, end);
25913
+ }
25914
+ return html;
25915
+ }
25916
+ function getClipboardTableHtml(dataTransfer) {
25917
+ const html = getClipboardData(dataTransfer, "text/html");
25918
+ if (!/<table(?:\s|>)/i.test(html)) return "";
25919
+ const fragment = extractClipboardHtmlFragment(html);
25920
+ if (typeof DOMParser !== "undefined") {
25921
+ const doc = new DOMParser().parseFromString(fragment, "text/html");
25922
+ const table = doc.querySelector("table");
25923
+ if (table) return table.outerHTML;
25924
+ }
25925
+ return fragment;
25926
+ }
25927
+ function escapeHtml(value) {
25928
+ return value.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
25929
+ }
25930
+ function renderCellHtml(value) {
25931
+ const lines = value.split("\n");
25932
+ return lines.map((line) => `<p>${escapeHtml(line)}</p>`).join("");
25933
+ }
25934
+ function parseTsvRows(text) {
25935
+ const rows = [];
25936
+ let row = [];
25937
+ let field = "";
25938
+ let inQuotes = false;
25939
+ const pushField = () => {
25940
+ row.push(field);
25941
+ field = "";
25942
+ };
25943
+ const pushRow = () => {
25944
+ pushField();
25945
+ rows.push(row);
25946
+ row = [];
25947
+ };
25948
+ for (let index = 0; index < text.length; index += 1) {
25949
+ const char = text[index];
25950
+ const next = text[index + 1];
25951
+ if (inQuotes) {
25952
+ if (char === '"' && next === '"') {
25953
+ field += '"';
25954
+ index += 1;
25955
+ continue;
25956
+ }
25957
+ if (char === '"') {
25958
+ inQuotes = false;
25959
+ continue;
25960
+ }
25961
+ field += char;
25962
+ continue;
25963
+ }
25964
+ if (char === '"' && field.length === 0) {
25965
+ inQuotes = true;
25966
+ continue;
25967
+ }
25968
+ if (char === " ") {
25969
+ pushField();
25970
+ continue;
25971
+ }
25972
+ if (char === "\n") {
25973
+ pushRow();
25974
+ continue;
25975
+ }
25976
+ field += char;
25977
+ }
25978
+ pushRow();
25979
+ while (rows.length > 0 && rows[rows.length - 1].every((cell) => cell === "")) {
25980
+ rows.pop();
25981
+ }
25982
+ return rows;
25983
+ }
25984
+ function getClipboardTsvTableHtml(dataTransfer) {
25985
+ const text = getClipboardData(dataTransfer, "text/plain").replace(/\r\n/g, "\n").replace(/\r/g, "\n").replace(/\n+$/, "");
25986
+ if (!text.includes(" ")) return "";
25987
+ const rows = parseTsvRows(text);
25988
+ if (rows.length === 0 || rows.every((row) => row.length < 2)) return "";
25989
+ const body = rows.map((row) => `<tr>${row.map((cell) => `<td>${renderCellHtml(cell)}</td>`).join("")}</tr>`).join("");
25990
+ return `<table><tbody>${body}</tbody></table>`;
25991
+ }
25899
25992
  function fileToDataUrl(file) {
25900
25993
  return new Promise((resolve, reject) => {
25901
25994
  const reader = new FileReader();
@@ -25950,6 +26043,18 @@ var ClipboardImages = import_core5.Extension.create({
25950
26043
  props: {
25951
26044
  handlePaste: (_view, event) => {
25952
26045
  if (!event || !event.clipboardData) return false;
26046
+ const tableHtml = getClipboardTableHtml(event.clipboardData);
26047
+ if (tableHtml) {
26048
+ event.preventDefault();
26049
+ editor.chain().focus().insertContent(tableHtml).run();
26050
+ return true;
26051
+ }
26052
+ const tsvTableHtml = getClipboardTsvTableHtml(event.clipboardData);
26053
+ if (tsvTableHtml) {
26054
+ event.preventDefault();
26055
+ editor.chain().focus().insertContent(tsvTableHtml).run();
26056
+ return true;
26057
+ }
25953
26058
  const files = getImageFiles(event.clipboardData);
25954
26059
  if (files.length === 0) return false;
25955
26060
  event.preventDefault();
@@ -29080,58 +29185,6 @@ var import_tables2 = require("@tiptap/pm/tables");
29080
29185
  var import_react_dom8 = require("react-dom");
29081
29186
  var import_lucide_react49 = require("lucide-react");
29082
29187
  var import_jsx_runtime86 = require("react/jsx-runtime");
29083
- var FloatingSlashCommandMenu = ({ editor, onClose }) => {
29084
- const t = useSmartTranslations("UEditor");
29085
- const messages = (0, import_react62.useMemo)(() => buildSlashCommandMessages(t), [t]);
29086
- const items = (0, import_react62.useMemo)(() => buildSlashCommandItems({ query: "", messages }), [messages]);
29087
- const listRef = (0, import_react62.useRef)(null);
29088
- (0, import_react62.useEffect)(() => {
29089
- const handleKeyDown2 = (event) => {
29090
- if (event.key === "Escape") {
29091
- event.preventDefault();
29092
- onClose();
29093
- return;
29094
- }
29095
- const handled = listRef.current?.onKeyDown({ event }) ?? false;
29096
- if (handled) {
29097
- event.preventDefault();
29098
- }
29099
- };
29100
- document.addEventListener("keydown", handleKeyDown2);
29101
- return () => document.removeEventListener("keydown", handleKeyDown2);
29102
- }, [onClose]);
29103
- return /* @__PURE__ */ (0, import_jsx_runtime86.jsx)(
29104
- SlashCommandList,
29105
- {
29106
- ref: listRef,
29107
- items,
29108
- messages,
29109
- command: (item) => {
29110
- item.command({ editor });
29111
- onClose();
29112
- }
29113
- }
29114
- );
29115
- };
29116
- var FloatingMenuContent = ({ editor }) => {
29117
- const t = useSmartTranslations("UEditor");
29118
- const [showCommands, setShowCommands] = (0, import_react62.useState)(false);
29119
- if (showCommands) {
29120
- return /* @__PURE__ */ (0, import_jsx_runtime86.jsx)(FloatingSlashCommandMenu, { editor, onClose: () => setShowCommands(false) });
29121
- }
29122
- return /* @__PURE__ */ (0, import_jsx_runtime86.jsxs)(
29123
- "button",
29124
- {
29125
- type: "button",
29126
- onClick: () => setShowCommands(true),
29127
- className: "flex items-center gap-1 px-2 py-1.5 rounded-lg hover:bg-accent transition-all group",
29128
- children: [
29129
- /* @__PURE__ */ (0, import_jsx_runtime86.jsx)(import_lucide_react49.Plus, { className: "w-4 h-4 text-muted-foreground group-hover:text-foreground" }),
29130
- /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("span", { className: "text-sm text-muted-foreground group-hover:text-foreground", children: t("floatingMenu.addBlock") })
29131
- ]
29132
- }
29133
- );
29134
- };
29135
29188
  function applyTableCellBackground(editor, color) {
29136
29189
  const value = color || null;
29137
29190
  const { state, view } = editor;
@@ -29758,54 +29811,6 @@ var CustomBubbleMenu = ({
29758
29811
  document.body
29759
29812
  );
29760
29813
  };
29761
- var CustomFloatingMenu = ({ editor }) => {
29762
- const FLOATING_MENU_OFFSET = 16;
29763
- const [isVisible, setIsVisible] = (0, import_react62.useState)(false);
29764
- const [position, setPosition] = (0, import_react62.useState)({ top: 0, left: 0 });
29765
- (0, import_react62.useEffect)(() => {
29766
- const updatePosition = () => {
29767
- const { state, view } = editor;
29768
- const { $from, empty } = state.selection;
29769
- const isEmptyTextBlock = $from.parent.isTextblock && $from.parent.type.name === "paragraph" && $from.parent.textContent === "" && empty;
29770
- if (!isEmptyTextBlock || !view.hasFocus()) {
29771
- setIsVisible(false);
29772
- return;
29773
- }
29774
- const coords = view.coordsAtPos($from.pos);
29775
- setPosition({ top: coords.top - FLOATING_MENU_OFFSET, left: coords.left });
29776
- setIsVisible(true);
29777
- };
29778
- const handleBlur = () => setIsVisible(false);
29779
- editor.on("selectionUpdate", updatePosition);
29780
- editor.on("focus", updatePosition);
29781
- editor.on("blur", handleBlur);
29782
- editor.on("update", updatePosition);
29783
- return () => {
29784
- editor.off("selectionUpdate", updatePosition);
29785
- editor.off("focus", updatePosition);
29786
- editor.off("blur", handleBlur);
29787
- editor.off("update", updatePosition);
29788
- };
29789
- }, [editor]);
29790
- if (!isVisible) return null;
29791
- return (0, import_react_dom8.createPortal)(
29792
- /* @__PURE__ */ (0, import_jsx_runtime86.jsx)(
29793
- "div",
29794
- {
29795
- "data-popover": true,
29796
- className: "fixed z-99999 rounded-2xl border border-border/50 bg-card text-card-foreground shadow-lg backdrop-blur-sm overflow-hidden animate-in fade-in-0 slide-in-from-bottom-2",
29797
- style: {
29798
- top: `${position.top}px`,
29799
- left: `${position.left}px`,
29800
- transform: "translate(-50%, -100%)"
29801
- },
29802
- onMouseDown: (e) => e.preventDefault(),
29803
- children: /* @__PURE__ */ (0, import_jsx_runtime86.jsx)(FloatingMenuContent, { editor })
29804
- }
29805
- ),
29806
- document.body
29807
- );
29808
- };
29809
29814
 
29810
29815
  // src/components/UEditor/CharacterCount.tsx
29811
29816
  var import_jsx_runtime87 = require("react/jsx-runtime");
@@ -34580,8 +34585,8 @@ function TableAddRails({
34580
34585
  const visibleTableHeight = Math.min(layout.tableHeight, layout.viewportHeight);
34581
34586
  const columnRailTop = layout.tableTop;
34582
34587
  const columnRailLeft = layout.tableLeft + visibleTableWidth + ADD_COLUMN_RAIL_GAP;
34583
- const rowRailTop = layout.tableTop + visibleTableHeight + ADD_ROW_RAIL_GAP;
34584
- const rowRailLeft = layout.tableLeft;
34588
+ const rowRailTop = layout.wrapperTop + layout.wrapperHeight + ADD_ROW_RAIL_GAP;
34589
+ const rowRailLeft = Math.max(layout.tableLeft, layout.wrapperLeft);
34585
34590
  const showColumnRail = controlsVisible || addColumnVisible;
34586
34591
  const showRowRail = controlsVisible || addRowVisible;
34587
34592
  return /* @__PURE__ */ (0, import_jsx_runtime89.jsxs)(import_jsx_runtime89.Fragment, { children: [
@@ -35211,6 +35216,7 @@ function TableControls({ editor, containerRef }) {
35211
35216
  const proseMirror = editor.view.dom;
35212
35217
  const surface = containerRef.current;
35213
35218
  if (!surface) return void 0;
35219
+ const scrollListenerOptions = { passive: true, capture: true };
35214
35220
  const handleMouseOver = (event) => {
35215
35221
  if (dragStateRef.current) return;
35216
35222
  const cell = getCellFromTarget(event.target);
@@ -35236,7 +35242,7 @@ function TableControls({ editor, containerRef }) {
35236
35242
  proseMirror.addEventListener("focusin", handleFocusIn);
35237
35243
  surface.addEventListener("mouseover", handleSurfaceMouseMove);
35238
35244
  surface.addEventListener("mousemove", handleSurfaceMouseMove);
35239
- surface.addEventListener("scroll", refreshCurrentLayout, { passive: true });
35245
+ surface.addEventListener("scroll", refreshCurrentLayout, scrollListenerOptions);
35240
35246
  surface.addEventListener(UEDITOR_TABLE_LAYOUT_CHANGE_EVENT, refreshCurrentLayout);
35241
35247
  window.addEventListener("resize", refreshCurrentLayout);
35242
35248
  editor.on("selectionUpdate", syncFromSelection);
@@ -35250,7 +35256,7 @@ function TableControls({ editor, containerRef }) {
35250
35256
  proseMirror.removeEventListener("focusin", handleFocusIn);
35251
35257
  surface.removeEventListener("mouseover", handleSurfaceMouseMove);
35252
35258
  surface.removeEventListener("mousemove", handleSurfaceMouseMove);
35253
- surface.removeEventListener("scroll", refreshCurrentLayout);
35259
+ surface.removeEventListener("scroll", refreshCurrentLayout, scrollListenerOptions);
35254
35260
  surface.removeEventListener(UEDITOR_TABLE_LAYOUT_CHANGE_EVENT, refreshCurrentLayout);
35255
35261
  window.removeEventListener("resize", refreshCurrentLayout);
35256
35262
  editor.off("selectionUpdate", syncFromSelection);
@@ -35720,7 +35726,7 @@ var UEDITOR_PROSEMIRROR_CLASS_NAME = cn(
35720
35726
  "[&_.column-resize-handle]:top-[-1px]",
35721
35727
  "[&_.column-resize-handle]:bottom-[-1px]",
35722
35728
  "[&_.column-resize-handle]:right-[-5px]",
35723
- "[&_.column-resize-handle]:z-10",
35729
+ "[&_.column-resize-handle]:z-30",
35724
35730
  "[&_.column-resize-handle]:w-2.5",
35725
35731
  "[&_.column-resize-handle]:bg-transparent",
35726
35732
  "[&_.column-resize-handle]:rounded-none",
@@ -35974,26 +35980,31 @@ function useUEditorTableInteractions(editor, editable = true) {
35974
35980
  const activeTableCellRef = (0, import_react66.useRef)(null);
35975
35981
  const suppressActiveCellHighlightRef = (0, import_react66.useRef)(false);
35976
35982
  const tableLayoutSyncFrameRef = (0, import_react66.useRef)(null);
35983
+ const getProseMirrorElement = import_react66.default.useCallback(() => {
35984
+ return editorContentRef.current?.querySelector(".ProseMirror");
35985
+ }, []);
35977
35986
  const setEditorResizeCursor = import_react66.default.useCallback((cursor) => {
35978
- const proseMirror = editorContentRef.current?.querySelector(".ProseMirror");
35987
+ const proseMirror = getProseMirrorElement();
35979
35988
  if (proseMirror) {
35980
35989
  proseMirror.style.cursor = cursor;
35981
35990
  }
35982
- }, []);
35991
+ }, [getProseMirrorElement]);
35983
35992
  const hideColumnGuide = import_react66.default.useCallback(() => {
35984
35993
  editorContentRef.current?.classList.remove("resize-cursor");
35994
+ getProseMirrorElement()?.classList.remove("resize-cursor");
35985
35995
  const guide = tableColumnGuideRef.current;
35986
35996
  if (guide) {
35987
35997
  guide.style.opacity = "0";
35988
35998
  }
35989
- }, []);
35999
+ }, [getProseMirrorElement]);
35990
36000
  const hideRowGuide = import_react66.default.useCallback(() => {
35991
36001
  editorContentRef.current?.classList.remove("resize-row-cursor");
36002
+ getProseMirrorElement()?.classList.remove("resize-row-cursor");
35992
36003
  const guide = tableRowGuideRef.current;
35993
36004
  if (guide) {
35994
36005
  guide.style.opacity = "0";
35995
36006
  }
35996
- }, []);
36007
+ }, [getProseMirrorElement]);
35997
36008
  const clearAllTableResizeHover = import_react66.default.useCallback(() => {
35998
36009
  setEditorResizeCursor("");
35999
36010
  hideColumnGuide();
@@ -36023,7 +36034,10 @@ function useUEditorTableInteractions(editor, editable = true) {
36023
36034
  });
36024
36035
  }, [updateActiveCellHighlight]);
36025
36036
  const setActiveTableCell = import_react66.default.useCallback((cell) => {
36026
- if (activeTableCellRef.current === cell) return;
36037
+ if (activeTableCellRef.current === cell) {
36038
+ updateActiveCellHighlight(cell);
36039
+ return;
36040
+ }
36027
36041
  activeTableCellRef.current = cell;
36028
36042
  updateActiveCellHighlight(activeTableCellRef.current);
36029
36043
  }, [updateActiveCellHighlight]);
@@ -36048,8 +36062,9 @@ function useUEditorTableInteractions(editor, editable = true) {
36048
36062
  guide.style.height = `${metrics.height}px`;
36049
36063
  guide.style.opacity = "1";
36050
36064
  surface.classList.add("resize-cursor");
36065
+ getProseMirrorElement()?.classList.add("resize-cursor");
36051
36066
  setEditorResizeCursor("col-resize");
36052
- }, [setEditorResizeCursor]);
36067
+ }, [getProseMirrorElement, setEditorResizeCursor]);
36053
36068
  const showRowGuide = import_react66.default.useCallback((table, row, cell) => {
36054
36069
  const surface = editorContentRef.current;
36055
36070
  const guide = tableRowGuideRef.current;
@@ -36061,8 +36076,9 @@ function useUEditorTableInteractions(editor, editable = true) {
36061
36076
  guide.style.height = `${ROW_RESIZE_LINE_THICKNESS}px`;
36062
36077
  guide.style.opacity = "1";
36063
36078
  surface.classList.add("resize-row-cursor");
36079
+ getProseMirrorElement()?.classList.add("resize-row-cursor");
36064
36080
  setEditorResizeCursor("row-resize");
36065
- }, [setEditorResizeCursor]);
36081
+ }, [getProseMirrorElement, setEditorResizeCursor]);
36066
36082
  const {
36067
36083
  beginResize,
36068
36084
  cancelResize,
@@ -36081,19 +36097,32 @@ function useUEditorTableInteractions(editor, editable = true) {
36081
36097
  });
36082
36098
  const syncActiveTableCellFromSelection = import_react66.default.useCallback(() => {
36083
36099
  if (!editor) return;
36100
+ if (!editor.isFocused) {
36101
+ clearActiveTableCell();
36102
+ return;
36103
+ }
36084
36104
  setActiveTableCell(getSelectionTableCell(editor.view));
36085
- }, [editor, setActiveTableCell]);
36105
+ }, [clearActiveTableCell, editor, setActiveTableCell]);
36086
36106
  (0, import_react66.useEffect)(() => {
36087
36107
  if (!editor || !editable) return void 0;
36088
36108
  const proseMirror = editor.view.dom;
36089
36109
  const surface = editorContentRef.current;
36090
36110
  let selectionSyncTimeoutId = 0;
36111
+ const scrollListenerOptions = { passive: true, capture: true };
36091
36112
  const scheduleActiveCellSync = (fallbackCell = null) => {
36092
36113
  requestAnimationFrame(() => {
36114
+ if (!editor.isFocused) {
36115
+ clearActiveTableCell();
36116
+ return;
36117
+ }
36093
36118
  setActiveTableCell(getSelectionTableCell(editor.view) ?? fallbackCell);
36094
36119
  });
36095
36120
  window.clearTimeout(selectionSyncTimeoutId);
36096
36121
  selectionSyncTimeoutId = window.setTimeout(() => {
36122
+ if (!editor.isFocused) {
36123
+ clearActiveTableCell();
36124
+ return;
36125
+ }
36097
36126
  setActiveTableCell(getSelectionTableCell(editor.view) ?? fallbackCell);
36098
36127
  }, 0);
36099
36128
  };
@@ -36197,13 +36226,15 @@ function useUEditorTableInteractions(editor, editable = true) {
36197
36226
  proseMirror.addEventListener("keyup", handleSelectionChange);
36198
36227
  proseMirror.addEventListener("focusin", handleSelectionChange);
36199
36228
  document.addEventListener("selectionchange", handleSelectionChange);
36200
- surface?.addEventListener("scroll", handleActiveCellLayoutChange, { passive: true });
36229
+ surface?.addEventListener("scroll", handleActiveCellLayoutChange, scrollListenerOptions);
36201
36230
  window.addEventListener("resize", handleActiveCellLayoutChange);
36202
36231
  document.addEventListener("pointermove", handlePointerMove);
36203
36232
  document.addEventListener("pointerup", handlePointerUp);
36204
36233
  window.addEventListener("blur", handleWindowBlur);
36205
36234
  editor.on("selectionUpdate", syncActiveTableCellFromSelection);
36206
36235
  editor.on("focus", syncActiveTableCellFromSelection);
36236
+ editor.on("blur", clearActiveTableCell);
36237
+ editor.on("update", scheduleTableLayoutSync);
36207
36238
  syncActiveTableCellFromSelection();
36208
36239
  return () => {
36209
36240
  proseMirror.removeEventListener("mousemove", handleEditorMouseMove);
@@ -36214,13 +36245,15 @@ function useUEditorTableInteractions(editor, editable = true) {
36214
36245
  proseMirror.removeEventListener("keyup", handleSelectionChange);
36215
36246
  proseMirror.removeEventListener("focusin", handleSelectionChange);
36216
36247
  document.removeEventListener("selectionchange", handleSelectionChange);
36217
- surface?.removeEventListener("scroll", handleActiveCellLayoutChange);
36248
+ surface?.removeEventListener("scroll", handleActiveCellLayoutChange, scrollListenerOptions);
36218
36249
  window.removeEventListener("resize", handleActiveCellLayoutChange);
36219
36250
  document.removeEventListener("pointermove", handlePointerMove);
36220
36251
  document.removeEventListener("pointerup", handlePointerUp);
36221
36252
  window.removeEventListener("blur", handleWindowBlur);
36222
36253
  editor.off("selectionUpdate", syncActiveTableCellFromSelection);
36223
36254
  editor.off("focus", syncActiveTableCellFromSelection);
36255
+ editor.off("blur", clearActiveTableCell);
36256
+ editor.off("update", scheduleTableLayoutSync);
36224
36257
  window.clearTimeout(selectionSyncTimeoutId);
36225
36258
  if (tableLayoutSyncFrameRef.current !== null) {
36226
36259
  window.cancelAnimationFrame(tableLayoutSyncFrameRef.current);
@@ -36233,7 +36266,7 @@ function useUEditorTableInteractions(editor, editable = true) {
36233
36266
  clearHoveredTableCell();
36234
36267
  clearAllTableResizeHover();
36235
36268
  };
36236
- }, [beginResize, cancelResize, cleanupRowResize, clearActiveTableCell, clearAllTableResizeHover, clearHoveredTableCell, editable, editor, handleRowResizePointerMove, handleRowResizePointerUp, hideColumnGuide, hideRowGuide, isRowResizing, showColumnGuide, showRowGuide, syncActiveRowResizeGuide, syncActiveTableCellFromSelection, updateActiveCellHighlight]);
36269
+ }, [beginResize, cancelResize, cleanupRowResize, clearActiveTableCell, clearAllTableResizeHover, clearHoveredTableCell, editable, editor, handleRowResizePointerMove, handleRowResizePointerUp, hideColumnGuide, hideRowGuide, isRowResizing, scheduleTableLayoutSync, showColumnGuide, showRowGuide, syncActiveRowResizeGuide, syncActiveTableCellFromSelection, updateActiveCellHighlight]);
36237
36270
  return {
36238
36271
  editorContentRef,
36239
36272
  tableColumnGuideRef,
@@ -36735,6 +36768,21 @@ var MenuBar = ({
36735
36768
  const openPreviewDialog = () => {
36736
36769
  setShowPreviewDialog(true);
36737
36770
  };
36771
+ const handlePreview = () => {
36772
+ if (onPreview) {
36773
+ onPreview();
36774
+ return;
36775
+ }
36776
+ openPreviewDialog();
36777
+ };
36778
+ import_react67.default.useEffect(() => {
36779
+ if (!showPreviewDialog) return void 0;
36780
+ const previousOverflow = document.body.style.overflow;
36781
+ document.body.style.overflow = "hidden";
36782
+ return () => {
36783
+ document.body.style.overflow = previousOverflow;
36784
+ };
36785
+ }, [showPreviewDialog]);
36738
36786
  const applySourceHtml = () => {
36739
36787
  editor.chain().focus().setContent(sourceHtml).run();
36740
36788
  setShowSourceDialog(false);
@@ -36846,7 +36894,7 @@ var MenuBar = ({
36846
36894
  { label: t("menubar.edit"), items: buildEditMenuItems(t, editor), open: void 0, onOpenChange: void 0 },
36847
36895
  {
36848
36896
  label: t("menubar.view"),
36849
- items: buildViewMenuItems(t, { containerRef, onSourceCode, openSourceDialog, onPreview, openPreviewDialog }),
36897
+ items: buildViewMenuItems(t, { containerRef, onSourceCode, openSourceDialog, onPreview: handlePreview, openPreviewDialog }),
36850
36898
  open: void 0,
36851
36899
  onOpenChange: void 0
36852
36900
  },
@@ -36883,17 +36931,33 @@ var MenuBar = ({
36883
36931
  onChange: (e) => handleImageFiles(e.target.files)
36884
36932
  }
36885
36933
  ),
36886
- /* @__PURE__ */ (0, import_jsx_runtime93.jsx)("div", { className: "flex items-center gap-0.5 border-b border-border/35 bg-muted/20 px-1.5 py-0.5", children: menus.map(({ label, items, open, onOpenChange }) => /* @__PURE__ */ (0, import_jsx_runtime93.jsx)(
36887
- DropdownMenu,
36888
- {
36889
- trigger: /* @__PURE__ */ (0, import_jsx_runtime93.jsx)(MenuBarTrigger, { children: label }),
36890
- placement: "bottom-start",
36891
- isOpen: open,
36892
- onOpenChange,
36893
- children: renderMenuItems(items)
36894
- },
36895
- label
36896
- )) }),
36934
+ /* @__PURE__ */ (0, import_jsx_runtime93.jsxs)("div", { className: "flex items-center gap-0.5 border-b border-border/35 bg-muted/20 px-1.5 py-0.5", children: [
36935
+ menus.map(({ label, items, open, onOpenChange }) => /* @__PURE__ */ (0, import_jsx_runtime93.jsx)(
36936
+ DropdownMenu,
36937
+ {
36938
+ trigger: /* @__PURE__ */ (0, import_jsx_runtime93.jsx)(MenuBarTrigger, { children: label }),
36939
+ placement: "bottom-start",
36940
+ isOpen: open,
36941
+ onOpenChange,
36942
+ children: renderMenuItems(items)
36943
+ },
36944
+ label
36945
+ )),
36946
+ /* @__PURE__ */ (0, import_jsx_runtime93.jsx)(
36947
+ "button",
36948
+ {
36949
+ type: "button",
36950
+ onClick: handlePreview,
36951
+ "aria-label": t("menubar.preview"),
36952
+ title: t("menubar.preview"),
36953
+ className: cn(
36954
+ "ml-auto inline-flex h-7 w-7 items-center justify-center rounded-md text-muted-foreground transition-colors",
36955
+ "hover:bg-accent hover:text-foreground focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-1"
36956
+ ),
36957
+ children: /* @__PURE__ */ (0, import_jsx_runtime93.jsx)(import_lucide_react53.Eye, { className: "h-4 w-4", "aria-hidden": "true" })
36958
+ }
36959
+ )
36960
+ ] }),
36897
36961
  /* @__PURE__ */ (0, import_jsx_runtime93.jsx)(
36898
36962
  Modal_default,
36899
36963
  {
@@ -36936,23 +37000,38 @@ var MenuBar = ({
36936
37000
  ] })
36937
37001
  }
36938
37002
  ),
36939
- /* @__PURE__ */ (0, import_jsx_runtime93.jsx)(
36940
- Modal_default,
36941
- {
36942
- isOpen: showPreviewDialog,
36943
- onClose: () => setShowPreviewDialog(false),
36944
- title: t("menubar.preview"),
36945
- size: "lg",
36946
- children: editor.isEmpty ? /* @__PURE__ */ (0, import_jsx_runtime93.jsx)("p", { className: "text-muted-foreground text-sm", children: t("menubar.previewEmpty") }) : /* @__PURE__ */ (0, import_jsx_runtime93.jsx)(
36947
- "div",
37003
+ showPreviewDialog && /* @__PURE__ */ (0, import_jsx_runtime93.jsxs)("div", { className: "fixed inset-0 z-9999 flex flex-col bg-background text-foreground", children: [
37004
+ /* @__PURE__ */ (0, import_jsx_runtime93.jsxs)("div", { className: "flex shrink-0 items-center justify-between border-b border-border bg-card px-4 py-3", children: [
37005
+ /* @__PURE__ */ (0, import_jsx_runtime93.jsx)("h2", { className: "text-base font-semibold", children: t("menubar.preview") }),
37006
+ /* @__PURE__ */ (0, import_jsx_runtime93.jsx)(
37007
+ "button",
36948
37008
  {
36949
- "data-testid": "preview-content",
36950
- className: UEDITOR_PROSEMIRROR_CLASS_NAME,
36951
- dangerouslySetInnerHTML: { __html: editor.getHTML() }
37009
+ type: "button",
37010
+ onClick: () => setShowPreviewDialog(false),
37011
+ "aria-label": t("menubar.closeDialog"),
37012
+ className: cn(
37013
+ "inline-flex h-8 w-8 items-center justify-center rounded-md text-muted-foreground transition-colors",
37014
+ "hover:bg-accent hover:text-foreground focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-1"
37015
+ ),
37016
+ children: /* @__PURE__ */ (0, import_jsx_runtime93.jsx)(import_lucide_react53.X, { className: "h-4 w-4", "aria-hidden": "true" })
36952
37017
  }
36953
37018
  )
36954
- }
36955
- )
37019
+ ] }),
37020
+ /* @__PURE__ */ (0, import_jsx_runtime93.jsx)(
37021
+ "div",
37022
+ {
37023
+ "data-testid": "preview-content",
37024
+ className: "min-h-0 flex-1 overflow-y-auto overscroll-contain px-4 py-4 md:px-8",
37025
+ children: editor.isEmpty ? /* @__PURE__ */ (0, import_jsx_runtime93.jsx)("p", { className: "text-muted-foreground text-sm", children: t("menubar.previewEmpty") }) : /* @__PURE__ */ (0, import_jsx_runtime93.jsx)(
37026
+ "div",
37027
+ {
37028
+ className: UEDITOR_PROSEMIRROR_CLASS_NAME,
37029
+ dangerouslySetInnerHTML: { __html: editor.getHTML() }
37030
+ }
37031
+ )
37032
+ }
37033
+ )
37034
+ ] })
36956
37035
  ] });
36957
37036
  };
36958
37037
 
@@ -36976,7 +37055,6 @@ var UEditor = import_react69.default.forwardRef(({
36976
37055
  autofocus = false,
36977
37056
  showToolbar = true,
36978
37057
  showBubbleMenu = true,
36979
- showFloatingMenu = false,
36980
37058
  showCharacterCount = true,
36981
37059
  maxCharacters,
36982
37060
  minHeight = "200px",
@@ -37178,7 +37256,6 @@ var UEditor = import_react69.default.forwardRef(({
37178
37256
  lineHeights
37179
37257
  }
37180
37258
  ),
37181
- editable && showFloatingMenu && /* @__PURE__ */ (0, import_jsx_runtime94.jsx)(CustomFloatingMenu, { editor }),
37182
37259
  /* @__PURE__ */ (0, import_jsx_runtime94.jsxs)(
37183
37260
  "div",
37184
37261
  {
@@ -37211,7 +37288,7 @@ var UEditor = import_react69.default.forwardRef(({
37211
37288
  ref: activeTableCellHighlightRef,
37212
37289
  "aria-hidden": "true",
37213
37290
  "data-ueditor-active-cell-highlight": "",
37214
- className: "pointer-events-none hidden absolute z-20 rounded-[2px] border-2 border-primary bg-primary/10 transition-[left,top,width,height] duration-100"
37291
+ className: "pointer-events-none hidden absolute z-20 rounded-[2px] border-2 border-primary bg-primary/10"
37215
37292
  }
37216
37293
  ),
37217
37294
  editable && /* @__PURE__ */ (0, import_jsx_runtime94.jsx)(TableControls, { editor, containerRef: editorContentRef }),