@underverse-ui/underverse 1.0.101 → 1.0.102

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.cjs CHANGED
@@ -23278,8 +23278,8 @@ function useLocale2() {
23278
23278
  }
23279
23279
 
23280
23280
  // src/components/UEditor/UEditor.tsx
23281
- var import_react52 = __toESM(require("react"), 1);
23282
- var import_react53 = require("@tiptap/react");
23281
+ var import_react53 = __toESM(require("react"), 1);
23282
+ var import_react54 = require("@tiptap/react");
23283
23283
 
23284
23284
  // src/components/UEditor/extensions.ts
23285
23285
  var import_extension_document = __toESM(require("@tiptap/extension-document"), 1);
@@ -30805,6 +30805,111 @@ var columnResizingPluginKey = new PluginKey3("tableColumnResizing");
30805
30805
 
30806
30806
  // src/components/UEditor/table-controls.tsx
30807
30807
  var import_lucide_react46 = require("lucide-react");
30808
+
30809
+ // src/components/UEditor/table-dom-utils.ts
30810
+ var MIN_TABLE_ROW_HEIGHT = 36;
30811
+ var COLUMN_RESIZE_LINE_THICKNESS = 2;
30812
+ var ROW_RESIZE_LINE_THICKNESS = 2;
30813
+ var UEDITOR_TABLE_LAYOUT_CHANGE_EVENT = "ueditor-table-layout-change";
30814
+ var TABLE_RESIZE_HIT_ZONE = 10;
30815
+ function findTableRowNodeInfo(view, rowElement) {
30816
+ const firstCell = rowElement.querySelector("th,td");
30817
+ if (!firstCell) return null;
30818
+ const cellPos = view.posAtDOM(firstCell, 0);
30819
+ const $pos = view.state.doc.resolve(cellPos);
30820
+ for (let depth = $pos.depth; depth > 0; depth -= 1) {
30821
+ const node = $pos.node(depth);
30822
+ if (node.type.name === "tableRow") {
30823
+ return {
30824
+ pos: $pos.before(depth),
30825
+ node
30826
+ };
30827
+ }
30828
+ }
30829
+ return null;
30830
+ }
30831
+ function resolveEventElement(target) {
30832
+ if (target instanceof Element) return target;
30833
+ if (target instanceof Node) return target.parentElement;
30834
+ return null;
30835
+ }
30836
+ function getSelectionTableCell(view) {
30837
+ const browserSelection = window.getSelection();
30838
+ const anchorElement = resolveEventElement(browserSelection?.anchorNode ?? null);
30839
+ const anchorCell = anchorElement?.closest?.("th,td");
30840
+ if (anchorCell instanceof HTMLElement) {
30841
+ return anchorCell;
30842
+ }
30843
+ const { from } = view.state.selection;
30844
+ const domAtPos = view.domAtPos(from);
30845
+ const element = resolveEventElement(domAtPos.node);
30846
+ const cell = element?.closest?.("th,td");
30847
+ return cell instanceof HTMLElement ? cell : null;
30848
+ }
30849
+ function isRowResizeHotspot(cell, clientX, clientY) {
30850
+ const rect = cell.getBoundingClientRect();
30851
+ const nearBottom = rect.bottom - clientY <= TABLE_RESIZE_HIT_ZONE;
30852
+ const nearRight = rect.right - clientX <= TABLE_RESIZE_HIT_ZONE;
30853
+ return nearBottom && !nearRight;
30854
+ }
30855
+ function isColumnResizeHotspot(cell, clientX, clientY) {
30856
+ const rect = cell.getBoundingClientRect();
30857
+ const nearRight = rect.right - clientX <= TABLE_RESIZE_HIT_ZONE;
30858
+ const nearBottom = rect.bottom - clientY <= TABLE_RESIZE_HIT_ZONE;
30859
+ return nearRight && !nearBottom;
30860
+ }
30861
+ function getRelativeBoundaryMetrics(surface, table, row, cell) {
30862
+ const surfaceRect = surface.getBoundingClientRect();
30863
+ const tableRect = table.getBoundingClientRect();
30864
+ const rowRect = row.getBoundingClientRect();
30865
+ const cellRect = cell.getBoundingClientRect();
30866
+ return {
30867
+ left: tableRect.left - surfaceRect.left + surface.scrollLeft,
30868
+ top: tableRect.top - surfaceRect.top + surface.scrollTop,
30869
+ width: tableRect.width,
30870
+ height: tableRect.height,
30871
+ rowBottom: rowRect.bottom - surfaceRect.top + surface.scrollTop,
30872
+ columnRight: cellRect.right - surfaceRect.left + surface.scrollLeft
30873
+ };
30874
+ }
30875
+ function getRelativeCellMetrics(surface, cell) {
30876
+ const surfaceRect = surface.getBoundingClientRect();
30877
+ const cellRect = cell.getBoundingClientRect();
30878
+ return {
30879
+ left: cellRect.left - surfaceRect.left + surface.scrollLeft,
30880
+ top: cellRect.top - surfaceRect.top + surface.scrollTop,
30881
+ width: cellRect.width,
30882
+ height: cellRect.height
30883
+ };
30884
+ }
30885
+ function getRelativeSelectedCellsMetrics(surface) {
30886
+ const selectedCells = Array.from(
30887
+ surface.querySelectorAll("td.selectedCell, th.selectedCell")
30888
+ );
30889
+ if (selectedCells.length === 0) {
30890
+ return null;
30891
+ }
30892
+ const surfaceRect = surface.getBoundingClientRect();
30893
+ let left = Number.POSITIVE_INFINITY;
30894
+ let top = Number.POSITIVE_INFINITY;
30895
+ let right = Number.NEGATIVE_INFINITY;
30896
+ let bottom = Number.NEGATIVE_INFINITY;
30897
+ selectedCells.forEach((cell) => {
30898
+ const rect = cell.getBoundingClientRect();
30899
+ left = Math.min(left, rect.left);
30900
+ top = Math.min(top, rect.top);
30901
+ right = Math.max(right, rect.right);
30902
+ bottom = Math.max(bottom, rect.bottom);
30903
+ });
30904
+ return {
30905
+ left: left - surfaceRect.left + surface.scrollLeft,
30906
+ top: top - surfaceRect.top + surface.scrollTop,
30907
+ width: right - left,
30908
+ height: bottom - top
30909
+ };
30910
+ }
30911
+
30912
+ // src/components/UEditor/table-controls.tsx
30808
30913
  var import_jsx_runtime83 = require("react/jsx-runtime");
30809
30914
  var FALLBACK_TABLE_ROW_HEIGHT = 44;
30810
30915
  var FALLBACK_TABLE_COLUMN_WIDTH = 160;
@@ -31104,6 +31209,7 @@ function TableControls({ editor, containerRef }) {
31104
31209
  surface.addEventListener("mouseover", handleSurfaceMouseMove);
31105
31210
  surface.addEventListener("mousemove", handleSurfaceMouseMove);
31106
31211
  surface.addEventListener("scroll", refreshCurrentLayout, { passive: true });
31212
+ surface.addEventListener(UEDITOR_TABLE_LAYOUT_CHANGE_EVENT, refreshCurrentLayout);
31107
31213
  window.addEventListener("resize", refreshCurrentLayout);
31108
31214
  editor.on("selectionUpdate", syncFromSelection);
31109
31215
  editor.on("update", refreshCurrentLayout);
@@ -31115,6 +31221,7 @@ function TableControls({ editor, containerRef }) {
31115
31221
  surface.removeEventListener("mouseover", handleSurfaceMouseMove);
31116
31222
  surface.removeEventListener("mousemove", handleSurfaceMouseMove);
31117
31223
  surface.removeEventListener("scroll", refreshCurrentLayout);
31224
+ surface.removeEventListener(UEDITOR_TABLE_LAYOUT_CHANGE_EVENT, refreshCurrentLayout);
31118
31225
  window.removeEventListener("resize", refreshCurrentLayout);
31119
31226
  editor.off("selectionUpdate", syncFromSelection);
31120
31227
  editor.off("update", refreshCurrentLayout);
@@ -31798,167 +31905,163 @@ function TableControls({ editor, containerRef }) {
31798
31905
  ] });
31799
31906
  }
31800
31907
 
31801
- // src/components/UEditor/UEditor.tsx
31802
- var import_jsx_runtime84 = require("react/jsx-runtime");
31803
- var TABLE_RESIZE_HIT_ZONE = 10;
31804
- var MIN_TABLE_ROW_HEIGHT = 36;
31805
- var COLUMN_RESIZE_LINE_THICKNESS = 2;
31806
- var ROW_RESIZE_LINE_THICKNESS = 2;
31807
- function applyPreviewRowHeight(rowElement, nextHeight) {
31808
- rowElement.style.height = `${nextHeight}px`;
31809
- rowElement.style.minHeight = `${nextHeight}px`;
31810
- rowElement.querySelectorAll("th,td").forEach((cell) => {
31811
- if (cell instanceof HTMLElement) {
31812
- cell.style.height = `${nextHeight}px`;
31813
- cell.style.minHeight = `${nextHeight}px`;
31814
- }
31815
- });
31816
- }
31817
- function clearPreviewRowHeight(rowElement) {
31818
- rowElement.style.height = "";
31819
- rowElement.style.minHeight = "";
31820
- rowElement.querySelectorAll("th,td").forEach((cell) => {
31821
- if (cell instanceof HTMLElement) {
31822
- cell.style.height = "";
31823
- cell.style.minHeight = "";
31824
- }
31825
- });
31826
- }
31827
- function findTableRowNodeInfo(view, rowElement) {
31828
- const firstCell = rowElement.querySelector("th,td");
31829
- if (!firstCell) return null;
31830
- const cellPos = view.posAtDOM(firstCell, 0);
31831
- const $pos = view.state.doc.resolve(cellPos);
31832
- for (let depth = $pos.depth; depth > 0; depth -= 1) {
31833
- const node = $pos.node(depth);
31834
- if (node.type.name === "tableRow") {
31835
- return {
31836
- pos: $pos.before(depth),
31837
- node
31838
- };
31839
- }
31840
- }
31841
- return null;
31842
- }
31843
- function resolveEventElement(target) {
31844
- if (target instanceof Element) return target;
31845
- if (target instanceof Node) return target.parentElement;
31846
- return null;
31847
- }
31848
- function getSelectionTableCell(view) {
31849
- const browserSelection = window.getSelection();
31850
- const anchorElement = resolveEventElement(browserSelection?.anchorNode ?? null);
31851
- const anchorCell = anchorElement?.closest?.("th,td");
31852
- if (anchorCell instanceof HTMLElement) {
31853
- return anchorCell;
31854
- }
31855
- const { from } = view.state.selection;
31856
- const domAtPos = view.domAtPos(from);
31857
- const element = resolveEventElement(domAtPos.node);
31858
- const cell = element?.closest?.("th,td");
31859
- return cell instanceof HTMLElement ? cell : null;
31860
- }
31861
- function isRowResizeHotspot(cell, clientX, clientY) {
31862
- const rect = cell.getBoundingClientRect();
31863
- const nearBottom = rect.bottom - clientY <= TABLE_RESIZE_HIT_ZONE;
31864
- const nearRight = rect.right - clientX <= TABLE_RESIZE_HIT_ZONE;
31865
- return nearBottom && !nearRight;
31866
- }
31867
- function isColumnResizeHotspot(cell, clientX, clientY) {
31868
- const rect = cell.getBoundingClientRect();
31869
- const nearRight = rect.right - clientX <= TABLE_RESIZE_HIT_ZONE;
31870
- const nearBottom = rect.bottom - clientY <= TABLE_RESIZE_HIT_ZONE;
31871
- return nearRight && !nearBottom;
31872
- }
31873
- function getRelativeBoundaryMetrics(surface, table, row, cell) {
31874
- const surfaceRect = surface.getBoundingClientRect();
31875
- const tableRect = table.getBoundingClientRect();
31876
- const rowRect = row.getBoundingClientRect();
31877
- const cellRect = cell.getBoundingClientRect();
31878
- return {
31879
- left: tableRect.left - surfaceRect.left + surface.scrollLeft,
31880
- top: tableRect.top - surfaceRect.top + surface.scrollTop,
31881
- width: tableRect.width,
31882
- height: tableRect.height,
31883
- rowBottom: rowRect.bottom - surfaceRect.top + surface.scrollTop,
31884
- columnRight: cellRect.right - surfaceRect.left + surface.scrollLeft
31885
- };
31886
- }
31887
- function getRelativeCellMetrics(surface, cell) {
31888
- const surfaceRect = surface.getBoundingClientRect();
31889
- const cellRect = cell.getBoundingClientRect();
31890
- return {
31891
- left: cellRect.left - surfaceRect.left + surface.scrollLeft,
31892
- top: cellRect.top - surfaceRect.top + surface.scrollTop,
31893
- width: cellRect.width,
31894
- height: cellRect.height
31895
- };
31896
- }
31897
- function getRelativeSelectedCellsMetrics(surface) {
31898
- const selectedCells = Array.from(
31899
- surface.querySelectorAll("td.selectedCell, th.selectedCell")
31900
- );
31901
- if (selectedCells.length === 0) {
31902
- return null;
31903
- }
31904
- const surfaceRect = surface.getBoundingClientRect();
31905
- let left = Number.POSITIVE_INFINITY;
31906
- let top = Number.POSITIVE_INFINITY;
31907
- let right = Number.NEGATIVE_INFINITY;
31908
- let bottom = Number.NEGATIVE_INFINITY;
31909
- selectedCells.forEach((cell) => {
31910
- const rect = cell.getBoundingClientRect();
31911
- left = Math.min(left, rect.left);
31912
- top = Math.min(top, rect.top);
31913
- right = Math.max(right, rect.right);
31914
- bottom = Math.max(bottom, rect.bottom);
31915
- });
31916
- return {
31917
- left: left - surfaceRect.left + surface.scrollLeft,
31918
- top: top - surfaceRect.top + surface.scrollTop,
31919
- width: right - left,
31920
- height: bottom - top
31921
- };
31922
- }
31923
- var UEditor = import_react52.default.forwardRef(({
31924
- content = "",
31925
- onChange,
31926
- onHtmlChange,
31927
- onJsonChange,
31928
- uploadImage,
31929
- uploadImageForSave,
31930
- uploadImageConcurrency = 3,
31931
- imageInsertMode = "base64",
31932
- maxImageFileSize,
31933
- allowedImageMimeTypes,
31934
- fallbackToDataUrl,
31935
- placeholder,
31936
- className,
31937
- editable = true,
31938
- autofocus = false,
31939
- showToolbar = true,
31940
- showBubbleMenu = true,
31941
- showFloatingMenu = false,
31942
- showCharacterCount = true,
31943
- maxCharacters,
31944
- minHeight = "200px",
31945
- maxHeight = "auto",
31946
- variant = "default",
31947
- fontFamilies,
31948
- fontSizes,
31949
- lineHeights,
31950
- letterSpacings
31951
- }, ref) => {
31952
- const t = useSmartTranslations("UEditor");
31953
- const effectivePlaceholder = placeholder ?? t("placeholder");
31954
- const inFlightPrepareRef = (0, import_react52.useRef)(null);
31955
- const lastAppliedContentRef = (0, import_react52.useRef)(content ?? "");
31908
+ // src/components/UEditor/editor-styles.ts
31909
+ var UEDITOR_PROSEMIRROR_CLASS_NAME = cn(
31910
+ "prose prose-sm sm:prose dark:prose-invert max-w-none",
31911
+ "focus:outline-none",
31912
+ "px-4 py-4",
31913
+ "[&_.is-editor-empty]:before:content-[attr(data-placeholder)]",
31914
+ "[&_.is-editor-empty]:before:text-muted-foreground/50",
31915
+ "[&_.is-editor-empty]:before:float-left",
31916
+ "[&_.is-editor-empty]:before:pointer-events-none",
31917
+ "[&_.is-editor-empty]:before:h-0",
31918
+ "[&_ul[data-type='taskList']]:list-none",
31919
+ "[&_ul[data-type='taskList']]:pl-0",
31920
+ "[&_ul[data-type='taskList']_li]:flex",
31921
+ "[&_ul[data-type='taskList']_li]:items-start",
31922
+ "[&_ul[data-type='taskList']_li]:gap-2",
31923
+ "[&_ul[data-type='taskList']_li>label]:mt-0.5",
31924
+ "[&_ul[data-type='taskList']_li>label>input]:w-4",
31925
+ "[&_ul[data-type='taskList']_li>label>input]:h-4",
31926
+ "[&_ul[data-type='taskList']_li>label>input]:rounded",
31927
+ "[&_ul[data-type='taskList']_li>label>input]:border-2",
31928
+ "[&_ul[data-type='taskList']_li>label>input]:border-primary/50",
31929
+ "[&_ul[data-type='taskList']_li>label>input]:accent-primary",
31930
+ "[&_pre]:bg-muted/40!",
31931
+ "[&_pre]:text-foreground!",
31932
+ "[&_pre]:border!",
31933
+ "[&_pre]:border-border/60!",
31934
+ "[&_pre_code]:bg-transparent!",
31935
+ "[&_.tableWrapper]:overflow-x-auto",
31936
+ "[&_.tableWrapper]:pb-1.5",
31937
+ "[&_.tableWrapper]:select-text",
31938
+ "[&_.tableWrapper]:[scrollbar-width:thin]",
31939
+ "[&_.tableWrapper]:[scrollbar-color:hsl(var(--border))_transparent]",
31940
+ "[&_.tableWrapper::-webkit-scrollbar]:h-2",
31941
+ "[&_.tableWrapper::-webkit-scrollbar]:w-2",
31942
+ "[&_.tableWrapper::-webkit-scrollbar-track]:rounded-full",
31943
+ "[&_.tableWrapper::-webkit-scrollbar-track]:bg-transparent",
31944
+ "[&_.tableWrapper::-webkit-scrollbar-thumb]:rounded-full",
31945
+ "[&_.tableWrapper::-webkit-scrollbar-thumb]:border",
31946
+ "[&_.tableWrapper::-webkit-scrollbar-thumb]:border-solid",
31947
+ "[&_.tableWrapper::-webkit-scrollbar-thumb]:border-transparent",
31948
+ "[&_.tableWrapper::-webkit-scrollbar-thumb]:bg-border/70",
31949
+ "[&_.tableWrapper::-webkit-scrollbar-thumb:hover]:bg-muted-foreground/45",
31950
+ "[&_table]:table-fixed",
31951
+ "[&_table]:overflow-hidden",
31952
+ "[&_table]:select-text",
31953
+ "[&_table[data-table-align]]:w-max",
31954
+ "[&_table[data-table-align]]:max-w-full",
31955
+ "[&_table[data-table-align='center']]:mx-auto",
31956
+ "[&_table[data-table-align='right']]:ml-auto",
31957
+ "[&_table[data-table-align='right']]:mr-0",
31958
+ "[&_td]:relative",
31959
+ "[&_td]:align-top",
31960
+ "[&_td]:box-border",
31961
+ "[&_td]:select-text",
31962
+ "[&_th]:relative",
31963
+ "[&_th]:align-top",
31964
+ "[&_th]:box-border",
31965
+ "[&_th]:select-text",
31966
+ "[&_.selectedCell]:after:content-['']",
31967
+ "[&_.selectedCell]:after:absolute",
31968
+ "[&_.selectedCell]:after:inset-0",
31969
+ "[&_.selectedCell]:after:z-[2]",
31970
+ "[&_.selectedCell]:after:bg-primary/15",
31971
+ "[&_.selectedCell]:after:pointer-events-none",
31972
+ "[&_.column-resize-handle]:pointer-events-auto",
31973
+ "[&_.column-resize-handle]:cursor-col-resize",
31974
+ "[&_.column-resize-handle]:absolute",
31975
+ "[&_.column-resize-handle]:top-[-1px]",
31976
+ "[&_.column-resize-handle]:bottom-[-1px]",
31977
+ "[&_.column-resize-handle]:right-[-5px]",
31978
+ "[&_.column-resize-handle]:z-10",
31979
+ "[&_.column-resize-handle]:w-2.5",
31980
+ "[&_.column-resize-handle]:bg-transparent",
31981
+ "[&_.column-resize-handle]:rounded-none",
31982
+ "[&_.column-resize-handle]:opacity-0",
31983
+ "[&_.column-resize-handle]:transition-opacity",
31984
+ "[&_.column-resize-handle]:after:absolute",
31985
+ "[&_.column-resize-handle]:after:top-0",
31986
+ "[&_.column-resize-handle]:after:bottom-0",
31987
+ "[&_.column-resize-handle]:after:left-1/2",
31988
+ "[&_.column-resize-handle]:after:w-0.5",
31989
+ "[&_.column-resize-handle]:after:-translate-x-1/2",
31990
+ "[&_.column-resize-handle]:after:rounded-full",
31991
+ "[&_.column-resize-handle]:after:bg-primary/75",
31992
+ "[&_.column-resize-handle]:after:content-['']",
31993
+ "[&.resize-cursor_.column-resize-handle]:opacity-100",
31994
+ "[&.resize-cursor_.column-resize-handle]:after:bg-primary",
31995
+ "[&.resize-cursor]:cursor-col-resize",
31996
+ "[&.resize-row-cursor]:cursor-row-resize",
31997
+ "[&_img.ProseMirror-selectednode]:ring-2",
31998
+ "[&_img.ProseMirror-selectednode]:ring-primary/60",
31999
+ "[&_img.ProseMirror-selectednode]:ring-offset-2",
32000
+ "[&_img.ProseMirror-selectednode]:ring-offset-background",
32001
+ "[&_hr]:border-t-2",
32002
+ "[&_hr]:border-primary/30",
32003
+ "[&_hr]:my-8",
32004
+ "[&_h1]:text-3xl",
32005
+ "[&_h1]:font-bold",
32006
+ "[&_h1]:mt-6",
32007
+ "[&_h1]:mb-4",
32008
+ "[&_h1]:text-foreground",
32009
+ "[&_h2]:text-2xl",
32010
+ "[&_h2]:font-semibold",
32011
+ "[&_h2]:mt-5",
32012
+ "[&_h2]:mb-3",
32013
+ "[&_h2]:text-foreground",
32014
+ "[&_h3]:text-xl",
32015
+ "[&_h3]:font-semibold",
32016
+ "[&_h3]:mt-4",
32017
+ "[&_h3]:mb-2",
32018
+ "[&_h3]:text-foreground",
32019
+ "[&_ul:not([data-type='taskList'])]:list-disc",
32020
+ "[&_ul:not([data-type='taskList'])]:pl-6",
32021
+ "[&_ul:not([data-type='taskList'])]:my-3",
32022
+ "[&_ol]:list-decimal",
32023
+ "[&_ol]:pl-6",
32024
+ "[&_ol]:my-3",
32025
+ "[&_li]:my-1",
32026
+ "[&_li]:pl-1",
32027
+ "[&_li_p]:my-0",
32028
+ "[&_blockquote]:border-l-4",
32029
+ "[&_blockquote]:border-primary",
32030
+ "[&_blockquote]:pl-4",
32031
+ "[&_blockquote]:py-2",
32032
+ "[&_blockquote]:my-4",
32033
+ "[&_blockquote]:bg-muted/30",
32034
+ "[&_blockquote]:rounded-r-lg",
32035
+ "[&_blockquote]:italic",
32036
+ "[&_blockquote]:text-muted-foreground",
32037
+ "[&_blockquote_p]:my-0",
32038
+ "[&_[data-image-layout='left']+p]:mt-1",
32039
+ "[&_[data-image-layout='left']+p]:min-h-[5rem]",
32040
+ "[&_[data-image-layout='right']+p]:mt-1",
32041
+ "[&_[data-image-layout='right']+p]:min-h-[5rem]",
32042
+ "max-md:[&_[data-image-layout='left']]:float-none",
32043
+ "max-md:[&_[data-image-layout='left']]:mr-0",
32044
+ "max-md:[&_[data-image-layout='left']]:ml-0",
32045
+ "max-md:[&_[data-image-layout='left']]:max-w-full",
32046
+ "max-md:[&_[data-image-layout='right']]:float-none",
32047
+ "max-md:[&_[data-image-layout='right']]:mr-0",
32048
+ "max-md:[&_[data-image-layout='right']]:ml-0",
32049
+ "max-md:[&_[data-image-layout='right']]:max-w-full",
32050
+ "max-md:[&_[data-image-layout='left']+p]:min-h-0",
32051
+ "max-md:[&_[data-image-layout='right']+p]:min-h-0"
32052
+ );
32053
+
32054
+ // src/components/UEditor/use-table-interactions.ts
32055
+ var import_react52 = __toESM(require("react"), 1);
32056
+ function useUEditorTableInteractions(editor) {
31956
32057
  const editorContentRef = (0, import_react52.useRef)(null);
31957
32058
  const tableColumnGuideRef = (0, import_react52.useRef)(null);
31958
32059
  const tableRowGuideRef = (0, import_react52.useRef)(null);
31959
32060
  const activeTableCellHighlightRef = (0, import_react52.useRef)(null);
31960
32061
  const hoveredTableCellRef = (0, import_react52.useRef)(null);
31961
32062
  const activeTableCellRef = (0, import_react52.useRef)(null);
32063
+ const tableLayoutSyncFrameRef = (0, import_react52.useRef)(null);
32064
+ const rowResizeCommitFrameRef = (0, import_react52.useRef)(null);
31962
32065
  const rowResizeStateRef = (0, import_react52.useRef)(null);
31963
32066
  const setEditorResizeCursor = import_react52.default.useCallback((cursor) => {
31964
32067
  const proseMirror = editorContentRef.current?.querySelector(".ProseMirror");
@@ -32000,6 +32103,14 @@ var UEditor = import_react52.default.forwardRef(({
32000
32103
  highlight.style.width = `${metrics.width}px`;
32001
32104
  highlight.style.height = `${metrics.height}px`;
32002
32105
  }, []);
32106
+ const scheduleTableLayoutSync = import_react52.default.useCallback(() => {
32107
+ if (tableLayoutSyncFrameRef.current !== null) return;
32108
+ tableLayoutSyncFrameRef.current = window.requestAnimationFrame(() => {
32109
+ tableLayoutSyncFrameRef.current = null;
32110
+ updateActiveCellHighlight(activeTableCellRef.current);
32111
+ editorContentRef.current?.dispatchEvent(new CustomEvent(UEDITOR_TABLE_LAYOUT_CHANGE_EVENT));
32112
+ });
32113
+ }, [updateActiveCellHighlight]);
32003
32114
  const setActiveTableCell = import_react52.default.useCallback((cell) => {
32004
32115
  if (activeTableCellRef.current === cell) return;
32005
32116
  activeTableCellRef.current = cell;
@@ -32041,239 +32152,49 @@ var UEditor = import_react52.default.forwardRef(({
32041
32152
  surface.classList.add("resize-row-cursor");
32042
32153
  setEditorResizeCursor("row-resize");
32043
32154
  }, [setEditorResizeCursor]);
32044
- const extensions = (0, import_react52.useMemo)(
32045
- () => buildUEditorExtensions({
32046
- placeholder: effectivePlaceholder,
32047
- translate: t,
32048
- maxCharacters,
32049
- uploadImage,
32050
- imageInsertMode,
32051
- maxImageFileSize,
32052
- allowedImageMimeTypes,
32053
- fallbackToDataUrl,
32054
- editable
32055
- }),
32056
- [effectivePlaceholder, t, maxCharacters, uploadImage, imageInsertMode, maxImageFileSize, allowedImageMimeTypes, fallbackToDataUrl, editable]
32057
- );
32058
- const editor = (0, import_react53.useEditor)({
32059
- immediatelyRender: false,
32060
- extensions,
32061
- content,
32062
- editable,
32063
- autofocus,
32064
- editorProps: {
32065
- handleDOMEvents: {
32066
- keydown: (_view, event) => {
32067
- if (!(event instanceof KeyboardEvent)) return false;
32068
- if (event.key === "ArrowLeft" || event.key === "ArrowRight" || event.key === "ArrowUp" || event.key === "ArrowDown") {
32069
- event.stopPropagation();
32070
- }
32071
- return false;
32072
- },
32073
- click: (view, event) => {
32074
- if (!(event instanceof MouseEvent)) return false;
32075
- if (event.button !== 0) return false;
32076
- const target = resolveEventElement(event.target);
32077
- const anchor = target?.closest?.("a[href]");
32078
- const href = anchor?.getAttribute("href") ?? "";
32079
- if (!href) return false;
32080
- if (!view.state.selection.empty) return false;
32081
- event.preventDefault();
32082
- event.stopPropagation();
32083
- window.open(href, "_blank", "noopener,noreferrer");
32084
- return true;
32085
- }
32086
- },
32087
- attributes: {
32088
- class: cn(
32089
- "prose prose-sm sm:prose dark:prose-invert max-w-none",
32090
- "focus:outline-none",
32091
- "px-4 py-4",
32092
- "[&_.is-editor-empty]:before:content-[attr(data-placeholder)]",
32093
- "[&_.is-editor-empty]:before:text-muted-foreground/50",
32094
- "[&_.is-editor-empty]:before:float-left",
32095
- "[&_.is-editor-empty]:before:pointer-events-none",
32096
- "[&_.is-editor-empty]:before:h-0",
32097
- "[&_ul[data-type='taskList']]:list-none",
32098
- "[&_ul[data-type='taskList']]:pl-0",
32099
- "[&_ul[data-type='taskList']_li]:flex",
32100
- "[&_ul[data-type='taskList']_li]:items-start",
32101
- "[&_ul[data-type='taskList']_li]:gap-2",
32102
- "[&_ul[data-type='taskList']_li>label]:mt-0.5",
32103
- "[&_ul[data-type='taskList']_li>label>input]:w-4",
32104
- "[&_ul[data-type='taskList']_li>label>input]:h-4",
32105
- "[&_ul[data-type='taskList']_li>label>input]:rounded",
32106
- "[&_ul[data-type='taskList']_li>label>input]:border-2",
32107
- "[&_ul[data-type='taskList']_li>label>input]:border-primary/50",
32108
- "[&_ul[data-type='taskList']_li>label>input]:accent-primary",
32109
- "[&_pre]:bg-muted/40!",
32110
- "[&_pre]:text-foreground!",
32111
- "[&_pre]:border!",
32112
- "[&_pre]:border-border/60!",
32113
- "[&_pre_code]:bg-transparent!",
32114
- "[&_.tableWrapper]:overflow-x-auto",
32115
- "[&_.tableWrapper]:pb-1.5",
32116
- "[&_.tableWrapper]:select-text",
32117
- "[&_.tableWrapper]:[scrollbar-width:thin]",
32118
- "[&_.tableWrapper]:[scrollbar-color:hsl(var(--border))_transparent]",
32119
- "[&_.tableWrapper::-webkit-scrollbar]:h-2",
32120
- "[&_.tableWrapper::-webkit-scrollbar]:w-2",
32121
- "[&_.tableWrapper::-webkit-scrollbar-track]:rounded-full",
32122
- "[&_.tableWrapper::-webkit-scrollbar-track]:bg-transparent",
32123
- "[&_.tableWrapper::-webkit-scrollbar-thumb]:rounded-full",
32124
- "[&_.tableWrapper::-webkit-scrollbar-thumb]:border",
32125
- "[&_.tableWrapper::-webkit-scrollbar-thumb]:border-solid",
32126
- "[&_.tableWrapper::-webkit-scrollbar-thumb]:border-transparent",
32127
- "[&_.tableWrapper::-webkit-scrollbar-thumb]:bg-border/70",
32128
- "[&_.tableWrapper::-webkit-scrollbar-thumb:hover]:bg-muted-foreground/45",
32129
- "[&_table]:table-fixed",
32130
- "[&_table]:overflow-hidden",
32131
- "[&_table]:select-text",
32132
- "[&_table[data-table-align]]:w-max",
32133
- "[&_table[data-table-align]]:max-w-full",
32134
- "[&_table[data-table-align='center']]:mx-auto",
32135
- "[&_table[data-table-align='right']]:ml-auto",
32136
- "[&_table[data-table-align='right']]:mr-0",
32137
- "[&_td]:relative",
32138
- "[&_td]:align-top",
32139
- "[&_td]:box-border",
32140
- "[&_td]:select-text",
32141
- "[&_th]:relative",
32142
- "[&_th]:align-top",
32143
- "[&_th]:box-border",
32144
- "[&_th]:select-text",
32145
- "[&_.selectedCell]:after:content-['']",
32146
- "[&_.selectedCell]:after:absolute",
32147
- "[&_.selectedCell]:after:inset-0",
32148
- "[&_.selectedCell]:after:z-[2]",
32149
- "[&_.selectedCell]:after:bg-primary/15",
32150
- "[&_.selectedCell]:after:pointer-events-none",
32151
- "[&_.column-resize-handle]:pointer-events-auto",
32152
- "[&_.column-resize-handle]:cursor-col-resize",
32153
- "[&_.column-resize-handle]:absolute",
32154
- "[&_.column-resize-handle]:top-[-1px]",
32155
- "[&_.column-resize-handle]:bottom-[-1px]",
32156
- "[&_.column-resize-handle]:right-[-5px]",
32157
- "[&_.column-resize-handle]:z-10",
32158
- "[&_.column-resize-handle]:w-2.5",
32159
- "[&_.column-resize-handle]:bg-transparent",
32160
- "[&_.column-resize-handle]:rounded-none",
32161
- "[&_.column-resize-handle]:opacity-0",
32162
- "[&_.column-resize-handle]:transition-opacity",
32163
- "[&_.column-resize-handle]:after:absolute",
32164
- "[&_.column-resize-handle]:after:top-0",
32165
- "[&_.column-resize-handle]:after:bottom-0",
32166
- "[&_.column-resize-handle]:after:left-1/2",
32167
- "[&_.column-resize-handle]:after:w-0.5",
32168
- "[&_.column-resize-handle]:after:-translate-x-1/2",
32169
- "[&_.column-resize-handle]:after:rounded-full",
32170
- "[&_.column-resize-handle]:after:bg-primary/75",
32171
- "[&_.column-resize-handle]:after:content-['']",
32172
- "[&.resize-cursor_.column-resize-handle]:opacity-100",
32173
- "[&.resize-cursor_.column-resize-handle]:after:bg-primary",
32174
- "[&.resize-cursor]:cursor-col-resize",
32175
- "[&.resize-row-cursor]:cursor-row-resize",
32176
- "[&_img.ProseMirror-selectednode]:ring-2",
32177
- "[&_img.ProseMirror-selectednode]:ring-primary/60",
32178
- "[&_img.ProseMirror-selectednode]:ring-offset-2",
32179
- "[&_img.ProseMirror-selectednode]:ring-offset-background",
32180
- "[&_hr]:border-t-2",
32181
- "[&_hr]:border-primary/30",
32182
- "[&_hr]:my-8",
32183
- "[&_h1]:text-3xl",
32184
- "[&_h1]:font-bold",
32185
- "[&_h1]:mt-6",
32186
- "[&_h1]:mb-4",
32187
- "[&_h1]:text-foreground",
32188
- "[&_h2]:text-2xl",
32189
- "[&_h2]:font-semibold",
32190
- "[&_h2]:mt-5",
32191
- "[&_h2]:mb-3",
32192
- "[&_h2]:text-foreground",
32193
- "[&_h3]:text-xl",
32194
- "[&_h3]:font-semibold",
32195
- "[&_h3]:mt-4",
32196
- "[&_h3]:mb-2",
32197
- "[&_h3]:text-foreground",
32198
- "[&_ul:not([data-type='taskList'])]:list-disc",
32199
- "[&_ul:not([data-type='taskList'])]:pl-6",
32200
- "[&_ul:not([data-type='taskList'])]:my-3",
32201
- "[&_ol]:list-decimal",
32202
- "[&_ol]:pl-6",
32203
- "[&_ol]:my-3",
32204
- "[&_li]:my-1",
32205
- "[&_li]:pl-1",
32206
- "[&_li_p]:my-0",
32207
- "[&_blockquote]:border-l-4",
32208
- "[&_blockquote]:border-primary",
32209
- "[&_blockquote]:pl-4",
32210
- "[&_blockquote]:py-2",
32211
- "[&_blockquote]:my-4",
32212
- "[&_blockquote]:bg-muted/30",
32213
- "[&_blockquote]:rounded-r-lg",
32214
- "[&_blockquote]:italic",
32215
- "[&_blockquote]:text-muted-foreground",
32216
- "[&_blockquote_p]:my-0",
32217
- "[&_[data-image-layout='left']+p]:mt-1",
32218
- "[&_[data-image-layout='left']+p]:min-h-[5rem]",
32219
- "[&_[data-image-layout='right']+p]:mt-1",
32220
- "[&_[data-image-layout='right']+p]:min-h-[5rem]",
32221
- "max-md:[&_[data-image-layout='left']]:float-none",
32222
- "max-md:[&_[data-image-layout='left']]:mr-0",
32223
- "max-md:[&_[data-image-layout='left']]:ml-0",
32224
- "max-md:[&_[data-image-layout='left']]:max-w-full",
32225
- "max-md:[&_[data-image-layout='right']]:float-none",
32226
- "max-md:[&_[data-image-layout='right']]:mr-0",
32227
- "max-md:[&_[data-image-layout='right']]:ml-0",
32228
- "max-md:[&_[data-image-layout='right']]:max-w-full",
32229
- "max-md:[&_[data-image-layout='left']+p]:min-h-0",
32230
- "max-md:[&_[data-image-layout='right']+p]:min-h-0"
32231
- )
32232
- }
32233
- },
32234
- onUpdate: ({ editor: editor2 }) => {
32235
- const html = editor2.getHTML();
32236
- onChange?.(html);
32237
- onHtmlChange?.(html);
32238
- onJsonChange?.(editor2.getJSON());
32155
+ const commitRowResizePreview = import_react52.default.useCallback(() => {
32156
+ if (!editor) return;
32157
+ const state = rowResizeStateRef.current;
32158
+ if (!state) return;
32159
+ const nextHeight = state.pendingHeight;
32160
+ if (nextHeight === state.previewHeight) {
32161
+ document.body.style.cursor = "row-resize";
32162
+ showRowGuide(state.tableElement, state.rowElement, state.cellElement);
32163
+ scheduleTableLayoutSync();
32164
+ return;
32239
32165
  }
32240
- });
32166
+ state.previewHeight = nextHeight;
32167
+ const tr = editor.view.state.tr;
32168
+ tr.setNodeMarkup(state.rowPos, void 0, {
32169
+ ...state.rowNode.attrs,
32170
+ rowHeight: nextHeight
32171
+ });
32172
+ tr.setMeta("addToHistory", false);
32173
+ editor.view.dispatch(tr);
32174
+ state.rowNode = editor.view.state.doc.nodeAt(state.rowPos) ?? state.rowNode;
32175
+ const refreshedRow = state.tableElement.rows.item(state.rowElement.rowIndex);
32176
+ if (refreshedRow instanceof HTMLTableRowElement) {
32177
+ state.rowElement = refreshedRow;
32178
+ const refreshedCell = refreshedRow.cells.item(state.cellIndex);
32179
+ if (refreshedCell instanceof HTMLTableCellElement) {
32180
+ state.cellElement = refreshedCell;
32181
+ }
32182
+ }
32183
+ document.body.style.cursor = "row-resize";
32184
+ showRowGuide(state.tableElement, state.rowElement, state.cellElement);
32185
+ scheduleTableLayoutSync();
32186
+ }, [editor, scheduleTableLayoutSync, showRowGuide]);
32187
+ const scheduleRowResizeCommit = import_react52.default.useCallback(() => {
32188
+ if (rowResizeCommitFrameRef.current !== null) return;
32189
+ rowResizeCommitFrameRef.current = window.requestAnimationFrame(() => {
32190
+ rowResizeCommitFrameRef.current = null;
32191
+ commitRowResizePreview();
32192
+ });
32193
+ }, [commitRowResizePreview]);
32241
32194
  const syncActiveTableCellFromSelection = import_react52.default.useCallback(() => {
32242
32195
  if (!editor) return;
32243
32196
  setActiveTableCell(getSelectionTableCell(editor.view));
32244
32197
  }, [editor, setActiveTableCell]);
32245
- (0, import_react52.useImperativeHandle)(
32246
- ref,
32247
- () => ({
32248
- prepareContentForSave: async ({ throwOnError = false } = {}) => {
32249
- if (!inFlightPrepareRef.current) {
32250
- const htmlSnapshot = editor?.getHTML() ?? content ?? "";
32251
- inFlightPrepareRef.current = prepareUEditorContentForSave({
32252
- html: htmlSnapshot,
32253
- uploadImageForSave,
32254
- uploadConcurrency: uploadImageConcurrency
32255
- }).finally(() => {
32256
- inFlightPrepareRef.current = null;
32257
- });
32258
- }
32259
- const result = await inFlightPrepareRef.current;
32260
- if (throwOnError && result.errors.length > 0) {
32261
- throw new UEditorPrepareContentForSaveError(result);
32262
- }
32263
- return result;
32264
- }
32265
- }),
32266
- [content, editor, uploadImageForSave, uploadImageConcurrency]
32267
- );
32268
- (0, import_react52.useEffect)(() => {
32269
- if (!editor) return;
32270
- const nextContent = content ?? "";
32271
- if (lastAppliedContentRef.current === nextContent) return;
32272
- lastAppliedContentRef.current = nextContent;
32273
- if (editor.getHTML() !== nextContent) {
32274
- editor.commands.setContent(nextContent, { emitUpdate: false });
32275
- }
32276
- }, [content, editor]);
32277
32198
  (0, import_react52.useEffect)(() => {
32278
32199
  if (!editor) return void 0;
32279
32200
  const proseMirror = editor.view.dom;
@@ -32363,6 +32284,7 @@ var UEditor = import_react52.default.forwardRef(({
32363
32284
  setHoveredTableCell(cell);
32364
32285
  const rowInfo = findTableRowNodeInfo(editor.view, row);
32365
32286
  if (!rowInfo) return;
32287
+ const startHeight = row.getBoundingClientRect().height;
32366
32288
  rowResizeStateRef.current = {
32367
32289
  rowElement: row,
32368
32290
  tableElement: table,
@@ -32371,8 +32293,9 @@ var UEditor = import_react52.default.forwardRef(({
32371
32293
  rowPos: rowInfo.pos,
32372
32294
  rowNode: rowInfo.node,
32373
32295
  startY: event.clientY,
32374
- startHeight: row.getBoundingClientRect().height,
32375
- previewHeight: row.getBoundingClientRect().height
32296
+ startHeight,
32297
+ previewHeight: startHeight,
32298
+ pendingHeight: startHeight
32376
32299
  };
32377
32300
  showRowGuide(table, row, cell);
32378
32301
  document.body.style.cursor = "row-resize";
@@ -32386,15 +32309,14 @@ var UEditor = import_react52.default.forwardRef(({
32386
32309
  MIN_TABLE_ROW_HEIGHT,
32387
32310
  Math.round(state.startHeight + (event.clientY - state.startY))
32388
32311
  );
32389
- if (nextHeight === state.previewHeight) {
32312
+ if (nextHeight === state.pendingHeight) {
32390
32313
  document.body.style.cursor = "row-resize";
32391
32314
  showRowGuide(state.tableElement, state.rowElement, state.cellElement);
32392
32315
  return;
32393
32316
  }
32394
- state.previewHeight = nextHeight;
32395
- applyPreviewRowHeight(state.rowElement, nextHeight);
32317
+ state.pendingHeight = nextHeight;
32396
32318
  document.body.style.cursor = "row-resize";
32397
- showRowGuide(state.tableElement, state.rowElement, state.cellElement);
32319
+ scheduleRowResizeCommit();
32398
32320
  };
32399
32321
  const handlePointerUp = (event) => {
32400
32322
  const state = rowResizeStateRef.current;
@@ -32403,11 +32325,17 @@ var UEditor = import_react52.default.forwardRef(({
32403
32325
  MIN_TABLE_ROW_HEIGHT,
32404
32326
  Math.round(state.startHeight + (event.clientY - state.startY))
32405
32327
  );
32406
- const rowNode = editor.view.state.doc.nodeAt(state.rowPos) ?? state.rowNode;
32407
- clearPreviewRowHeight(state.rowElement);
32328
+ state.pendingHeight = nextHeight;
32329
+ if (rowResizeCommitFrameRef.current !== null) {
32330
+ window.cancelAnimationFrame(rowResizeCommitFrameRef.current);
32331
+ rowResizeCommitFrameRef.current = null;
32332
+ }
32333
+ commitRowResizePreview();
32334
+ const latestState = rowResizeStateRef.current ?? state;
32335
+ const rowNode = editor.view.state.doc.nodeAt(latestState.rowPos) ?? latestState.rowNode;
32408
32336
  if (rowNode.attrs.rowHeight !== nextHeight) {
32409
32337
  const tr = editor.view.state.tr;
32410
- tr.setNodeMarkup(state.rowPos, void 0, {
32338
+ tr.setNodeMarkup(latestState.rowPos, void 0, {
32411
32339
  ...rowNode.attrs,
32412
32340
  rowHeight: nextHeight
32413
32341
  });
@@ -32417,15 +32345,20 @@ var UEditor = import_react52.default.forwardRef(({
32417
32345
  document.body.style.cursor = "";
32418
32346
  clearHoveredTableCell();
32419
32347
  clearAllTableResizeHover();
32348
+ scheduleTableLayoutSync();
32420
32349
  };
32421
32350
  const handleWindowBlur = () => {
32422
32351
  const state = rowResizeStateRef.current;
32423
32352
  if (!state) return;
32424
- clearPreviewRowHeight(state.rowElement);
32353
+ if (rowResizeCommitFrameRef.current !== null) {
32354
+ window.cancelAnimationFrame(rowResizeCommitFrameRef.current);
32355
+ rowResizeCommitFrameRef.current = null;
32356
+ }
32425
32357
  rowResizeStateRef.current = null;
32426
32358
  document.body.style.cursor = "";
32427
32359
  clearHoveredTableCell();
32428
32360
  clearAllTableResizeHover();
32361
+ scheduleTableLayoutSync();
32429
32362
  };
32430
32363
  proseMirror.addEventListener("mousemove", handleEditorMouseMove);
32431
32364
  proseMirror.addEventListener("mouseleave", handleEditorMouseLeave);
@@ -32464,13 +32397,156 @@ var UEditor = import_react52.default.forwardRef(({
32464
32397
  editor.off("selectionUpdate", syncActiveTableCellFromSelection);
32465
32398
  editor.off("focus", syncActiveTableCellFromSelection);
32466
32399
  window.clearTimeout(selectionSyncTimeoutId);
32400
+ if (tableLayoutSyncFrameRef.current !== null) {
32401
+ window.cancelAnimationFrame(tableLayoutSyncFrameRef.current);
32402
+ tableLayoutSyncFrameRef.current = null;
32403
+ }
32404
+ if (rowResizeCommitFrameRef.current !== null) {
32405
+ window.cancelAnimationFrame(rowResizeCommitFrameRef.current);
32406
+ rowResizeCommitFrameRef.current = null;
32407
+ }
32467
32408
  document.body.style.cursor = "";
32468
32409
  clearActiveTableCell();
32469
32410
  clearHoveredTableCell();
32470
32411
  clearAllTableResizeHover();
32471
32412
  rowResizeStateRef.current = null;
32472
32413
  };
32473
- }, [clearActiveTableCell, clearAllTableResizeHover, clearHoveredTableCell, editor, hideColumnGuide, hideRowGuide, setHoveredTableCell, showColumnGuide, showRowGuide, syncActiveTableCellFromSelection, updateActiveCellHighlight]);
32414
+ }, [clearActiveTableCell, clearAllTableResizeHover, clearHoveredTableCell, commitRowResizePreview, editor, hideColumnGuide, hideRowGuide, scheduleRowResizeCommit, scheduleTableLayoutSync, setHoveredTableCell, showColumnGuide, showRowGuide, syncActiveTableCellFromSelection, updateActiveCellHighlight]);
32415
+ return {
32416
+ editorContentRef,
32417
+ tableColumnGuideRef,
32418
+ tableRowGuideRef,
32419
+ activeTableCellHighlightRef
32420
+ };
32421
+ }
32422
+
32423
+ // src/components/UEditor/UEditor.tsx
32424
+ var import_jsx_runtime84 = require("react/jsx-runtime");
32425
+ var UEditor = import_react53.default.forwardRef(({
32426
+ content = "",
32427
+ onChange,
32428
+ onHtmlChange,
32429
+ onJsonChange,
32430
+ uploadImage,
32431
+ uploadImageForSave,
32432
+ uploadImageConcurrency = 3,
32433
+ imageInsertMode = "base64",
32434
+ maxImageFileSize,
32435
+ allowedImageMimeTypes,
32436
+ fallbackToDataUrl,
32437
+ placeholder,
32438
+ className,
32439
+ editable = true,
32440
+ autofocus = false,
32441
+ showToolbar = true,
32442
+ showBubbleMenu = true,
32443
+ showFloatingMenu = false,
32444
+ showCharacterCount = true,
32445
+ maxCharacters,
32446
+ minHeight = "200px",
32447
+ maxHeight = "auto",
32448
+ variant = "default",
32449
+ fontFamilies,
32450
+ fontSizes,
32451
+ lineHeights,
32452
+ letterSpacings
32453
+ }, ref) => {
32454
+ const t = useSmartTranslations("UEditor");
32455
+ const effectivePlaceholder = placeholder ?? t("placeholder");
32456
+ const inFlightPrepareRef = (0, import_react53.useRef)(null);
32457
+ const lastAppliedContentRef = (0, import_react53.useRef)(content ?? "");
32458
+ const extensions = (0, import_react53.useMemo)(
32459
+ () => buildUEditorExtensions({
32460
+ placeholder: effectivePlaceholder,
32461
+ translate: t,
32462
+ maxCharacters,
32463
+ uploadImage,
32464
+ imageInsertMode,
32465
+ maxImageFileSize,
32466
+ allowedImageMimeTypes,
32467
+ fallbackToDataUrl,
32468
+ editable
32469
+ }),
32470
+ [effectivePlaceholder, t, maxCharacters, uploadImage, imageInsertMode, maxImageFileSize, allowedImageMimeTypes, fallbackToDataUrl, editable]
32471
+ );
32472
+ const editor = (0, import_react54.useEditor)({
32473
+ immediatelyRender: false,
32474
+ extensions,
32475
+ content,
32476
+ editable,
32477
+ autofocus,
32478
+ editorProps: {
32479
+ handleDOMEvents: {
32480
+ keydown: (_view, event) => {
32481
+ if (!(event instanceof KeyboardEvent)) return false;
32482
+ if (event.key === "ArrowLeft" || event.key === "ArrowRight" || event.key === "ArrowUp" || event.key === "ArrowDown") {
32483
+ event.stopPropagation();
32484
+ }
32485
+ return false;
32486
+ },
32487
+ click: (view, event) => {
32488
+ if (!(event instanceof MouseEvent)) return false;
32489
+ if (event.button !== 0) return false;
32490
+ const target = resolveEventElement(event.target);
32491
+ const anchor = target?.closest?.("a[href]");
32492
+ const href = anchor?.getAttribute("href") ?? "";
32493
+ if (!href) return false;
32494
+ if (!view.state.selection.empty) return false;
32495
+ event.preventDefault();
32496
+ event.stopPropagation();
32497
+ window.open(href, "_blank", "noopener,noreferrer");
32498
+ return true;
32499
+ }
32500
+ },
32501
+ attributes: {
32502
+ class: UEDITOR_PROSEMIRROR_CLASS_NAME
32503
+ }
32504
+ },
32505
+ onUpdate: ({ editor: editor2 }) => {
32506
+ const html = editor2.getHTML();
32507
+ onChange?.(html);
32508
+ onHtmlChange?.(html);
32509
+ onJsonChange?.(editor2.getJSON());
32510
+ }
32511
+ });
32512
+ const {
32513
+ editorContentRef,
32514
+ tableColumnGuideRef,
32515
+ tableRowGuideRef,
32516
+ activeTableCellHighlightRef
32517
+ } = useUEditorTableInteractions(editor);
32518
+ (0, import_react53.useImperativeHandle)(
32519
+ ref,
32520
+ () => ({
32521
+ prepareContentForSave: async ({ throwOnError = false } = {}) => {
32522
+ if (!inFlightPrepareRef.current) {
32523
+ const htmlSnapshot = editor?.getHTML() ?? content ?? "";
32524
+ inFlightPrepareRef.current = prepareUEditorContentForSave({
32525
+ html: htmlSnapshot,
32526
+ uploadImageForSave,
32527
+ uploadConcurrency: uploadImageConcurrency
32528
+ }).finally(() => {
32529
+ inFlightPrepareRef.current = null;
32530
+ });
32531
+ }
32532
+ const result = await inFlightPrepareRef.current;
32533
+ if (throwOnError && result.errors.length > 0) {
32534
+ throw new UEditorPrepareContentForSaveError(result);
32535
+ }
32536
+ return result;
32537
+ }
32538
+ }),
32539
+ [content, editor, uploadImageForSave, uploadImageConcurrency]
32540
+ );
32541
+ (0, import_react53.useEffect)(() => {
32542
+ if (!editor) return;
32543
+ const nextContent = content ?? "";
32544
+ if (lastAppliedContentRef.current === nextContent) return;
32545
+ lastAppliedContentRef.current = nextContent;
32546
+ if (editor.getHTML() !== nextContent) {
32547
+ editor.commands.setContent(nextContent, { emitUpdate: false });
32548
+ }
32549
+ }, [content, editor]);
32474
32550
  if (!editor) {
32475
32551
  return /* @__PURE__ */ (0, import_jsx_runtime84.jsx)(
32476
32552
  "div",
@@ -32553,7 +32629,7 @@ var UEditor = import_react52.default.forwardRef(({
32553
32629
  ),
32554
32630
  editable && /* @__PURE__ */ (0, import_jsx_runtime84.jsx)(TableControls, { editor, containerRef: editorContentRef }),
32555
32631
  /* @__PURE__ */ (0, import_jsx_runtime84.jsx)(
32556
- import_react53.EditorContent,
32632
+ import_react54.EditorContent,
32557
32633
  {
32558
32634
  editor,
32559
32635
  className: "min-h-full"