@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.js CHANGED
@@ -23109,7 +23109,7 @@ function useLocale2() {
23109
23109
  }
23110
23110
 
23111
23111
  // src/components/UEditor/UEditor.tsx
23112
- import React74, { useEffect as useEffect35, useImperativeHandle as useImperativeHandle3, useMemo as useMemo24, useRef as useRef31 } from "react";
23112
+ import React75, { useEffect as useEffect36, useImperativeHandle as useImperativeHandle3, useMemo as useMemo24, useRef as useRef32 } from "react";
23113
23113
  import { useEditor, EditorContent } from "@tiptap/react";
23114
23114
 
23115
23115
  // src/components/UEditor/extensions.ts
@@ -30715,6 +30715,111 @@ import {
30715
30715
  Table as TableIcon2,
30716
30716
  Trash2 as Trash24
30717
30717
  } from "lucide-react";
30718
+
30719
+ // src/components/UEditor/table-dom-utils.ts
30720
+ var MIN_TABLE_ROW_HEIGHT = 36;
30721
+ var COLUMN_RESIZE_LINE_THICKNESS = 2;
30722
+ var ROW_RESIZE_LINE_THICKNESS = 2;
30723
+ var UEDITOR_TABLE_LAYOUT_CHANGE_EVENT = "ueditor-table-layout-change";
30724
+ var TABLE_RESIZE_HIT_ZONE = 10;
30725
+ function findTableRowNodeInfo(view, rowElement) {
30726
+ const firstCell = rowElement.querySelector("th,td");
30727
+ if (!firstCell) return null;
30728
+ const cellPos = view.posAtDOM(firstCell, 0);
30729
+ const $pos = view.state.doc.resolve(cellPos);
30730
+ for (let depth = $pos.depth; depth > 0; depth -= 1) {
30731
+ const node = $pos.node(depth);
30732
+ if (node.type.name === "tableRow") {
30733
+ return {
30734
+ pos: $pos.before(depth),
30735
+ node
30736
+ };
30737
+ }
30738
+ }
30739
+ return null;
30740
+ }
30741
+ function resolveEventElement(target) {
30742
+ if (target instanceof Element) return target;
30743
+ if (target instanceof Node) return target.parentElement;
30744
+ return null;
30745
+ }
30746
+ function getSelectionTableCell(view) {
30747
+ const browserSelection = window.getSelection();
30748
+ const anchorElement = resolveEventElement(browserSelection?.anchorNode ?? null);
30749
+ const anchorCell = anchorElement?.closest?.("th,td");
30750
+ if (anchorCell instanceof HTMLElement) {
30751
+ return anchorCell;
30752
+ }
30753
+ const { from } = view.state.selection;
30754
+ const domAtPos = view.domAtPos(from);
30755
+ const element = resolveEventElement(domAtPos.node);
30756
+ const cell = element?.closest?.("th,td");
30757
+ return cell instanceof HTMLElement ? cell : null;
30758
+ }
30759
+ function isRowResizeHotspot(cell, clientX, clientY) {
30760
+ const rect = cell.getBoundingClientRect();
30761
+ const nearBottom = rect.bottom - clientY <= TABLE_RESIZE_HIT_ZONE;
30762
+ const nearRight = rect.right - clientX <= TABLE_RESIZE_HIT_ZONE;
30763
+ return nearBottom && !nearRight;
30764
+ }
30765
+ function isColumnResizeHotspot(cell, clientX, clientY) {
30766
+ const rect = cell.getBoundingClientRect();
30767
+ const nearRight = rect.right - clientX <= TABLE_RESIZE_HIT_ZONE;
30768
+ const nearBottom = rect.bottom - clientY <= TABLE_RESIZE_HIT_ZONE;
30769
+ return nearRight && !nearBottom;
30770
+ }
30771
+ function getRelativeBoundaryMetrics(surface, table, row, cell) {
30772
+ const surfaceRect = surface.getBoundingClientRect();
30773
+ const tableRect = table.getBoundingClientRect();
30774
+ const rowRect = row.getBoundingClientRect();
30775
+ const cellRect = cell.getBoundingClientRect();
30776
+ return {
30777
+ left: tableRect.left - surfaceRect.left + surface.scrollLeft,
30778
+ top: tableRect.top - surfaceRect.top + surface.scrollTop,
30779
+ width: tableRect.width,
30780
+ height: tableRect.height,
30781
+ rowBottom: rowRect.bottom - surfaceRect.top + surface.scrollTop,
30782
+ columnRight: cellRect.right - surfaceRect.left + surface.scrollLeft
30783
+ };
30784
+ }
30785
+ function getRelativeCellMetrics(surface, cell) {
30786
+ const surfaceRect = surface.getBoundingClientRect();
30787
+ const cellRect = cell.getBoundingClientRect();
30788
+ return {
30789
+ left: cellRect.left - surfaceRect.left + surface.scrollLeft,
30790
+ top: cellRect.top - surfaceRect.top + surface.scrollTop,
30791
+ width: cellRect.width,
30792
+ height: cellRect.height
30793
+ };
30794
+ }
30795
+ function getRelativeSelectedCellsMetrics(surface) {
30796
+ const selectedCells = Array.from(
30797
+ surface.querySelectorAll("td.selectedCell, th.selectedCell")
30798
+ );
30799
+ if (selectedCells.length === 0) {
30800
+ return null;
30801
+ }
30802
+ const surfaceRect = surface.getBoundingClientRect();
30803
+ let left = Number.POSITIVE_INFINITY;
30804
+ let top = Number.POSITIVE_INFINITY;
30805
+ let right = Number.NEGATIVE_INFINITY;
30806
+ let bottom = Number.NEGATIVE_INFINITY;
30807
+ selectedCells.forEach((cell) => {
30808
+ const rect = cell.getBoundingClientRect();
30809
+ left = Math.min(left, rect.left);
30810
+ top = Math.min(top, rect.top);
30811
+ right = Math.max(right, rect.right);
30812
+ bottom = Math.max(bottom, rect.bottom);
30813
+ });
30814
+ return {
30815
+ left: left - surfaceRect.left + surface.scrollLeft,
30816
+ top: top - surfaceRect.top + surface.scrollTop,
30817
+ width: right - left,
30818
+ height: bottom - top
30819
+ };
30820
+ }
30821
+
30822
+ // src/components/UEditor/table-controls.tsx
30718
30823
  import { Fragment as Fragment27, jsx as jsx82, jsxs as jsxs70 } from "react/jsx-runtime";
30719
30824
  var FALLBACK_TABLE_ROW_HEIGHT = 44;
30720
30825
  var FALLBACK_TABLE_COLUMN_WIDTH = 160;
@@ -31014,6 +31119,7 @@ function TableControls({ editor, containerRef }) {
31014
31119
  surface.addEventListener("mouseover", handleSurfaceMouseMove);
31015
31120
  surface.addEventListener("mousemove", handleSurfaceMouseMove);
31016
31121
  surface.addEventListener("scroll", refreshCurrentLayout, { passive: true });
31122
+ surface.addEventListener(UEDITOR_TABLE_LAYOUT_CHANGE_EVENT, refreshCurrentLayout);
31017
31123
  window.addEventListener("resize", refreshCurrentLayout);
31018
31124
  editor.on("selectionUpdate", syncFromSelection);
31019
31125
  editor.on("update", refreshCurrentLayout);
@@ -31025,6 +31131,7 @@ function TableControls({ editor, containerRef }) {
31025
31131
  surface.removeEventListener("mouseover", handleSurfaceMouseMove);
31026
31132
  surface.removeEventListener("mousemove", handleSurfaceMouseMove);
31027
31133
  surface.removeEventListener("scroll", refreshCurrentLayout);
31134
+ surface.removeEventListener(UEDITOR_TABLE_LAYOUT_CHANGE_EVENT, refreshCurrentLayout);
31028
31135
  window.removeEventListener("resize", refreshCurrentLayout);
31029
31136
  editor.off("selectionUpdate", syncFromSelection);
31030
31137
  editor.off("update", refreshCurrentLayout);
@@ -31708,167 +31815,163 @@ function TableControls({ editor, containerRef }) {
31708
31815
  ] });
31709
31816
  }
31710
31817
 
31711
- // src/components/UEditor/UEditor.tsx
31712
- import { jsx as jsx83, jsxs as jsxs71 } from "react/jsx-runtime";
31713
- var TABLE_RESIZE_HIT_ZONE = 10;
31714
- var MIN_TABLE_ROW_HEIGHT = 36;
31715
- var COLUMN_RESIZE_LINE_THICKNESS = 2;
31716
- var ROW_RESIZE_LINE_THICKNESS = 2;
31717
- function applyPreviewRowHeight(rowElement, nextHeight) {
31718
- rowElement.style.height = `${nextHeight}px`;
31719
- rowElement.style.minHeight = `${nextHeight}px`;
31720
- rowElement.querySelectorAll("th,td").forEach((cell) => {
31721
- if (cell instanceof HTMLElement) {
31722
- cell.style.height = `${nextHeight}px`;
31723
- cell.style.minHeight = `${nextHeight}px`;
31724
- }
31725
- });
31726
- }
31727
- function clearPreviewRowHeight(rowElement) {
31728
- rowElement.style.height = "";
31729
- rowElement.style.minHeight = "";
31730
- rowElement.querySelectorAll("th,td").forEach((cell) => {
31731
- if (cell instanceof HTMLElement) {
31732
- cell.style.height = "";
31733
- cell.style.minHeight = "";
31734
- }
31735
- });
31736
- }
31737
- function findTableRowNodeInfo(view, rowElement) {
31738
- const firstCell = rowElement.querySelector("th,td");
31739
- if (!firstCell) return null;
31740
- const cellPos = view.posAtDOM(firstCell, 0);
31741
- const $pos = view.state.doc.resolve(cellPos);
31742
- for (let depth = $pos.depth; depth > 0; depth -= 1) {
31743
- const node = $pos.node(depth);
31744
- if (node.type.name === "tableRow") {
31745
- return {
31746
- pos: $pos.before(depth),
31747
- node
31748
- };
31749
- }
31750
- }
31751
- return null;
31752
- }
31753
- function resolveEventElement(target) {
31754
- if (target instanceof Element) return target;
31755
- if (target instanceof Node) return target.parentElement;
31756
- return null;
31757
- }
31758
- function getSelectionTableCell(view) {
31759
- const browserSelection = window.getSelection();
31760
- const anchorElement = resolveEventElement(browserSelection?.anchorNode ?? null);
31761
- const anchorCell = anchorElement?.closest?.("th,td");
31762
- if (anchorCell instanceof HTMLElement) {
31763
- return anchorCell;
31764
- }
31765
- const { from } = view.state.selection;
31766
- const domAtPos = view.domAtPos(from);
31767
- const element = resolveEventElement(domAtPos.node);
31768
- const cell = element?.closest?.("th,td");
31769
- return cell instanceof HTMLElement ? cell : null;
31770
- }
31771
- function isRowResizeHotspot(cell, clientX, clientY) {
31772
- const rect = cell.getBoundingClientRect();
31773
- const nearBottom = rect.bottom - clientY <= TABLE_RESIZE_HIT_ZONE;
31774
- const nearRight = rect.right - clientX <= TABLE_RESIZE_HIT_ZONE;
31775
- return nearBottom && !nearRight;
31776
- }
31777
- function isColumnResizeHotspot(cell, clientX, clientY) {
31778
- const rect = cell.getBoundingClientRect();
31779
- const nearRight = rect.right - clientX <= TABLE_RESIZE_HIT_ZONE;
31780
- const nearBottom = rect.bottom - clientY <= TABLE_RESIZE_HIT_ZONE;
31781
- return nearRight && !nearBottom;
31782
- }
31783
- function getRelativeBoundaryMetrics(surface, table, row, cell) {
31784
- const surfaceRect = surface.getBoundingClientRect();
31785
- const tableRect = table.getBoundingClientRect();
31786
- const rowRect = row.getBoundingClientRect();
31787
- const cellRect = cell.getBoundingClientRect();
31788
- return {
31789
- left: tableRect.left - surfaceRect.left + surface.scrollLeft,
31790
- top: tableRect.top - surfaceRect.top + surface.scrollTop,
31791
- width: tableRect.width,
31792
- height: tableRect.height,
31793
- rowBottom: rowRect.bottom - surfaceRect.top + surface.scrollTop,
31794
- columnRight: cellRect.right - surfaceRect.left + surface.scrollLeft
31795
- };
31796
- }
31797
- function getRelativeCellMetrics(surface, cell) {
31798
- const surfaceRect = surface.getBoundingClientRect();
31799
- const cellRect = cell.getBoundingClientRect();
31800
- return {
31801
- left: cellRect.left - surfaceRect.left + surface.scrollLeft,
31802
- top: cellRect.top - surfaceRect.top + surface.scrollTop,
31803
- width: cellRect.width,
31804
- height: cellRect.height
31805
- };
31806
- }
31807
- function getRelativeSelectedCellsMetrics(surface) {
31808
- const selectedCells = Array.from(
31809
- surface.querySelectorAll("td.selectedCell, th.selectedCell")
31810
- );
31811
- if (selectedCells.length === 0) {
31812
- return null;
31813
- }
31814
- const surfaceRect = surface.getBoundingClientRect();
31815
- let left = Number.POSITIVE_INFINITY;
31816
- let top = Number.POSITIVE_INFINITY;
31817
- let right = Number.NEGATIVE_INFINITY;
31818
- let bottom = Number.NEGATIVE_INFINITY;
31819
- selectedCells.forEach((cell) => {
31820
- const rect = cell.getBoundingClientRect();
31821
- left = Math.min(left, rect.left);
31822
- top = Math.min(top, rect.top);
31823
- right = Math.max(right, rect.right);
31824
- bottom = Math.max(bottom, rect.bottom);
31825
- });
31826
- return {
31827
- left: left - surfaceRect.left + surface.scrollLeft,
31828
- top: top - surfaceRect.top + surface.scrollTop,
31829
- width: right - left,
31830
- height: bottom - top
31831
- };
31832
- }
31833
- var UEditor = React74.forwardRef(({
31834
- content = "",
31835
- onChange,
31836
- onHtmlChange,
31837
- onJsonChange,
31838
- uploadImage,
31839
- uploadImageForSave,
31840
- uploadImageConcurrency = 3,
31841
- imageInsertMode = "base64",
31842
- maxImageFileSize,
31843
- allowedImageMimeTypes,
31844
- fallbackToDataUrl,
31845
- placeholder,
31846
- className,
31847
- editable = true,
31848
- autofocus = false,
31849
- showToolbar = true,
31850
- showBubbleMenu = true,
31851
- showFloatingMenu = false,
31852
- showCharacterCount = true,
31853
- maxCharacters,
31854
- minHeight = "200px",
31855
- maxHeight = "auto",
31856
- variant = "default",
31857
- fontFamilies,
31858
- fontSizes,
31859
- lineHeights,
31860
- letterSpacings
31861
- }, ref) => {
31862
- const t = useSmartTranslations("UEditor");
31863
- const effectivePlaceholder = placeholder ?? t("placeholder");
31864
- const inFlightPrepareRef = useRef31(null);
31865
- const lastAppliedContentRef = useRef31(content ?? "");
31818
+ // src/components/UEditor/editor-styles.ts
31819
+ var UEDITOR_PROSEMIRROR_CLASS_NAME = cn(
31820
+ "prose prose-sm sm:prose dark:prose-invert max-w-none",
31821
+ "focus:outline-none",
31822
+ "px-4 py-4",
31823
+ "[&_.is-editor-empty]:before:content-[attr(data-placeholder)]",
31824
+ "[&_.is-editor-empty]:before:text-muted-foreground/50",
31825
+ "[&_.is-editor-empty]:before:float-left",
31826
+ "[&_.is-editor-empty]:before:pointer-events-none",
31827
+ "[&_.is-editor-empty]:before:h-0",
31828
+ "[&_ul[data-type='taskList']]:list-none",
31829
+ "[&_ul[data-type='taskList']]:pl-0",
31830
+ "[&_ul[data-type='taskList']_li]:flex",
31831
+ "[&_ul[data-type='taskList']_li]:items-start",
31832
+ "[&_ul[data-type='taskList']_li]:gap-2",
31833
+ "[&_ul[data-type='taskList']_li>label]:mt-0.5",
31834
+ "[&_ul[data-type='taskList']_li>label>input]:w-4",
31835
+ "[&_ul[data-type='taskList']_li>label>input]:h-4",
31836
+ "[&_ul[data-type='taskList']_li>label>input]:rounded",
31837
+ "[&_ul[data-type='taskList']_li>label>input]:border-2",
31838
+ "[&_ul[data-type='taskList']_li>label>input]:border-primary/50",
31839
+ "[&_ul[data-type='taskList']_li>label>input]:accent-primary",
31840
+ "[&_pre]:bg-muted/40!",
31841
+ "[&_pre]:text-foreground!",
31842
+ "[&_pre]:border!",
31843
+ "[&_pre]:border-border/60!",
31844
+ "[&_pre_code]:bg-transparent!",
31845
+ "[&_.tableWrapper]:overflow-x-auto",
31846
+ "[&_.tableWrapper]:pb-1.5",
31847
+ "[&_.tableWrapper]:select-text",
31848
+ "[&_.tableWrapper]:[scrollbar-width:thin]",
31849
+ "[&_.tableWrapper]:[scrollbar-color:hsl(var(--border))_transparent]",
31850
+ "[&_.tableWrapper::-webkit-scrollbar]:h-2",
31851
+ "[&_.tableWrapper::-webkit-scrollbar]:w-2",
31852
+ "[&_.tableWrapper::-webkit-scrollbar-track]:rounded-full",
31853
+ "[&_.tableWrapper::-webkit-scrollbar-track]:bg-transparent",
31854
+ "[&_.tableWrapper::-webkit-scrollbar-thumb]:rounded-full",
31855
+ "[&_.tableWrapper::-webkit-scrollbar-thumb]:border",
31856
+ "[&_.tableWrapper::-webkit-scrollbar-thumb]:border-solid",
31857
+ "[&_.tableWrapper::-webkit-scrollbar-thumb]:border-transparent",
31858
+ "[&_.tableWrapper::-webkit-scrollbar-thumb]:bg-border/70",
31859
+ "[&_.tableWrapper::-webkit-scrollbar-thumb:hover]:bg-muted-foreground/45",
31860
+ "[&_table]:table-fixed",
31861
+ "[&_table]:overflow-hidden",
31862
+ "[&_table]:select-text",
31863
+ "[&_table[data-table-align]]:w-max",
31864
+ "[&_table[data-table-align]]:max-w-full",
31865
+ "[&_table[data-table-align='center']]:mx-auto",
31866
+ "[&_table[data-table-align='right']]:ml-auto",
31867
+ "[&_table[data-table-align='right']]:mr-0",
31868
+ "[&_td]:relative",
31869
+ "[&_td]:align-top",
31870
+ "[&_td]:box-border",
31871
+ "[&_td]:select-text",
31872
+ "[&_th]:relative",
31873
+ "[&_th]:align-top",
31874
+ "[&_th]:box-border",
31875
+ "[&_th]:select-text",
31876
+ "[&_.selectedCell]:after:content-['']",
31877
+ "[&_.selectedCell]:after:absolute",
31878
+ "[&_.selectedCell]:after:inset-0",
31879
+ "[&_.selectedCell]:after:z-[2]",
31880
+ "[&_.selectedCell]:after:bg-primary/15",
31881
+ "[&_.selectedCell]:after:pointer-events-none",
31882
+ "[&_.column-resize-handle]:pointer-events-auto",
31883
+ "[&_.column-resize-handle]:cursor-col-resize",
31884
+ "[&_.column-resize-handle]:absolute",
31885
+ "[&_.column-resize-handle]:top-[-1px]",
31886
+ "[&_.column-resize-handle]:bottom-[-1px]",
31887
+ "[&_.column-resize-handle]:right-[-5px]",
31888
+ "[&_.column-resize-handle]:z-10",
31889
+ "[&_.column-resize-handle]:w-2.5",
31890
+ "[&_.column-resize-handle]:bg-transparent",
31891
+ "[&_.column-resize-handle]:rounded-none",
31892
+ "[&_.column-resize-handle]:opacity-0",
31893
+ "[&_.column-resize-handle]:transition-opacity",
31894
+ "[&_.column-resize-handle]:after:absolute",
31895
+ "[&_.column-resize-handle]:after:top-0",
31896
+ "[&_.column-resize-handle]:after:bottom-0",
31897
+ "[&_.column-resize-handle]:after:left-1/2",
31898
+ "[&_.column-resize-handle]:after:w-0.5",
31899
+ "[&_.column-resize-handle]:after:-translate-x-1/2",
31900
+ "[&_.column-resize-handle]:after:rounded-full",
31901
+ "[&_.column-resize-handle]:after:bg-primary/75",
31902
+ "[&_.column-resize-handle]:after:content-['']",
31903
+ "[&.resize-cursor_.column-resize-handle]:opacity-100",
31904
+ "[&.resize-cursor_.column-resize-handle]:after:bg-primary",
31905
+ "[&.resize-cursor]:cursor-col-resize",
31906
+ "[&.resize-row-cursor]:cursor-row-resize",
31907
+ "[&_img.ProseMirror-selectednode]:ring-2",
31908
+ "[&_img.ProseMirror-selectednode]:ring-primary/60",
31909
+ "[&_img.ProseMirror-selectednode]:ring-offset-2",
31910
+ "[&_img.ProseMirror-selectednode]:ring-offset-background",
31911
+ "[&_hr]:border-t-2",
31912
+ "[&_hr]:border-primary/30",
31913
+ "[&_hr]:my-8",
31914
+ "[&_h1]:text-3xl",
31915
+ "[&_h1]:font-bold",
31916
+ "[&_h1]:mt-6",
31917
+ "[&_h1]:mb-4",
31918
+ "[&_h1]:text-foreground",
31919
+ "[&_h2]:text-2xl",
31920
+ "[&_h2]:font-semibold",
31921
+ "[&_h2]:mt-5",
31922
+ "[&_h2]:mb-3",
31923
+ "[&_h2]:text-foreground",
31924
+ "[&_h3]:text-xl",
31925
+ "[&_h3]:font-semibold",
31926
+ "[&_h3]:mt-4",
31927
+ "[&_h3]:mb-2",
31928
+ "[&_h3]:text-foreground",
31929
+ "[&_ul:not([data-type='taskList'])]:list-disc",
31930
+ "[&_ul:not([data-type='taskList'])]:pl-6",
31931
+ "[&_ul:not([data-type='taskList'])]:my-3",
31932
+ "[&_ol]:list-decimal",
31933
+ "[&_ol]:pl-6",
31934
+ "[&_ol]:my-3",
31935
+ "[&_li]:my-1",
31936
+ "[&_li]:pl-1",
31937
+ "[&_li_p]:my-0",
31938
+ "[&_blockquote]:border-l-4",
31939
+ "[&_blockquote]:border-primary",
31940
+ "[&_blockquote]:pl-4",
31941
+ "[&_blockquote]:py-2",
31942
+ "[&_blockquote]:my-4",
31943
+ "[&_blockquote]:bg-muted/30",
31944
+ "[&_blockquote]:rounded-r-lg",
31945
+ "[&_blockquote]:italic",
31946
+ "[&_blockquote]:text-muted-foreground",
31947
+ "[&_blockquote_p]:my-0",
31948
+ "[&_[data-image-layout='left']+p]:mt-1",
31949
+ "[&_[data-image-layout='left']+p]:min-h-[5rem]",
31950
+ "[&_[data-image-layout='right']+p]:mt-1",
31951
+ "[&_[data-image-layout='right']+p]:min-h-[5rem]",
31952
+ "max-md:[&_[data-image-layout='left']]:float-none",
31953
+ "max-md:[&_[data-image-layout='left']]:mr-0",
31954
+ "max-md:[&_[data-image-layout='left']]:ml-0",
31955
+ "max-md:[&_[data-image-layout='left']]:max-w-full",
31956
+ "max-md:[&_[data-image-layout='right']]:float-none",
31957
+ "max-md:[&_[data-image-layout='right']]:mr-0",
31958
+ "max-md:[&_[data-image-layout='right']]:ml-0",
31959
+ "max-md:[&_[data-image-layout='right']]:max-w-full",
31960
+ "max-md:[&_[data-image-layout='left']+p]:min-h-0",
31961
+ "max-md:[&_[data-image-layout='right']+p]:min-h-0"
31962
+ );
31963
+
31964
+ // src/components/UEditor/use-table-interactions.ts
31965
+ import React74, { useEffect as useEffect35, useRef as useRef31 } from "react";
31966
+ function useUEditorTableInteractions(editor) {
31866
31967
  const editorContentRef = useRef31(null);
31867
31968
  const tableColumnGuideRef = useRef31(null);
31868
31969
  const tableRowGuideRef = useRef31(null);
31869
31970
  const activeTableCellHighlightRef = useRef31(null);
31870
31971
  const hoveredTableCellRef = useRef31(null);
31871
31972
  const activeTableCellRef = useRef31(null);
31973
+ const tableLayoutSyncFrameRef = useRef31(null);
31974
+ const rowResizeCommitFrameRef = useRef31(null);
31872
31975
  const rowResizeStateRef = useRef31(null);
31873
31976
  const setEditorResizeCursor = React74.useCallback((cursor) => {
31874
31977
  const proseMirror = editorContentRef.current?.querySelector(".ProseMirror");
@@ -31910,6 +32013,14 @@ var UEditor = React74.forwardRef(({
31910
32013
  highlight.style.width = `${metrics.width}px`;
31911
32014
  highlight.style.height = `${metrics.height}px`;
31912
32015
  }, []);
32016
+ const scheduleTableLayoutSync = React74.useCallback(() => {
32017
+ if (tableLayoutSyncFrameRef.current !== null) return;
32018
+ tableLayoutSyncFrameRef.current = window.requestAnimationFrame(() => {
32019
+ tableLayoutSyncFrameRef.current = null;
32020
+ updateActiveCellHighlight(activeTableCellRef.current);
32021
+ editorContentRef.current?.dispatchEvent(new CustomEvent(UEDITOR_TABLE_LAYOUT_CHANGE_EVENT));
32022
+ });
32023
+ }, [updateActiveCellHighlight]);
31913
32024
  const setActiveTableCell = React74.useCallback((cell) => {
31914
32025
  if (activeTableCellRef.current === cell) return;
31915
32026
  activeTableCellRef.current = cell;
@@ -31951,239 +32062,49 @@ var UEditor = React74.forwardRef(({
31951
32062
  surface.classList.add("resize-row-cursor");
31952
32063
  setEditorResizeCursor("row-resize");
31953
32064
  }, [setEditorResizeCursor]);
31954
- const extensions = useMemo24(
31955
- () => buildUEditorExtensions({
31956
- placeholder: effectivePlaceholder,
31957
- translate: t,
31958
- maxCharacters,
31959
- uploadImage,
31960
- imageInsertMode,
31961
- maxImageFileSize,
31962
- allowedImageMimeTypes,
31963
- fallbackToDataUrl,
31964
- editable
31965
- }),
31966
- [effectivePlaceholder, t, maxCharacters, uploadImage, imageInsertMode, maxImageFileSize, allowedImageMimeTypes, fallbackToDataUrl, editable]
31967
- );
31968
- const editor = useEditor({
31969
- immediatelyRender: false,
31970
- extensions,
31971
- content,
31972
- editable,
31973
- autofocus,
31974
- editorProps: {
31975
- handleDOMEvents: {
31976
- keydown: (_view, event) => {
31977
- if (!(event instanceof KeyboardEvent)) return false;
31978
- if (event.key === "ArrowLeft" || event.key === "ArrowRight" || event.key === "ArrowUp" || event.key === "ArrowDown") {
31979
- event.stopPropagation();
31980
- }
31981
- return false;
31982
- },
31983
- click: (view, event) => {
31984
- if (!(event instanceof MouseEvent)) return false;
31985
- if (event.button !== 0) return false;
31986
- const target = resolveEventElement(event.target);
31987
- const anchor = target?.closest?.("a[href]");
31988
- const href = anchor?.getAttribute("href") ?? "";
31989
- if (!href) return false;
31990
- if (!view.state.selection.empty) return false;
31991
- event.preventDefault();
31992
- event.stopPropagation();
31993
- window.open(href, "_blank", "noopener,noreferrer");
31994
- return true;
31995
- }
31996
- },
31997
- attributes: {
31998
- class: cn(
31999
- "prose prose-sm sm:prose dark:prose-invert max-w-none",
32000
- "focus:outline-none",
32001
- "px-4 py-4",
32002
- "[&_.is-editor-empty]:before:content-[attr(data-placeholder)]",
32003
- "[&_.is-editor-empty]:before:text-muted-foreground/50",
32004
- "[&_.is-editor-empty]:before:float-left",
32005
- "[&_.is-editor-empty]:before:pointer-events-none",
32006
- "[&_.is-editor-empty]:before:h-0",
32007
- "[&_ul[data-type='taskList']]:list-none",
32008
- "[&_ul[data-type='taskList']]:pl-0",
32009
- "[&_ul[data-type='taskList']_li]:flex",
32010
- "[&_ul[data-type='taskList']_li]:items-start",
32011
- "[&_ul[data-type='taskList']_li]:gap-2",
32012
- "[&_ul[data-type='taskList']_li>label]:mt-0.5",
32013
- "[&_ul[data-type='taskList']_li>label>input]:w-4",
32014
- "[&_ul[data-type='taskList']_li>label>input]:h-4",
32015
- "[&_ul[data-type='taskList']_li>label>input]:rounded",
32016
- "[&_ul[data-type='taskList']_li>label>input]:border-2",
32017
- "[&_ul[data-type='taskList']_li>label>input]:border-primary/50",
32018
- "[&_ul[data-type='taskList']_li>label>input]:accent-primary",
32019
- "[&_pre]:bg-muted/40!",
32020
- "[&_pre]:text-foreground!",
32021
- "[&_pre]:border!",
32022
- "[&_pre]:border-border/60!",
32023
- "[&_pre_code]:bg-transparent!",
32024
- "[&_.tableWrapper]:overflow-x-auto",
32025
- "[&_.tableWrapper]:pb-1.5",
32026
- "[&_.tableWrapper]:select-text",
32027
- "[&_.tableWrapper]:[scrollbar-width:thin]",
32028
- "[&_.tableWrapper]:[scrollbar-color:hsl(var(--border))_transparent]",
32029
- "[&_.tableWrapper::-webkit-scrollbar]:h-2",
32030
- "[&_.tableWrapper::-webkit-scrollbar]:w-2",
32031
- "[&_.tableWrapper::-webkit-scrollbar-track]:rounded-full",
32032
- "[&_.tableWrapper::-webkit-scrollbar-track]:bg-transparent",
32033
- "[&_.tableWrapper::-webkit-scrollbar-thumb]:rounded-full",
32034
- "[&_.tableWrapper::-webkit-scrollbar-thumb]:border",
32035
- "[&_.tableWrapper::-webkit-scrollbar-thumb]:border-solid",
32036
- "[&_.tableWrapper::-webkit-scrollbar-thumb]:border-transparent",
32037
- "[&_.tableWrapper::-webkit-scrollbar-thumb]:bg-border/70",
32038
- "[&_.tableWrapper::-webkit-scrollbar-thumb:hover]:bg-muted-foreground/45",
32039
- "[&_table]:table-fixed",
32040
- "[&_table]:overflow-hidden",
32041
- "[&_table]:select-text",
32042
- "[&_table[data-table-align]]:w-max",
32043
- "[&_table[data-table-align]]:max-w-full",
32044
- "[&_table[data-table-align='center']]:mx-auto",
32045
- "[&_table[data-table-align='right']]:ml-auto",
32046
- "[&_table[data-table-align='right']]:mr-0",
32047
- "[&_td]:relative",
32048
- "[&_td]:align-top",
32049
- "[&_td]:box-border",
32050
- "[&_td]:select-text",
32051
- "[&_th]:relative",
32052
- "[&_th]:align-top",
32053
- "[&_th]:box-border",
32054
- "[&_th]:select-text",
32055
- "[&_.selectedCell]:after:content-['']",
32056
- "[&_.selectedCell]:after:absolute",
32057
- "[&_.selectedCell]:after:inset-0",
32058
- "[&_.selectedCell]:after:z-[2]",
32059
- "[&_.selectedCell]:after:bg-primary/15",
32060
- "[&_.selectedCell]:after:pointer-events-none",
32061
- "[&_.column-resize-handle]:pointer-events-auto",
32062
- "[&_.column-resize-handle]:cursor-col-resize",
32063
- "[&_.column-resize-handle]:absolute",
32064
- "[&_.column-resize-handle]:top-[-1px]",
32065
- "[&_.column-resize-handle]:bottom-[-1px]",
32066
- "[&_.column-resize-handle]:right-[-5px]",
32067
- "[&_.column-resize-handle]:z-10",
32068
- "[&_.column-resize-handle]:w-2.5",
32069
- "[&_.column-resize-handle]:bg-transparent",
32070
- "[&_.column-resize-handle]:rounded-none",
32071
- "[&_.column-resize-handle]:opacity-0",
32072
- "[&_.column-resize-handle]:transition-opacity",
32073
- "[&_.column-resize-handle]:after:absolute",
32074
- "[&_.column-resize-handle]:after:top-0",
32075
- "[&_.column-resize-handle]:after:bottom-0",
32076
- "[&_.column-resize-handle]:after:left-1/2",
32077
- "[&_.column-resize-handle]:after:w-0.5",
32078
- "[&_.column-resize-handle]:after:-translate-x-1/2",
32079
- "[&_.column-resize-handle]:after:rounded-full",
32080
- "[&_.column-resize-handle]:after:bg-primary/75",
32081
- "[&_.column-resize-handle]:after:content-['']",
32082
- "[&.resize-cursor_.column-resize-handle]:opacity-100",
32083
- "[&.resize-cursor_.column-resize-handle]:after:bg-primary",
32084
- "[&.resize-cursor]:cursor-col-resize",
32085
- "[&.resize-row-cursor]:cursor-row-resize",
32086
- "[&_img.ProseMirror-selectednode]:ring-2",
32087
- "[&_img.ProseMirror-selectednode]:ring-primary/60",
32088
- "[&_img.ProseMirror-selectednode]:ring-offset-2",
32089
- "[&_img.ProseMirror-selectednode]:ring-offset-background",
32090
- "[&_hr]:border-t-2",
32091
- "[&_hr]:border-primary/30",
32092
- "[&_hr]:my-8",
32093
- "[&_h1]:text-3xl",
32094
- "[&_h1]:font-bold",
32095
- "[&_h1]:mt-6",
32096
- "[&_h1]:mb-4",
32097
- "[&_h1]:text-foreground",
32098
- "[&_h2]:text-2xl",
32099
- "[&_h2]:font-semibold",
32100
- "[&_h2]:mt-5",
32101
- "[&_h2]:mb-3",
32102
- "[&_h2]:text-foreground",
32103
- "[&_h3]:text-xl",
32104
- "[&_h3]:font-semibold",
32105
- "[&_h3]:mt-4",
32106
- "[&_h3]:mb-2",
32107
- "[&_h3]:text-foreground",
32108
- "[&_ul:not([data-type='taskList'])]:list-disc",
32109
- "[&_ul:not([data-type='taskList'])]:pl-6",
32110
- "[&_ul:not([data-type='taskList'])]:my-3",
32111
- "[&_ol]:list-decimal",
32112
- "[&_ol]:pl-6",
32113
- "[&_ol]:my-3",
32114
- "[&_li]:my-1",
32115
- "[&_li]:pl-1",
32116
- "[&_li_p]:my-0",
32117
- "[&_blockquote]:border-l-4",
32118
- "[&_blockquote]:border-primary",
32119
- "[&_blockquote]:pl-4",
32120
- "[&_blockquote]:py-2",
32121
- "[&_blockquote]:my-4",
32122
- "[&_blockquote]:bg-muted/30",
32123
- "[&_blockquote]:rounded-r-lg",
32124
- "[&_blockquote]:italic",
32125
- "[&_blockquote]:text-muted-foreground",
32126
- "[&_blockquote_p]:my-0",
32127
- "[&_[data-image-layout='left']+p]:mt-1",
32128
- "[&_[data-image-layout='left']+p]:min-h-[5rem]",
32129
- "[&_[data-image-layout='right']+p]:mt-1",
32130
- "[&_[data-image-layout='right']+p]:min-h-[5rem]",
32131
- "max-md:[&_[data-image-layout='left']]:float-none",
32132
- "max-md:[&_[data-image-layout='left']]:mr-0",
32133
- "max-md:[&_[data-image-layout='left']]:ml-0",
32134
- "max-md:[&_[data-image-layout='left']]:max-w-full",
32135
- "max-md:[&_[data-image-layout='right']]:float-none",
32136
- "max-md:[&_[data-image-layout='right']]:mr-0",
32137
- "max-md:[&_[data-image-layout='right']]:ml-0",
32138
- "max-md:[&_[data-image-layout='right']]:max-w-full",
32139
- "max-md:[&_[data-image-layout='left']+p]:min-h-0",
32140
- "max-md:[&_[data-image-layout='right']+p]:min-h-0"
32141
- )
32142
- }
32143
- },
32144
- onUpdate: ({ editor: editor2 }) => {
32145
- const html = editor2.getHTML();
32146
- onChange?.(html);
32147
- onHtmlChange?.(html);
32148
- onJsonChange?.(editor2.getJSON());
32065
+ const commitRowResizePreview = React74.useCallback(() => {
32066
+ if (!editor) return;
32067
+ const state = rowResizeStateRef.current;
32068
+ if (!state) return;
32069
+ const nextHeight = state.pendingHeight;
32070
+ if (nextHeight === state.previewHeight) {
32071
+ document.body.style.cursor = "row-resize";
32072
+ showRowGuide(state.tableElement, state.rowElement, state.cellElement);
32073
+ scheduleTableLayoutSync();
32074
+ return;
32149
32075
  }
32150
- });
32076
+ state.previewHeight = nextHeight;
32077
+ const tr = editor.view.state.tr;
32078
+ tr.setNodeMarkup(state.rowPos, void 0, {
32079
+ ...state.rowNode.attrs,
32080
+ rowHeight: nextHeight
32081
+ });
32082
+ tr.setMeta("addToHistory", false);
32083
+ editor.view.dispatch(tr);
32084
+ state.rowNode = editor.view.state.doc.nodeAt(state.rowPos) ?? state.rowNode;
32085
+ const refreshedRow = state.tableElement.rows.item(state.rowElement.rowIndex);
32086
+ if (refreshedRow instanceof HTMLTableRowElement) {
32087
+ state.rowElement = refreshedRow;
32088
+ const refreshedCell = refreshedRow.cells.item(state.cellIndex);
32089
+ if (refreshedCell instanceof HTMLTableCellElement) {
32090
+ state.cellElement = refreshedCell;
32091
+ }
32092
+ }
32093
+ document.body.style.cursor = "row-resize";
32094
+ showRowGuide(state.tableElement, state.rowElement, state.cellElement);
32095
+ scheduleTableLayoutSync();
32096
+ }, [editor, scheduleTableLayoutSync, showRowGuide]);
32097
+ const scheduleRowResizeCommit = React74.useCallback(() => {
32098
+ if (rowResizeCommitFrameRef.current !== null) return;
32099
+ rowResizeCommitFrameRef.current = window.requestAnimationFrame(() => {
32100
+ rowResizeCommitFrameRef.current = null;
32101
+ commitRowResizePreview();
32102
+ });
32103
+ }, [commitRowResizePreview]);
32151
32104
  const syncActiveTableCellFromSelection = React74.useCallback(() => {
32152
32105
  if (!editor) return;
32153
32106
  setActiveTableCell(getSelectionTableCell(editor.view));
32154
32107
  }, [editor, setActiveTableCell]);
32155
- useImperativeHandle3(
32156
- ref,
32157
- () => ({
32158
- prepareContentForSave: async ({ throwOnError = false } = {}) => {
32159
- if (!inFlightPrepareRef.current) {
32160
- const htmlSnapshot = editor?.getHTML() ?? content ?? "";
32161
- inFlightPrepareRef.current = prepareUEditorContentForSave({
32162
- html: htmlSnapshot,
32163
- uploadImageForSave,
32164
- uploadConcurrency: uploadImageConcurrency
32165
- }).finally(() => {
32166
- inFlightPrepareRef.current = null;
32167
- });
32168
- }
32169
- const result = await inFlightPrepareRef.current;
32170
- if (throwOnError && result.errors.length > 0) {
32171
- throw new UEditorPrepareContentForSaveError(result);
32172
- }
32173
- return result;
32174
- }
32175
- }),
32176
- [content, editor, uploadImageForSave, uploadImageConcurrency]
32177
- );
32178
- useEffect35(() => {
32179
- if (!editor) return;
32180
- const nextContent = content ?? "";
32181
- if (lastAppliedContentRef.current === nextContent) return;
32182
- lastAppliedContentRef.current = nextContent;
32183
- if (editor.getHTML() !== nextContent) {
32184
- editor.commands.setContent(nextContent, { emitUpdate: false });
32185
- }
32186
- }, [content, editor]);
32187
32108
  useEffect35(() => {
32188
32109
  if (!editor) return void 0;
32189
32110
  const proseMirror = editor.view.dom;
@@ -32273,6 +32194,7 @@ var UEditor = React74.forwardRef(({
32273
32194
  setHoveredTableCell(cell);
32274
32195
  const rowInfo = findTableRowNodeInfo(editor.view, row);
32275
32196
  if (!rowInfo) return;
32197
+ const startHeight = row.getBoundingClientRect().height;
32276
32198
  rowResizeStateRef.current = {
32277
32199
  rowElement: row,
32278
32200
  tableElement: table,
@@ -32281,8 +32203,9 @@ var UEditor = React74.forwardRef(({
32281
32203
  rowPos: rowInfo.pos,
32282
32204
  rowNode: rowInfo.node,
32283
32205
  startY: event.clientY,
32284
- startHeight: row.getBoundingClientRect().height,
32285
- previewHeight: row.getBoundingClientRect().height
32206
+ startHeight,
32207
+ previewHeight: startHeight,
32208
+ pendingHeight: startHeight
32286
32209
  };
32287
32210
  showRowGuide(table, row, cell);
32288
32211
  document.body.style.cursor = "row-resize";
@@ -32296,15 +32219,14 @@ var UEditor = React74.forwardRef(({
32296
32219
  MIN_TABLE_ROW_HEIGHT,
32297
32220
  Math.round(state.startHeight + (event.clientY - state.startY))
32298
32221
  );
32299
- if (nextHeight === state.previewHeight) {
32222
+ if (nextHeight === state.pendingHeight) {
32300
32223
  document.body.style.cursor = "row-resize";
32301
32224
  showRowGuide(state.tableElement, state.rowElement, state.cellElement);
32302
32225
  return;
32303
32226
  }
32304
- state.previewHeight = nextHeight;
32305
- applyPreviewRowHeight(state.rowElement, nextHeight);
32227
+ state.pendingHeight = nextHeight;
32306
32228
  document.body.style.cursor = "row-resize";
32307
- showRowGuide(state.tableElement, state.rowElement, state.cellElement);
32229
+ scheduleRowResizeCommit();
32308
32230
  };
32309
32231
  const handlePointerUp = (event) => {
32310
32232
  const state = rowResizeStateRef.current;
@@ -32313,11 +32235,17 @@ var UEditor = React74.forwardRef(({
32313
32235
  MIN_TABLE_ROW_HEIGHT,
32314
32236
  Math.round(state.startHeight + (event.clientY - state.startY))
32315
32237
  );
32316
- const rowNode = editor.view.state.doc.nodeAt(state.rowPos) ?? state.rowNode;
32317
- clearPreviewRowHeight(state.rowElement);
32238
+ state.pendingHeight = nextHeight;
32239
+ if (rowResizeCommitFrameRef.current !== null) {
32240
+ window.cancelAnimationFrame(rowResizeCommitFrameRef.current);
32241
+ rowResizeCommitFrameRef.current = null;
32242
+ }
32243
+ commitRowResizePreview();
32244
+ const latestState = rowResizeStateRef.current ?? state;
32245
+ const rowNode = editor.view.state.doc.nodeAt(latestState.rowPos) ?? latestState.rowNode;
32318
32246
  if (rowNode.attrs.rowHeight !== nextHeight) {
32319
32247
  const tr = editor.view.state.tr;
32320
- tr.setNodeMarkup(state.rowPos, void 0, {
32248
+ tr.setNodeMarkup(latestState.rowPos, void 0, {
32321
32249
  ...rowNode.attrs,
32322
32250
  rowHeight: nextHeight
32323
32251
  });
@@ -32327,15 +32255,20 @@ var UEditor = React74.forwardRef(({
32327
32255
  document.body.style.cursor = "";
32328
32256
  clearHoveredTableCell();
32329
32257
  clearAllTableResizeHover();
32258
+ scheduleTableLayoutSync();
32330
32259
  };
32331
32260
  const handleWindowBlur = () => {
32332
32261
  const state = rowResizeStateRef.current;
32333
32262
  if (!state) return;
32334
- clearPreviewRowHeight(state.rowElement);
32263
+ if (rowResizeCommitFrameRef.current !== null) {
32264
+ window.cancelAnimationFrame(rowResizeCommitFrameRef.current);
32265
+ rowResizeCommitFrameRef.current = null;
32266
+ }
32335
32267
  rowResizeStateRef.current = null;
32336
32268
  document.body.style.cursor = "";
32337
32269
  clearHoveredTableCell();
32338
32270
  clearAllTableResizeHover();
32271
+ scheduleTableLayoutSync();
32339
32272
  };
32340
32273
  proseMirror.addEventListener("mousemove", handleEditorMouseMove);
32341
32274
  proseMirror.addEventListener("mouseleave", handleEditorMouseLeave);
@@ -32374,13 +32307,156 @@ var UEditor = React74.forwardRef(({
32374
32307
  editor.off("selectionUpdate", syncActiveTableCellFromSelection);
32375
32308
  editor.off("focus", syncActiveTableCellFromSelection);
32376
32309
  window.clearTimeout(selectionSyncTimeoutId);
32310
+ if (tableLayoutSyncFrameRef.current !== null) {
32311
+ window.cancelAnimationFrame(tableLayoutSyncFrameRef.current);
32312
+ tableLayoutSyncFrameRef.current = null;
32313
+ }
32314
+ if (rowResizeCommitFrameRef.current !== null) {
32315
+ window.cancelAnimationFrame(rowResizeCommitFrameRef.current);
32316
+ rowResizeCommitFrameRef.current = null;
32317
+ }
32377
32318
  document.body.style.cursor = "";
32378
32319
  clearActiveTableCell();
32379
32320
  clearHoveredTableCell();
32380
32321
  clearAllTableResizeHover();
32381
32322
  rowResizeStateRef.current = null;
32382
32323
  };
32383
- }, [clearActiveTableCell, clearAllTableResizeHover, clearHoveredTableCell, editor, hideColumnGuide, hideRowGuide, setHoveredTableCell, showColumnGuide, showRowGuide, syncActiveTableCellFromSelection, updateActiveCellHighlight]);
32324
+ }, [clearActiveTableCell, clearAllTableResizeHover, clearHoveredTableCell, commitRowResizePreview, editor, hideColumnGuide, hideRowGuide, scheduleRowResizeCommit, scheduleTableLayoutSync, setHoveredTableCell, showColumnGuide, showRowGuide, syncActiveTableCellFromSelection, updateActiveCellHighlight]);
32325
+ return {
32326
+ editorContentRef,
32327
+ tableColumnGuideRef,
32328
+ tableRowGuideRef,
32329
+ activeTableCellHighlightRef
32330
+ };
32331
+ }
32332
+
32333
+ // src/components/UEditor/UEditor.tsx
32334
+ import { jsx as jsx83, jsxs as jsxs71 } from "react/jsx-runtime";
32335
+ var UEditor = React75.forwardRef(({
32336
+ content = "",
32337
+ onChange,
32338
+ onHtmlChange,
32339
+ onJsonChange,
32340
+ uploadImage,
32341
+ uploadImageForSave,
32342
+ uploadImageConcurrency = 3,
32343
+ imageInsertMode = "base64",
32344
+ maxImageFileSize,
32345
+ allowedImageMimeTypes,
32346
+ fallbackToDataUrl,
32347
+ placeholder,
32348
+ className,
32349
+ editable = true,
32350
+ autofocus = false,
32351
+ showToolbar = true,
32352
+ showBubbleMenu = true,
32353
+ showFloatingMenu = false,
32354
+ showCharacterCount = true,
32355
+ maxCharacters,
32356
+ minHeight = "200px",
32357
+ maxHeight = "auto",
32358
+ variant = "default",
32359
+ fontFamilies,
32360
+ fontSizes,
32361
+ lineHeights,
32362
+ letterSpacings
32363
+ }, ref) => {
32364
+ const t = useSmartTranslations("UEditor");
32365
+ const effectivePlaceholder = placeholder ?? t("placeholder");
32366
+ const inFlightPrepareRef = useRef32(null);
32367
+ const lastAppliedContentRef = useRef32(content ?? "");
32368
+ const extensions = useMemo24(
32369
+ () => buildUEditorExtensions({
32370
+ placeholder: effectivePlaceholder,
32371
+ translate: t,
32372
+ maxCharacters,
32373
+ uploadImage,
32374
+ imageInsertMode,
32375
+ maxImageFileSize,
32376
+ allowedImageMimeTypes,
32377
+ fallbackToDataUrl,
32378
+ editable
32379
+ }),
32380
+ [effectivePlaceholder, t, maxCharacters, uploadImage, imageInsertMode, maxImageFileSize, allowedImageMimeTypes, fallbackToDataUrl, editable]
32381
+ );
32382
+ const editor = useEditor({
32383
+ immediatelyRender: false,
32384
+ extensions,
32385
+ content,
32386
+ editable,
32387
+ autofocus,
32388
+ editorProps: {
32389
+ handleDOMEvents: {
32390
+ keydown: (_view, event) => {
32391
+ if (!(event instanceof KeyboardEvent)) return false;
32392
+ if (event.key === "ArrowLeft" || event.key === "ArrowRight" || event.key === "ArrowUp" || event.key === "ArrowDown") {
32393
+ event.stopPropagation();
32394
+ }
32395
+ return false;
32396
+ },
32397
+ click: (view, event) => {
32398
+ if (!(event instanceof MouseEvent)) return false;
32399
+ if (event.button !== 0) return false;
32400
+ const target = resolveEventElement(event.target);
32401
+ const anchor = target?.closest?.("a[href]");
32402
+ const href = anchor?.getAttribute("href") ?? "";
32403
+ if (!href) return false;
32404
+ if (!view.state.selection.empty) return false;
32405
+ event.preventDefault();
32406
+ event.stopPropagation();
32407
+ window.open(href, "_blank", "noopener,noreferrer");
32408
+ return true;
32409
+ }
32410
+ },
32411
+ attributes: {
32412
+ class: UEDITOR_PROSEMIRROR_CLASS_NAME
32413
+ }
32414
+ },
32415
+ onUpdate: ({ editor: editor2 }) => {
32416
+ const html = editor2.getHTML();
32417
+ onChange?.(html);
32418
+ onHtmlChange?.(html);
32419
+ onJsonChange?.(editor2.getJSON());
32420
+ }
32421
+ });
32422
+ const {
32423
+ editorContentRef,
32424
+ tableColumnGuideRef,
32425
+ tableRowGuideRef,
32426
+ activeTableCellHighlightRef
32427
+ } = useUEditorTableInteractions(editor);
32428
+ useImperativeHandle3(
32429
+ ref,
32430
+ () => ({
32431
+ prepareContentForSave: async ({ throwOnError = false } = {}) => {
32432
+ if (!inFlightPrepareRef.current) {
32433
+ const htmlSnapshot = editor?.getHTML() ?? content ?? "";
32434
+ inFlightPrepareRef.current = prepareUEditorContentForSave({
32435
+ html: htmlSnapshot,
32436
+ uploadImageForSave,
32437
+ uploadConcurrency: uploadImageConcurrency
32438
+ }).finally(() => {
32439
+ inFlightPrepareRef.current = null;
32440
+ });
32441
+ }
32442
+ const result = await inFlightPrepareRef.current;
32443
+ if (throwOnError && result.errors.length > 0) {
32444
+ throw new UEditorPrepareContentForSaveError(result);
32445
+ }
32446
+ return result;
32447
+ }
32448
+ }),
32449
+ [content, editor, uploadImageForSave, uploadImageConcurrency]
32450
+ );
32451
+ useEffect36(() => {
32452
+ if (!editor) return;
32453
+ const nextContent = content ?? "";
32454
+ if (lastAppliedContentRef.current === nextContent) return;
32455
+ lastAppliedContentRef.current = nextContent;
32456
+ if (editor.getHTML() !== nextContent) {
32457
+ editor.commands.setContent(nextContent, { emitUpdate: false });
32458
+ }
32459
+ }, [content, editor]);
32384
32460
  if (!editor) {
32385
32461
  return /* @__PURE__ */ jsx83(
32386
32462
  "div",