@underverse-ui/underverse 2.0.31 → 2.0.32

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,7 +1,7 @@
1
1
  "use client";
2
2
  import {
3
3
  Modal_default
4
- } from "./chunk-2P7TSXEE.js";
4
+ } from "./chunk-RSSSQS2A.js";
5
5
  import {
6
6
  DEFAULT_TABLE_ROW_HEIGHT,
7
7
  DEFAULT_UEDITOR_IMAGE_MAX_FILE_SIZE,
@@ -29,7 +29,7 @@ import {
29
29
  trackEditorInsertionPosition,
30
30
  useDropdownMenuClose,
31
31
  useSharedEditorUiRenderState
32
- } from "./chunk-37MHVJMV.js";
32
+ } from "./chunk-4TXHZS3S.js";
33
33
  import {
34
34
  cn,
35
35
  resolveUEditorPortalContainer,
@@ -1118,4 +1118,4 @@ var MenuBar = ({
1118
1118
  export {
1119
1119
  MenuBar
1120
1120
  };
1121
- //# sourceMappingURL=menu-bar-DPCNNUX5.js.map
1121
+ //# sourceMappingURL=menu-bar-GDDGHNNJ.js.map
package/dist/ueditor.cjs CHANGED
@@ -5524,10 +5524,15 @@ function isCrossRealmTableRow(value) {
5524
5524
  function isCrossRealmTableCell(value) {
5525
5525
  return isCrossRealmElement(value) && ["TD", "TH"].includes(String(value.tagName).toUpperCase()) && "cellIndex" in value;
5526
5526
  }
5527
+ function isValidProseMirrorPosition(doc, pos) {
5528
+ return Number.isInteger(pos) && pos >= 0 && pos <= doc.content.size;
5529
+ }
5527
5530
  function findTableRowNodeInfo(view, rowElement) {
5531
+ if (!view.dom.contains(rowElement)) return null;
5528
5532
  const firstCell = rowElement.querySelector("th,td");
5529
- if (!firstCell) return null;
5533
+ if (!isCrossRealmTableCell(firstCell) || !view.dom.contains(firstCell)) return null;
5530
5534
  const cellPos = view.posAtDOM(firstCell, 0);
5535
+ if (!isValidProseMirrorPosition(view.state.doc, cellPos)) return null;
5531
5536
  const $pos = view.state.doc.resolve(cellPos);
5532
5537
  for (let depth = $pos.depth; depth > 0; depth -= 1) {
5533
5538
  const node = $pos.node(depth);
@@ -5569,14 +5574,14 @@ function getSelectionTableCell(view) {
5569
5574
  const browserSelection = realm?.getSelection();
5570
5575
  const anchorElement = resolveEventElement(browserSelection?.anchorNode ?? null);
5571
5576
  const anchorCell = anchorElement?.closest?.("th,td");
5572
- if (realm && anchorCell instanceof realm.HTMLElement) {
5577
+ if (isCrossRealmTableCell(anchorCell) && view.dom.contains(anchorCell)) {
5573
5578
  return anchorCell;
5574
5579
  }
5575
5580
  const { from } = view.state.selection;
5576
5581
  const domAtPos = view.domAtPos(from);
5577
5582
  const element = resolveEventElement(domAtPos.node);
5578
5583
  const cell = element?.closest?.("th,td");
5579
- return realm && cell instanceof realm.HTMLElement ? cell : null;
5584
+ return isCrossRealmTableCell(cell) && view.dom.contains(cell) ? cell : null;
5580
5585
  }
5581
5586
  function resolveRowResizeTarget(cell, clientX, clientY) {
5582
5587
  const rect = cell.getBoundingClientRect();
@@ -7963,18 +7968,22 @@ function getTableAnchorPos(editor) {
7963
7968
  const editorWindow = editorDocument.defaultView;
7964
7969
  const selectionAnchor = resolveEventElement(editorWindow?.getSelection()?.anchorNode ?? null);
7965
7970
  const selectionCell2 = selectionAnchor?.closest?.("th,td");
7966
- if (editorWindow && selectionCell2 instanceof editorWindow.HTMLTableCellElement && editor.view.dom.contains(selectionCell2)) {
7967
- return editor.view.posAtDOM(selectionCell2, 0) + 1;
7971
+ if (isCrossRealmTableCell(selectionCell2) && editor.view.dom.contains(selectionCell2)) {
7972
+ const cellPos2 = editor.view.posAtDOM(selectionCell2, 0);
7973
+ return isValidProseMirrorPosition(editor.state.doc, cellPos2) && isValidProseMirrorPosition(editor.state.doc, cellPos2 + 1) ? cellPos2 + 1 : null;
7968
7974
  }
7969
7975
  const activeElement = editorWindow && editorDocument.activeElement instanceof editorWindow.Element ? editorDocument.activeElement : null;
7970
7976
  const activeCell = activeElement?.closest?.("th,td");
7971
- if (editorWindow && activeCell instanceof editorWindow.HTMLTableCellElement && editor.view.dom.contains(activeCell)) {
7972
- return editor.view.posAtDOM(activeCell, 0) + 1;
7977
+ if (isCrossRealmTableCell(activeCell) && editor.view.dom.contains(activeCell)) {
7978
+ const cellPos2 = editor.view.posAtDOM(activeCell, 0);
7979
+ return isValidProseMirrorPosition(editor.state.doc, cellPos2) && isValidProseMirrorPosition(editor.state.doc, cellPos2 + 1) ? cellPos2 + 1 : null;
7973
7980
  }
7974
7981
  const tables = editor.view.dom.querySelectorAll("table");
7975
7982
  if (tables.length !== 1) return null;
7976
7983
  const firstCell = tables[0]?.querySelector("th,td");
7977
- return editorWindow && firstCell instanceof editorWindow.HTMLTableCellElement ? editor.view.posAtDOM(firstCell, 0) + 1 : null;
7984
+ if (!isCrossRealmTableCell(firstCell) || !editor.view.dom.contains(firstCell)) return null;
7985
+ const cellPos = editor.view.posAtDOM(firstCell, 0);
7986
+ return isValidProseMirrorPosition(editor.state.doc, cellPos) && isValidProseMirrorPosition(editor.state.doc, cellPos + 1) ? cellPos + 1 : null;
7978
7987
  }
7979
7988
  function computeEditorUiRenderState(editor) {
7980
7989
  const textStyle = editor.getAttributes("textStyle");
@@ -16297,6 +16306,7 @@ function getBubbleMenuPosition({
16297
16306
  end,
16298
16307
  menuSize,
16299
16308
  viewport,
16309
+ preferredPlacement = "auto",
16300
16310
  offset = 16,
16301
16311
  padding = 8
16302
16312
  }) {
@@ -16304,7 +16314,7 @@ function getBubbleMenuPosition({
16304
16314
  const selectionBottom = Math.max(start.bottom, end.bottom);
16305
16315
  const spaceAbove = selectionTop - offset - padding;
16306
16316
  const spaceBelow = viewport.height - padding - selectionBottom - offset;
16307
- const placement = menuSize.height <= spaceAbove || spaceAbove >= spaceBelow ? "top" : "bottom";
16317
+ const placement = preferredPlacement === "auto" ? menuSize.height <= spaceAbove || spaceAbove >= spaceBelow ? "top" : "bottom" : preferredPlacement;
16308
16318
  const halfWidth = menuSize.width / 2;
16309
16319
  const minLeft = padding + halfWidth;
16310
16320
  const maxLeft = viewport.width - padding - halfWidth;
@@ -17208,6 +17218,7 @@ var LinkPreviewContent = ({ editor, onEdit }) => {
17208
17218
  };
17209
17219
  var CustomBubbleMenu = ({
17210
17220
  editor,
17221
+ placement = "auto",
17211
17222
  fontSizes,
17212
17223
  lineHeights
17213
17224
  }) => {
@@ -17301,6 +17312,7 @@ var CustomBubbleMenu = ({
17301
17312
  width: editorWindow?.innerWidth ?? window.innerWidth,
17302
17313
  height: editorWindow?.innerHeight ?? window.innerHeight
17303
17314
  },
17315
+ preferredPlacement: placement,
17304
17316
  offset: BUBBLE_MENU_OFFSET
17305
17317
  }));
17306
17318
  if (keepOpenRef.current) {
@@ -17347,7 +17359,7 @@ var CustomBubbleMenu = ({
17347
17359
  editorWindow?.removeEventListener("resize", schedulePositionUpdate);
17348
17360
  editorWindow?.removeEventListener("scroll", schedulePositionUpdate, true);
17349
17361
  };
17350
- }, [editor, editorDocument, editorWindow]);
17362
+ }, [editor, editorDocument, editorWindow, placement]);
17351
17363
  (0, import_react36.useEffect)(() => {
17352
17364
  if (!isVisible || !portalWindow?.ResizeObserver) return;
17353
17365
  const menu = menuRef.current;
@@ -17401,6 +17413,7 @@ var CustomBubbleMenu = ({
17401
17413
  {
17402
17414
  ref: menuRef,
17403
17415
  "data-popover": true,
17416
+ "data-placement": position.placement,
17404
17417
  className: "fixed z-[99999] flex rounded-xl border border-border/40 bg-card text-card-foreground shadow-lg backdrop-blur-sm overflow-hidden animate-in fade-in-0 zoom-in-95",
17405
17418
  style: {
17406
17419
  top: `${position.top}px`,
@@ -22216,6 +22229,7 @@ function getCellFromTarget(target) {
22216
22229
  return null;
22217
22230
  }
22218
22231
  function findTableInfo(editor, pos) {
22232
+ if (!isValidProseMirrorPosition(editor.state.doc, pos)) return null;
22219
22233
  const $pos = editor.state.doc.resolve(pos);
22220
22234
  for (let depth = $pos.depth; depth > 0; depth -= 1) {
22221
22235
  const node = $pos.node(depth);
@@ -22258,6 +22272,7 @@ function buildLogicalColumnMetrics({
22258
22272
  for (const tableCell of Array.from(firstRow.cells)) {
22259
22273
  if (!isTableCellElement(tableCell)) continue;
22260
22274
  const cellPos = editor.view.posAtDOM(tableCell, 0);
22275
+ if (!isValidProseMirrorPosition(editor.state.doc, cellPos)) continue;
22261
22276
  const relativeCellPos = getCellRelativePosFromDomPos(map, tableInfo.start, cellPos);
22262
22277
  if (relativeCellPos == null) continue;
22263
22278
  const cellMapRect = map.findCell(relativeCellPos);
@@ -22331,18 +22346,20 @@ function buildLogicalRowMetrics({
22331
22346
  if (visualRows.length > 0) {
22332
22347
  return visualRows.sort((a, b) => a.index - b.index);
22333
22348
  }
22334
- return rows.map((tableRow, index) => {
22349
+ return rows.flatMap((tableRow, index) => {
22335
22350
  const rowRect = tableRow.getBoundingClientRect();
22336
22351
  const anchorCell = tableRow.cells.item(0) ?? cornerCell;
22337
22352
  const start = rowRect.height > 0 ? rowRect.top - surfaceRect.top - surface.clientTop + surface.scrollTop : tableTop + index * fallbackHeight;
22338
22353
  const size = metricOrFallback(rowRect.height, fallbackHeight);
22339
- return {
22354
+ const cellPos = editor.view.posAtDOM(anchorCell, 0);
22355
+ if (!isValidProseMirrorPosition(editor.state.doc, cellPos)) return [];
22356
+ return [{
22340
22357
  index,
22341
- cellPos: editor.view.posAtDOM(anchorCell, 0),
22358
+ cellPos,
22342
22359
  start,
22343
22360
  size,
22344
22361
  center: start + size / 2
22345
- };
22362
+ }];
22346
22363
  });
22347
22364
  }
22348
22365
  function getTableCellTextSelectionRange(editor, cellPos) {
@@ -22362,6 +22379,7 @@ function getTableCellTextSelectionRange(editor, cellPos) {
22362
22379
  return from !== null && to !== null && from < to ? { from, to } : null;
22363
22380
  }
22364
22381
  function buildTableControlLayout(editor, surface, cell) {
22382
+ if (!editor.view.dom.contains(cell)) return null;
22365
22383
  const row = cell.closest("tr");
22366
22384
  const table = cell.closest("table");
22367
22385
  if (!isTableRowElement(row) || !isTableElement(table)) {
@@ -22370,6 +22388,7 @@ function buildTableControlLayout(editor, surface, cell) {
22370
22388
  const rows = Array.from(table.rows).filter(isTableRowElement);
22371
22389
  const cornerCell = getLastCell(table);
22372
22390
  const cellPos = editor.view.posAtDOM(cell, 0);
22391
+ if (!isValidProseMirrorPosition(editor.state.doc, cellPos)) return null;
22373
22392
  const tableInfo = findTableInfo(editor, cellPos);
22374
22393
  if (rows.length === 0 || !tableInfo || !isTableCellElement(cornerCell)) {
22375
22394
  return null;
@@ -23327,7 +23346,7 @@ function getSelectedCell(editor) {
23327
23346
  const browserSelection = editorWindow?.getSelection();
23328
23347
  const anchorElement = resolveEventElement(browserSelection?.anchorNode ?? null);
23329
23348
  const anchorCell = anchorElement?.closest?.("th,td");
23330
- if (isCrossRealmTableCell(anchorCell)) {
23349
+ if (isCrossRealmTableCell(anchorCell) && editor.view.dom.contains(anchorCell)) {
23331
23350
  return anchorCell;
23332
23351
  }
23333
23352
  const domAtPos = editor.view.domAtPos(editor.state.selection.from);
@@ -24804,12 +24823,12 @@ function getFormulaEditingTableContext(view) {
24804
24823
  if (!getCellText2(node).startsWith("=")) return null;
24805
24824
  const cellPos = $from.before(depth);
24806
24825
  const cellDom = view.nodeDOM(cellPos);
24807
- if (!(cellDom instanceof HTMLTableCellElement)) return null;
24826
+ if (!isCrossRealmTableCell(cellDom) || !view.dom.contains(cellDom)) return null;
24808
24827
  const tableDepth = depth - 2;
24809
24828
  const tableNode = tableDepth > 0 ? $from.node(tableDepth) : null;
24810
24829
  if (!tableNode || tableNode.type.name !== "table") return null;
24811
24830
  const tableDom = cellDom.closest("table");
24812
- if (!(tableDom instanceof HTMLTableElement)) return null;
24831
+ if (!isCrossRealmTable(tableDom) || !view.dom.contains(tableDom)) return null;
24813
24832
  const tableMap = import_tables9.TableMap.get(tableNode);
24814
24833
  const tableStart = $from.start(tableDepth);
24815
24834
  const formulaCellRect = tableMap.findCell(cellPos - tableStart);
@@ -24881,6 +24900,7 @@ function getReferenceInsertionPrefix(view, cellContentStart, insertionPos) {
24881
24900
  return isInsideFunctionArguments && followsReference ? "," : "";
24882
24901
  }
24883
24902
  function findTableForPos(view, pos) {
24903
+ if (!isValidProseMirrorPosition(view.state.doc, pos)) return null;
24884
24904
  const $pos = view.state.doc.resolve(pos);
24885
24905
  for (let depth = $pos.depth; depth > 0; depth -= 1) {
24886
24906
  const node = $pos.node(depth);
@@ -24909,8 +24929,9 @@ function getCellRelativePosFromDomPos2(map, tableStart, domPos) {
24909
24929
  function getFormulaTableCellInfo(view, target, tablePos) {
24910
24930
  const element = resolveEventElement(target);
24911
24931
  const cell = element?.closest?.("th,td");
24912
- if (!(cell instanceof HTMLTableCellElement)) return null;
24932
+ if (!isCrossRealmTableCell(cell) || !view.dom.contains(cell)) return null;
24913
24933
  const domPos = view.posAtDOM(cell, 0);
24934
+ if (!isValidProseMirrorPosition(view.state.doc, domPos)) return null;
24914
24935
  const tableInfo = findTableForPos(view, domPos);
24915
24936
  if (!tableInfo || tableInfo.pos !== tablePos) return null;
24916
24937
  const map = import_tables9.TableMap.get(tableInfo.node);
@@ -25608,6 +25629,7 @@ var UEditor = import_react46.default.forwardRef(({
25608
25629
  autofocus = false,
25609
25630
  showToolbar = true,
25610
25631
  showBubbleMenu = true,
25632
+ bubbleMenuPlacement = "auto",
25611
25633
  showFloatingMenu = false,
25612
25634
  showCharacterCount = true,
25613
25635
  showFooter = true,
@@ -25967,6 +25989,7 @@ var UEditor = import_react46.default.forwardRef(({
25967
25989
  CustomBubbleMenu,
25968
25990
  {
25969
25991
  editor,
25992
+ placement: bubbleMenuPlacement,
25970
25993
  fontSizes,
25971
25994
  lineHeights
25972
25995
  }