@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.
package/CHANGELOG.md CHANGED
@@ -8,6 +8,16 @@ All notable changes to `@underverse-ui/underverse` are documented in this file.
8
8
 
9
9
  - `DataTable` sortable headers now keep their titles visually centered while the sort control remains aligned to the trailing edge.
10
10
 
11
+ ## [2.0.32] - 2026-09-09
12
+
13
+ ### Added
14
+
15
+ - Added `UEditor.bubbleMenuPlacement` to keep the selection bubble menu above, below, or automatically positioned around the selection.
16
+
17
+ ### Fixed
18
+
19
+ - Hardened `UEditor` table selection and layout resolution against external HTML table cells and invalid `posAtDOM()` positions, including cross-realm popup and iframe documents.
20
+
11
21
  ## [2.0.2] - 2026-07-28
12
22
 
13
23
  ### Added
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "package": "@underverse-ui/underverse",
3
- "version": "2.0.31",
3
+ "version": "2.0.32",
4
4
  "sourceEntry": "src/index.ts",
5
- "totalExports": 263,
5
+ "totalExports": 264,
6
6
  "exports": [
7
7
  {
8
8
  "name": "*",
@@ -1604,6 +1604,13 @@
1604
1604
  "local": false,
1605
1605
  "aliasOf": "default"
1606
1606
  },
1607
+ {
1608
+ "name": "UEditorBubbleMenuPlacement",
1609
+ "kind": "type",
1610
+ "source": "./components/UEditor",
1611
+ "reexport": true,
1612
+ "local": false
1613
+ },
1607
1614
  {
1608
1615
  "name": "UEditorFontFamilyOption",
1609
1616
  "kind": "type",
@@ -3090,11 +3090,16 @@ function isCrossRealmTableRow(value) {
3090
3090
  function isCrossRealmTableCell(value) {
3091
3091
  return isCrossRealmElement(value) && ["TD", "TH"].includes(String(value.tagName).toUpperCase()) && "cellIndex" in value;
3092
3092
  }
3093
+ function isValidProseMirrorPosition(doc, pos) {
3094
+ return Number.isInteger(pos) && pos >= 0 && pos <= doc.content.size;
3095
+ }
3093
3096
  var TABLE_RESIZE_HIT_ZONE = 5;
3094
3097
  function findTableRowNodeInfo(view, rowElement) {
3098
+ if (!view.dom.contains(rowElement)) return null;
3095
3099
  const firstCell = rowElement.querySelector("th,td");
3096
- if (!firstCell) return null;
3100
+ if (!isCrossRealmTableCell(firstCell) || !view.dom.contains(firstCell)) return null;
3097
3101
  const cellPos = view.posAtDOM(firstCell, 0);
3102
+ if (!isValidProseMirrorPosition(view.state.doc, cellPos)) return null;
3098
3103
  const $pos = view.state.doc.resolve(cellPos);
3099
3104
  for (let depth = $pos.depth; depth > 0; depth -= 1) {
3100
3105
  const node = $pos.node(depth);
@@ -3136,14 +3141,14 @@ function getSelectionTableCell(view) {
3136
3141
  const browserSelection = realm?.getSelection();
3137
3142
  const anchorElement = resolveEventElement(browserSelection?.anchorNode ?? null);
3138
3143
  const anchorCell = anchorElement?.closest?.("th,td");
3139
- if (realm && anchorCell instanceof realm.HTMLElement) {
3144
+ if (isCrossRealmTableCell(anchorCell) && view.dom.contains(anchorCell)) {
3140
3145
  return anchorCell;
3141
3146
  }
3142
3147
  const { from } = view.state.selection;
3143
3148
  const domAtPos = view.domAtPos(from);
3144
3149
  const element = resolveEventElement(domAtPos.node);
3145
3150
  const cell = element?.closest?.("th,td");
3146
- return realm && cell instanceof realm.HTMLElement ? cell : null;
3151
+ return isCrossRealmTableCell(cell) && view.dom.contains(cell) ? cell : null;
3147
3152
  }
3148
3153
  function resolveRowResizeTarget(cell, clientX, clientY) {
3149
3154
  const rect = cell.getBoundingClientRect();
@@ -4327,18 +4332,22 @@ function getTableAnchorPos(editor) {
4327
4332
  const editorWindow = editorDocument.defaultView;
4328
4333
  const selectionAnchor = resolveEventElement(editorWindow?.getSelection()?.anchorNode ?? null);
4329
4334
  const selectionCell = selectionAnchor?.closest?.("th,td");
4330
- if (editorWindow && selectionCell instanceof editorWindow.HTMLTableCellElement && editor.view.dom.contains(selectionCell)) {
4331
- return editor.view.posAtDOM(selectionCell, 0) + 1;
4335
+ if (isCrossRealmTableCell(selectionCell) && editor.view.dom.contains(selectionCell)) {
4336
+ const cellPos2 = editor.view.posAtDOM(selectionCell, 0);
4337
+ return isValidProseMirrorPosition(editor.state.doc, cellPos2) && isValidProseMirrorPosition(editor.state.doc, cellPos2 + 1) ? cellPos2 + 1 : null;
4332
4338
  }
4333
4339
  const activeElement = editorWindow && editorDocument.activeElement instanceof editorWindow.Element ? editorDocument.activeElement : null;
4334
4340
  const activeCell = activeElement?.closest?.("th,td");
4335
- if (editorWindow && activeCell instanceof editorWindow.HTMLTableCellElement && editor.view.dom.contains(activeCell)) {
4336
- return editor.view.posAtDOM(activeCell, 0) + 1;
4341
+ if (isCrossRealmTableCell(activeCell) && editor.view.dom.contains(activeCell)) {
4342
+ const cellPos2 = editor.view.posAtDOM(activeCell, 0);
4343
+ return isValidProseMirrorPosition(editor.state.doc, cellPos2) && isValidProseMirrorPosition(editor.state.doc, cellPos2 + 1) ? cellPos2 + 1 : null;
4337
4344
  }
4338
4345
  const tables = editor.view.dom.querySelectorAll("table");
4339
4346
  if (tables.length !== 1) return null;
4340
4347
  const firstCell = tables[0]?.querySelector("th,td");
4341
- return editorWindow && firstCell instanceof editorWindow.HTMLTableCellElement ? editor.view.posAtDOM(firstCell, 0) + 1 : null;
4348
+ if (!isCrossRealmTableCell(firstCell) || !editor.view.dom.contains(firstCell)) return null;
4349
+ const cellPos = editor.view.posAtDOM(firstCell, 0);
4350
+ return isValidProseMirrorPosition(editor.state.doc, cellPos) && isValidProseMirrorPosition(editor.state.doc, cellPos + 1) ? cellPos + 1 : null;
4342
4351
  }
4343
4352
  var EDITOR_UI_ACTIVE_MARKS = [
4344
4353
  "blockquote",
@@ -5758,6 +5767,7 @@ export {
5758
5767
  isCrossRealmTable,
5759
5768
  isCrossRealmTableRow,
5760
5769
  isCrossRealmTableCell,
5770
+ isValidProseMirrorPosition,
5761
5771
  findTableRowNodeInfo,
5762
5772
  resolveEventElement,
5763
5773
  isPointOverRenderedText,
@@ -5817,4 +5827,4 @@ export {
5817
5827
  EditorToolbar,
5818
5828
  UEDITOR_PROSEMIRROR_CLASS_NAME
5819
5829
  };
5820
- //# sourceMappingURL=chunk-37MHVJMV.js.map
5830
+ //# sourceMappingURL=chunk-4TXHZS3S.js.map