@atlaskit/editor-plugin-paste-options-toolbar 9.1.3 → 9.1.5

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
@@ -1,5 +1,24 @@
1
1
  # @atlaskit/editor-plugin-paste-options-toolbar
2
2
 
3
+ ## 9.1.5
4
+
5
+ ### Patch Changes
6
+
7
+ - [`2e030e319c013`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/2e030e319c013) -
8
+ [EDITOR-5982] Fix AI paste menu not appearing when pasting heading + text
9
+ - [`e7032ec0e9287`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/e7032ec0e9287) -
10
+ [ux] EDITOR-5983 Ensure paste menu is in correct position when first pasted node is empty
11
+
12
+ ## 9.1.4
13
+
14
+ ### Patch Changes
15
+
16
+ - [`cdacbdec78ed6`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/cdacbdec78ed6) -
17
+ [EDITOR-5980] Fix sticky menu stopping before table when paste selection ends inside cell
18
+ - [`70e3625a8ae3f`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/70e3625a8ae3f) -
19
+ [EDITOR-5880] updated prop name for consistency and used view.dom for stable editor reference
20
+ - Updated dependencies
21
+
3
22
  ## 9.1.3
4
23
 
5
24
  ### Patch Changes
@@ -6,7 +6,10 @@ Object.defineProperty(exports, "__esModule", {
6
6
  value: true
7
7
  });
8
8
  exports.PasteActionsMenu = void 0;
9
+ exports.getTargetElement = getTargetElement;
10
+ exports.getVisualEndBottom = getVisualEndBottom;
9
11
  exports.onPositionCalculated = onPositionCalculated;
12
+ exports.resolveTableAfterPos = resolveTableAfterPos;
10
13
  var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
11
14
  var _react = _interopRequireWildcard(require("react"));
12
15
  var _analytics = require("@atlaskit/editor-common/analytics");
@@ -27,10 +30,21 @@ function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r
27
30
  function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
28
31
  function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { (0, _defineProperty2.default)(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
29
32
  var PopupWithListeners = (0, _uiReact.withReactEditorViewOuterListeners)(_ui.Popup);
33
+ /**
34
+ * Returns the DOM element at the given document position for use as a Popup anchor.
35
+ * For empty blocks (BR elements), returns the parent element to ensure correct positioning.
36
+ */
30
37
  function getTargetElement(editorView, pos) {
31
38
  try {
32
39
  var domRef = (0, _utils.findDomRefAtPos)(pos, editorView.domAtPos.bind(editorView));
33
40
  if (domRef instanceof HTMLElement) {
41
+ // Empty blocks render a <br> placeholder whose bounding rect has no
42
+ // meaningful dimensions (height ≈ 0). Using it as the Popup anchor
43
+ // causes the menu to appear at an unexpected position. Walk up to the
44
+ // parent block element so the Popup anchors correctly.
45
+ if (domRef.nodeName === 'BR' && domRef.parentElement) {
46
+ return domRef.parentElement;
47
+ }
34
48
  return domRef;
35
49
  }
36
50
  return null;
@@ -39,6 +53,34 @@ function getTargetElement(editorView, pos) {
39
53
  }
40
54
  }
41
55
 
56
+ /**
57
+ * Returns the position immediately after a table ancestor of `pos`, or
58
+ * `undefined` if not inside a table. Safe to cache per document version.
59
+ */
60
+ function resolveTableAfterPos(editorView, pos) {
61
+ var $pos = editorView.state.doc.resolve(pos);
62
+ for (var depth = $pos.depth; depth > 0; depth--) {
63
+ if ($pos.node(depth).type.name === 'table') {
64
+ return $pos.after(depth);
65
+ }
66
+ }
67
+ return undefined;
68
+ }
69
+
70
+ /**
71
+ * Returns the visual bottom of the pasted content. For positions inside a
72
+ * table, uses the pre-computed `tableAfterPos` to get the correct bottom edge.
73
+ */
74
+ function getVisualEndBottom(editorView, pasteEndPos, tableAfterPos) {
75
+ var endCoords = editorView.coordsAtPos(pasteEndPos);
76
+ var bottom = endCoords.bottom;
77
+ if (tableAfterPos !== undefined) {
78
+ var afterCoords = editorView.coordsAtPos(tableAfterPos);
79
+ bottom = Math.max(bottom, afterCoords.bottom);
80
+ }
81
+ return bottom;
82
+ }
83
+
42
84
  /**
43
85
  * Adjusts the vertical position of the paste menu to align with the top of the
44
86
  * pasted content using the exact coordinates at the paste start position,
@@ -56,10 +98,12 @@ function getTargetElement(editorView, pos) {
56
98
  * above the visible area.
57
99
  */
58
100
  function onPositionCalculated(editorView, pasteStartPos, pasteEndPos, targetElement, scrollableElement) {
101
+ // Pre-compute once per render to avoid doc.resolve() on every scroll frame.
102
+ var tableAfterPos = resolveTableAfterPos(editorView, pasteEndPos);
59
103
  return function (position) {
60
104
  var _position$top;
61
105
  var startCoords = editorView.coordsAtPos(pasteStartPos);
62
- var endCoords = editorView.coordsAtPos(pasteEndPos);
106
+ var endBottom = getVisualEndBottom(editorView, pasteEndPos, tableAfterPos);
63
107
  var targetRect = targetElement.getBoundingClientRect();
64
108
 
65
109
  // The Popup places the menu at the target's bottom edge by default.
@@ -73,7 +117,7 @@ function onPositionCalculated(editorView, pasteStartPos, pasteEndPos, targetElem
73
117
  // content is still visible.
74
118
  if (scrollableElement) {
75
119
  var scrollContainerTop = scrollableElement.getBoundingClientRect().top;
76
- if (startCoords.top < scrollContainerTop && endCoords.bottom > scrollContainerTop) {
120
+ if (startCoords.top < scrollContainerTop && endBottom > scrollContainerTop) {
77
121
  adjustedTop += scrollContainerTop - startCoords.top + _constants.PASTE_MENU_GAP_TOP;
78
122
  }
79
123
  }
@@ -115,7 +159,12 @@ var PasteActionsMenu = exports.PasteActionsMenu = function PasteActionsMenu(_ref
115
159
  var $pos = editorView.state.doc.resolve(lastContentPasted.pasteStartPos);
116
160
  var pasteAncestorNodeNames = [];
117
161
  for (var depth = $pos.depth; depth > 0; depth--) {
118
- pasteAncestorNodeNames.push($pos.node(depth).type.name);
162
+ // Only include an ancestor if the entire pasted range is contained within it.
163
+ // This prevents nodes like 'heading' from being flagged as ancestors when the
164
+ // pasted content starts in a heading but extends beyond it (e.g. heading + paragraph).
165
+ if (lastContentPasted.pasteEndPos <= $pos.end(depth)) {
166
+ pasteAncestorNodeNames.push($pos.node(depth).type.name);
167
+ }
119
168
  }
120
169
  var legacyVisible = (0, _toolbar2.isToolbarVisible)(editorView.state, lastContentPasted) && ((_lastContentPasted$te = (_lastContentPasted$te2 = lastContentPasted.text) === null || _lastContentPasted$te2 === void 0 ? void 0 : _lastContentPasted$te2.length) !== null && _lastContentPasted$te !== void 0 ? _lastContentPasted$te : 0) >= 100;
121
170
  (0, _commands.showToolbar)(lastContentPasted, selectedOption, legacyVisible, pasteAncestorNodeNames)(editorView.state, editorView.dispatch);
@@ -177,8 +226,7 @@ var PasteActionsMenu = exports.PasteActionsMenu = function PasteActionsMenu(_ref
177
226
  // so the Popup attaches its built-in scroll listener, which calls
178
227
  // scheduledUpdatePosition (RAF-throttled) on each scroll event — triggering
179
228
  // onPositionCalculated with fresh viewport coordinates.
180
- var targetForScroll = isToolbarShown ? getTargetElement(editorView, pasteStartPos) : null;
181
- var overflowScrollParent = targetForScroll ? (0, _ui.findOverflowScrollParent)(targetForScroll) : false;
229
+ var overflowScrollParent = isToolbarShown ? (0, _ui.findOverflowScrollParent)(editorView.dom) : false;
182
230
  var effectiveScrollableElement = overflowScrollParent || scrollableElement;
183
231
  var pasteMenuComponents = (_api$uiControlRegistr3 = api === null || api === void 0 || (_api$uiControlRegistr4 = api.uiControlRegistry) === null || _api$uiControlRegistr4 === void 0 ? void 0 : _api$uiControlRegistr4.actions.getComponents(_toolbar.PASTE_MENU.key)) !== null && _api$uiControlRegistr3 !== void 0 ? _api$uiControlRegistr3 : [];
184
232
  var anyComponentVisible = (0, _hasVisibleButton.hasVisibleButton)(pasteMenuComponents);
@@ -14,10 +14,21 @@ import { isToolbarVisible } from '../toolbar';
14
14
  import { getVisibleKeys, hasVisibleButton } from './hasVisibleButton';
15
15
  import { PasteActionsMenuContent } from './PasteActionsMenuContent';
16
16
  const PopupWithListeners = withReactEditorViewOuterListeners(Popup);
17
- function getTargetElement(editorView, pos) {
17
+ /**
18
+ * Returns the DOM element at the given document position for use as a Popup anchor.
19
+ * For empty blocks (BR elements), returns the parent element to ensure correct positioning.
20
+ */
21
+ export function getTargetElement(editorView, pos) {
18
22
  try {
19
23
  const domRef = findDomRefAtPos(pos, editorView.domAtPos.bind(editorView));
20
24
  if (domRef instanceof HTMLElement) {
25
+ // Empty blocks render a <br> placeholder whose bounding rect has no
26
+ // meaningful dimensions (height ≈ 0). Using it as the Popup anchor
27
+ // causes the menu to appear at an unexpected position. Walk up to the
28
+ // parent block element so the Popup anchors correctly.
29
+ if (domRef.nodeName === 'BR' && domRef.parentElement) {
30
+ return domRef.parentElement;
31
+ }
21
32
  return domRef;
22
33
  }
23
34
  return null;
@@ -26,6 +37,34 @@ function getTargetElement(editorView, pos) {
26
37
  }
27
38
  }
28
39
 
40
+ /**
41
+ * Returns the position immediately after a table ancestor of `pos`, or
42
+ * `undefined` if not inside a table. Safe to cache per document version.
43
+ */
44
+ export function resolveTableAfterPos(editorView, pos) {
45
+ const $pos = editorView.state.doc.resolve(pos);
46
+ for (let depth = $pos.depth; depth > 0; depth--) {
47
+ if ($pos.node(depth).type.name === 'table') {
48
+ return $pos.after(depth);
49
+ }
50
+ }
51
+ return undefined;
52
+ }
53
+
54
+ /**
55
+ * Returns the visual bottom of the pasted content. For positions inside a
56
+ * table, uses the pre-computed `tableAfterPos` to get the correct bottom edge.
57
+ */
58
+ export function getVisualEndBottom(editorView, pasteEndPos, tableAfterPos) {
59
+ const endCoords = editorView.coordsAtPos(pasteEndPos);
60
+ let bottom = endCoords.bottom;
61
+ if (tableAfterPos !== undefined) {
62
+ const afterCoords = editorView.coordsAtPos(tableAfterPos);
63
+ bottom = Math.max(bottom, afterCoords.bottom);
64
+ }
65
+ return bottom;
66
+ }
67
+
29
68
  /**
30
69
  * Adjusts the vertical position of the paste menu to align with the top of the
31
70
  * pasted content using the exact coordinates at the paste start position,
@@ -43,10 +82,12 @@ function getTargetElement(editorView, pos) {
43
82
  * above the visible area.
44
83
  */
45
84
  export function onPositionCalculated(editorView, pasteStartPos, pasteEndPos, targetElement, scrollableElement) {
85
+ // Pre-compute once per render to avoid doc.resolve() on every scroll frame.
86
+ const tableAfterPos = resolveTableAfterPos(editorView, pasteEndPos);
46
87
  return position => {
47
88
  var _position$top;
48
89
  const startCoords = editorView.coordsAtPos(pasteStartPos);
49
- const endCoords = editorView.coordsAtPos(pasteEndPos);
90
+ const endBottom = getVisualEndBottom(editorView, pasteEndPos, tableAfterPos);
50
91
  const targetRect = targetElement.getBoundingClientRect();
51
92
 
52
93
  // The Popup places the menu at the target's bottom edge by default.
@@ -60,7 +101,7 @@ export function onPositionCalculated(editorView, pasteStartPos, pasteEndPos, tar
60
101
  // content is still visible.
61
102
  if (scrollableElement) {
62
103
  const scrollContainerTop = scrollableElement.getBoundingClientRect().top;
63
- if (startCoords.top < scrollContainerTop && endCoords.bottom > scrollContainerTop) {
104
+ if (startCoords.top < scrollContainerTop && endBottom > scrollContainerTop) {
64
105
  adjustedTop += scrollContainerTop - startCoords.top + PASTE_MENU_GAP_TOP;
65
106
  }
66
107
  }
@@ -105,7 +146,12 @@ export const PasteActionsMenu = ({
105
146
  const $pos = editorView.state.doc.resolve(lastContentPasted.pasteStartPos);
106
147
  const pasteAncestorNodeNames = [];
107
148
  for (let depth = $pos.depth; depth > 0; depth--) {
108
- pasteAncestorNodeNames.push($pos.node(depth).type.name);
149
+ // Only include an ancestor if the entire pasted range is contained within it.
150
+ // This prevents nodes like 'heading' from being flagged as ancestors when the
151
+ // pasted content starts in a heading but extends beyond it (e.g. heading + paragraph).
152
+ if (lastContentPasted.pasteEndPos <= $pos.end(depth)) {
153
+ pasteAncestorNodeNames.push($pos.node(depth).type.name);
154
+ }
109
155
  }
110
156
  const legacyVisible = isToolbarVisible(editorView.state, lastContentPasted) && ((_lastContentPasted$te = (_lastContentPasted$te2 = lastContentPasted.text) === null || _lastContentPasted$te2 === void 0 ? void 0 : _lastContentPasted$te2.length) !== null && _lastContentPasted$te !== void 0 ? _lastContentPasted$te : 0) >= 100;
111
157
  showToolbar(lastContentPasted, selectedOption, legacyVisible, pasteAncestorNodeNames)(editorView.state, editorView.dispatch);
@@ -168,8 +214,7 @@ export const PasteActionsMenu = ({
168
214
  // so the Popup attaches its built-in scroll listener, which calls
169
215
  // scheduledUpdatePosition (RAF-throttled) on each scroll event — triggering
170
216
  // onPositionCalculated with fresh viewport coordinates.
171
- const targetForScroll = isToolbarShown ? getTargetElement(editorView, pasteStartPos) : null;
172
- const overflowScrollParent = targetForScroll ? findOverflowScrollParent(targetForScroll) : false;
217
+ const overflowScrollParent = isToolbarShown ? findOverflowScrollParent(editorView.dom) : false;
173
218
  const effectiveScrollableElement = overflowScrollParent || scrollableElement;
174
219
  const pasteMenuComponents = (_api$uiControlRegistr3 = api === null || api === void 0 ? void 0 : (_api$uiControlRegistr4 = api.uiControlRegistry) === null || _api$uiControlRegistr4 === void 0 ? void 0 : _api$uiControlRegistr4.actions.getComponents(PASTE_MENU.key)) !== null && _api$uiControlRegistr3 !== void 0 ? _api$uiControlRegistr3 : [];
175
220
  const anyComponentVisible = hasVisibleButton(pasteMenuComponents);
@@ -17,10 +17,21 @@ import { isToolbarVisible } from '../toolbar';
17
17
  import { getVisibleKeys, hasVisibleButton } from './hasVisibleButton';
18
18
  import { PasteActionsMenuContent } from './PasteActionsMenuContent';
19
19
  var PopupWithListeners = withReactEditorViewOuterListeners(Popup);
20
- function getTargetElement(editorView, pos) {
20
+ /**
21
+ * Returns the DOM element at the given document position for use as a Popup anchor.
22
+ * For empty blocks (BR elements), returns the parent element to ensure correct positioning.
23
+ */
24
+ export function getTargetElement(editorView, pos) {
21
25
  try {
22
26
  var domRef = findDomRefAtPos(pos, editorView.domAtPos.bind(editorView));
23
27
  if (domRef instanceof HTMLElement) {
28
+ // Empty blocks render a <br> placeholder whose bounding rect has no
29
+ // meaningful dimensions (height ≈ 0). Using it as the Popup anchor
30
+ // causes the menu to appear at an unexpected position. Walk up to the
31
+ // parent block element so the Popup anchors correctly.
32
+ if (domRef.nodeName === 'BR' && domRef.parentElement) {
33
+ return domRef.parentElement;
34
+ }
24
35
  return domRef;
25
36
  }
26
37
  return null;
@@ -29,6 +40,34 @@ function getTargetElement(editorView, pos) {
29
40
  }
30
41
  }
31
42
 
43
+ /**
44
+ * Returns the position immediately after a table ancestor of `pos`, or
45
+ * `undefined` if not inside a table. Safe to cache per document version.
46
+ */
47
+ export function resolveTableAfterPos(editorView, pos) {
48
+ var $pos = editorView.state.doc.resolve(pos);
49
+ for (var depth = $pos.depth; depth > 0; depth--) {
50
+ if ($pos.node(depth).type.name === 'table') {
51
+ return $pos.after(depth);
52
+ }
53
+ }
54
+ return undefined;
55
+ }
56
+
57
+ /**
58
+ * Returns the visual bottom of the pasted content. For positions inside a
59
+ * table, uses the pre-computed `tableAfterPos` to get the correct bottom edge.
60
+ */
61
+ export function getVisualEndBottom(editorView, pasteEndPos, tableAfterPos) {
62
+ var endCoords = editorView.coordsAtPos(pasteEndPos);
63
+ var bottom = endCoords.bottom;
64
+ if (tableAfterPos !== undefined) {
65
+ var afterCoords = editorView.coordsAtPos(tableAfterPos);
66
+ bottom = Math.max(bottom, afterCoords.bottom);
67
+ }
68
+ return bottom;
69
+ }
70
+
32
71
  /**
33
72
  * Adjusts the vertical position of the paste menu to align with the top of the
34
73
  * pasted content using the exact coordinates at the paste start position,
@@ -46,10 +85,12 @@ function getTargetElement(editorView, pos) {
46
85
  * above the visible area.
47
86
  */
48
87
  export function onPositionCalculated(editorView, pasteStartPos, pasteEndPos, targetElement, scrollableElement) {
88
+ // Pre-compute once per render to avoid doc.resolve() on every scroll frame.
89
+ var tableAfterPos = resolveTableAfterPos(editorView, pasteEndPos);
49
90
  return function (position) {
50
91
  var _position$top;
51
92
  var startCoords = editorView.coordsAtPos(pasteStartPos);
52
- var endCoords = editorView.coordsAtPos(pasteEndPos);
93
+ var endBottom = getVisualEndBottom(editorView, pasteEndPos, tableAfterPos);
53
94
  var targetRect = targetElement.getBoundingClientRect();
54
95
 
55
96
  // The Popup places the menu at the target's bottom edge by default.
@@ -63,7 +104,7 @@ export function onPositionCalculated(editorView, pasteStartPos, pasteEndPos, tar
63
104
  // content is still visible.
64
105
  if (scrollableElement) {
65
106
  var scrollContainerTop = scrollableElement.getBoundingClientRect().top;
66
- if (startCoords.top < scrollContainerTop && endCoords.bottom > scrollContainerTop) {
107
+ if (startCoords.top < scrollContainerTop && endBottom > scrollContainerTop) {
67
108
  adjustedTop += scrollContainerTop - startCoords.top + PASTE_MENU_GAP_TOP;
68
109
  }
69
110
  }
@@ -105,7 +146,12 @@ export var PasteActionsMenu = function PasteActionsMenu(_ref) {
105
146
  var $pos = editorView.state.doc.resolve(lastContentPasted.pasteStartPos);
106
147
  var pasteAncestorNodeNames = [];
107
148
  for (var depth = $pos.depth; depth > 0; depth--) {
108
- pasteAncestorNodeNames.push($pos.node(depth).type.name);
149
+ // Only include an ancestor if the entire pasted range is contained within it.
150
+ // This prevents nodes like 'heading' from being flagged as ancestors when the
151
+ // pasted content starts in a heading but extends beyond it (e.g. heading + paragraph).
152
+ if (lastContentPasted.pasteEndPos <= $pos.end(depth)) {
153
+ pasteAncestorNodeNames.push($pos.node(depth).type.name);
154
+ }
109
155
  }
110
156
  var legacyVisible = isToolbarVisible(editorView.state, lastContentPasted) && ((_lastContentPasted$te = (_lastContentPasted$te2 = lastContentPasted.text) === null || _lastContentPasted$te2 === void 0 ? void 0 : _lastContentPasted$te2.length) !== null && _lastContentPasted$te !== void 0 ? _lastContentPasted$te : 0) >= 100;
111
157
  showToolbar(lastContentPasted, selectedOption, legacyVisible, pasteAncestorNodeNames)(editorView.state, editorView.dispatch);
@@ -167,8 +213,7 @@ export var PasteActionsMenu = function PasteActionsMenu(_ref) {
167
213
  // so the Popup attaches its built-in scroll listener, which calls
168
214
  // scheduledUpdatePosition (RAF-throttled) on each scroll event — triggering
169
215
  // onPositionCalculated with fresh viewport coordinates.
170
- var targetForScroll = isToolbarShown ? getTargetElement(editorView, pasteStartPos) : null;
171
- var overflowScrollParent = targetForScroll ? findOverflowScrollParent(targetForScroll) : false;
216
+ var overflowScrollParent = isToolbarShown ? findOverflowScrollParent(editorView.dom) : false;
172
217
  var effectiveScrollableElement = overflowScrollParent || scrollableElement;
173
218
  var pasteMenuComponents = (_api$uiControlRegistr3 = api === null || api === void 0 || (_api$uiControlRegistr4 = api.uiControlRegistry) === null || _api$uiControlRegistr4 === void 0 ? void 0 : _api$uiControlRegistr4.actions.getComponents(PASTE_MENU.key)) !== null && _api$uiControlRegistr3 !== void 0 ? _api$uiControlRegistr3 : [];
174
219
  var anyComponentVisible = hasVisibleButton(pasteMenuComponents);
@@ -9,6 +9,21 @@ interface PasteActionsMenuProps {
9
9
  mountTo?: HTMLElement;
10
10
  scrollableElement?: HTMLElement;
11
11
  }
12
+ /**
13
+ * Returns the DOM element at the given document position for use as a Popup anchor.
14
+ * For empty blocks (BR elements), returns the parent element to ensure correct positioning.
15
+ */
16
+ export declare function getTargetElement(editorView: EditorView, pos: number): HTMLElement | null;
17
+ /**
18
+ * Returns the position immediately after a table ancestor of `pos`, or
19
+ * `undefined` if not inside a table. Safe to cache per document version.
20
+ */
21
+ export declare function resolveTableAfterPos(editorView: EditorView, pos: number): number | undefined;
22
+ /**
23
+ * Returns the visual bottom of the pasted content. For positions inside a
24
+ * table, uses the pre-computed `tableAfterPos` to get the correct bottom edge.
25
+ */
26
+ export declare function getVisualEndBottom(editorView: EditorView, pasteEndPos: number, tableAfterPos?: number): number;
12
27
  /**
13
28
  * Adjusts the vertical position of the paste menu to align with the top of the
14
29
  * pasted content using the exact coordinates at the paste start position,
@@ -9,6 +9,21 @@ interface PasteActionsMenuProps {
9
9
  mountTo?: HTMLElement;
10
10
  scrollableElement?: HTMLElement;
11
11
  }
12
+ /**
13
+ * Returns the DOM element at the given document position for use as a Popup anchor.
14
+ * For empty blocks (BR elements), returns the parent element to ensure correct positioning.
15
+ */
16
+ export declare function getTargetElement(editorView: EditorView, pos: number): HTMLElement | null;
17
+ /**
18
+ * Returns the position immediately after a table ancestor of `pos`, or
19
+ * `undefined` if not inside a table. Safe to cache per document version.
20
+ */
21
+ export declare function resolveTableAfterPos(editorView: EditorView, pos: number): number | undefined;
22
+ /**
23
+ * Returns the visual bottom of the pasted content. For positions inside a
24
+ * table, uses the pre-computed `tableAfterPos` to get the correct bottom edge.
25
+ */
26
+ export declare function getVisualEndBottom(editorView: EditorView, pasteEndPos: number, tableAfterPos?: number): number;
12
27
  /**
13
28
  * Adjusts the vertical position of the paste menu to align with the top of the
14
29
  * pasted content using the exact coordinates at the paste start position,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atlaskit/editor-plugin-paste-options-toolbar",
3
- "version": "9.1.3",
3
+ "version": "9.1.5",
4
4
  "description": "Paste options toolbar for @atlaskit/editor-core",
5
5
  "author": "Atlassian Pty Ltd",
6
6
  "license": "Apache-2.0",
@@ -48,7 +48,7 @@
48
48
  "react-intl-next": "npm:react-intl@^5.18.1"
49
49
  },
50
50
  "peerDependencies": {
51
- "@atlaskit/editor-common": "^112.5.0",
51
+ "@atlaskit/editor-common": "^112.6.0",
52
52
  "react": "^18.2.0",
53
53
  "react-dom": "^18.2.0"
54
54
  },