@atlaskit/editor-plugin-block-controls 12.4.1 → 13.0.0

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.
Files changed (104) hide show
  1. package/CHANGELOG.md +38 -0
  2. package/block-decoration-utils/anchor-name/package.json +1 -8
  3. package/block-decoration-utils/consts/package.json +1 -8
  4. package/block-decoration-utils/dom-attr-name/package.json +1 -8
  5. package/block-decoration-utils/drag-handle-positions/package.json +1 -8
  6. package/block-decoration-utils/package.json +1 -8
  7. package/block-decoration-utils/visibility-container/package.json +1 -8
  8. package/block-decoration-utils/widget-positions/package.json +1 -8
  9. package/blockControlsPlugin/package.json +1 -8
  10. package/blockControlsPluginType/package.json +1 -8
  11. package/dist/cjs/blockControlsPlugin.js +1 -1
  12. package/dist/cjs/pm-plugins/interaction-tracking/constants.js +8 -0
  13. package/dist/cjs/pm-plugins/interaction-tracking/handle-mouse-move.js +102 -14
  14. package/dist/cjs/pm-plugins/interaction-tracking/pm-plugin.js +44 -10
  15. package/dist/cjs/ui/visibility-container.js +2 -0
  16. package/dist/es2019/blockControlsPlugin.js +1 -1
  17. package/dist/es2019/pm-plugins/interaction-tracking/constants.js +2 -0
  18. package/dist/es2019/pm-plugins/interaction-tracking/handle-mouse-move.js +86 -13
  19. package/dist/es2019/pm-plugins/interaction-tracking/pm-plugin.js +44 -11
  20. package/dist/es2019/ui/visibility-container.js +2 -0
  21. package/dist/esm/blockControlsPlugin.js +1 -1
  22. package/dist/esm/pm-plugins/interaction-tracking/constants.js +2 -0
  23. package/dist/esm/pm-plugins/interaction-tracking/handle-mouse-move.js +102 -14
  24. package/dist/esm/pm-plugins/interaction-tracking/pm-plugin.js +44 -10
  25. package/dist/esm/ui/visibility-container.js +2 -0
  26. package/dist/types/pm-plugins/interaction-tracking/constants.d.ts +2 -0
  27. package/dist/types/pm-plugins/interaction-tracking/handle-mouse-move.d.ts +3 -1
  28. package/dist/types/pm-plugins/interaction-tracking/pm-plugin.d.ts +3 -1
  29. package/package.json +37 -41
  30. package/dist/types-ts4.5/blockControlsPlugin.d.ts +0 -2
  31. package/dist/types-ts4.5/blockControlsPluginType.d.ts +0 -250
  32. package/dist/types-ts4.5/editor-commands/handle-key-down-with-preserved-selection.d.ts +0 -17
  33. package/dist/types-ts4.5/editor-commands/map-preserved-selection.d.ts +0 -13
  34. package/dist/types-ts4.5/editor-commands/move-node-with-block-menu.d.ts +0 -4
  35. package/dist/types-ts4.5/editor-commands/move-node.d.ts +0 -5
  36. package/dist/types-ts4.5/editor-commands/move-to-layout.d.ts +0 -7
  37. package/dist/types-ts4.5/editor-commands/show-drag-handle.d.ts +0 -3
  38. package/dist/types-ts4.5/editor-commands/utils/move-node-utils.d.ts +0 -31
  39. package/dist/types-ts4.5/entry-points/block-decoration-utils-anchor-name.d.ts +0 -1
  40. package/dist/types-ts4.5/entry-points/block-decoration-utils-consts.d.ts +0 -1
  41. package/dist/types-ts4.5/entry-points/block-decoration-utils-dom-attr-name.d.ts +0 -1
  42. package/dist/types-ts4.5/entry-points/block-decoration-utils-drag-handle-positions.d.ts +0 -1
  43. package/dist/types-ts4.5/entry-points/block-decoration-utils-visibility-container.d.ts +0 -1
  44. package/dist/types-ts4.5/entry-points/block-decoration-utils-widget-positions.d.ts +0 -1
  45. package/dist/types-ts4.5/entry-points/blockControlsPlugin.d.ts +0 -1
  46. package/dist/types-ts4.5/entry-points/blockControlsPluginType.d.ts +0 -1
  47. package/dist/types-ts4.5/index.d.ts +0 -2
  48. package/dist/types-ts4.5/pm-plugins/decorations-anchor.d.ts +0 -15
  49. package/dist/types-ts4.5/pm-plugins/decorations-common.d.ts +0 -9
  50. package/dist/types-ts4.5/pm-plugins/decorations-drag-handle.d.ts +0 -30
  51. package/dist/types-ts4.5/pm-plugins/decorations-drop-target-active.d.ts +0 -13
  52. package/dist/types-ts4.5/pm-plugins/decorations-drop-target.d.ts +0 -21
  53. package/dist/types-ts4.5/pm-plugins/decorations-find-surrounding-nodes.d.ts +0 -22
  54. package/dist/types-ts4.5/pm-plugins/decorations-quick-insert-button.d.ts +0 -30
  55. package/dist/types-ts4.5/pm-plugins/first-node-dec-plugin.d.ts +0 -5
  56. package/dist/types-ts4.5/pm-plugins/handle-mouse-down.d.ts +0 -4
  57. package/dist/types-ts4.5/pm-plugins/handle-mouse-over.d.ts +0 -4
  58. package/dist/types-ts4.5/pm-plugins/interaction-tracking/commands.d.ts +0 -7
  59. package/dist/types-ts4.5/pm-plugins/interaction-tracking/handle-key-down.d.ts +0 -2
  60. package/dist/types-ts4.5/pm-plugins/interaction-tracking/handle-mouse-move.d.ts +0 -4
  61. package/dist/types-ts4.5/pm-plugins/interaction-tracking/pm-plugin.d.ts +0 -20
  62. package/dist/types-ts4.5/pm-plugins/keymap.d.ts +0 -5
  63. package/dist/types-ts4.5/pm-plugins/main.d.ts +0 -63
  64. package/dist/types-ts4.5/pm-plugins/quick-insert-calculate-position.d.ts +0 -12
  65. package/dist/types-ts4.5/pm-plugins/selection-preservation/editor-commands.d.ts +0 -13
  66. package/dist/types-ts4.5/pm-plugins/selection-preservation/plugin-key.d.ts +0 -3
  67. package/dist/types-ts4.5/pm-plugins/selection-preservation/pm-plugin.d.ts +0 -35
  68. package/dist/types-ts4.5/pm-plugins/selection-preservation/types.d.ts +0 -7
  69. package/dist/types-ts4.5/pm-plugins/selection-preservation/utils.d.ts +0 -30
  70. package/dist/types-ts4.5/pm-plugins/utils/active-anchor-tracker.d.ts +0 -16
  71. package/dist/types-ts4.5/pm-plugins/utils/analytics.d.ts +0 -12
  72. package/dist/types-ts4.5/pm-plugins/utils/anchor-utils.d.ts +0 -27
  73. package/dist/types-ts4.5/pm-plugins/utils/check-fragment.d.ts +0 -9
  74. package/dist/types-ts4.5/pm-plugins/utils/check-media-layout.d.ts +0 -2
  75. package/dist/types-ts4.5/pm-plugins/utils/consts.d.ts +0 -2
  76. package/dist/types-ts4.5/pm-plugins/utils/drag-handle-positions.d.ts +0 -12
  77. package/dist/types-ts4.5/pm-plugins/utils/expand-and-update-selection.d.ts +0 -20
  78. package/dist/types-ts4.5/pm-plugins/utils/getNestedNodePosition.d.ts +0 -16
  79. package/dist/types-ts4.5/pm-plugins/utils/getSelection.d.ts +0 -32
  80. package/dist/types-ts4.5/pm-plugins/utils/inline-drop-target.d.ts +0 -7
  81. package/dist/types-ts4.5/pm-plugins/utils/marks.d.ts +0 -25
  82. package/dist/types-ts4.5/pm-plugins/utils/remove-from-source.d.ts +0 -3
  83. package/dist/types-ts4.5/pm-plugins/utils/selection.d.ts +0 -71
  84. package/dist/types-ts4.5/pm-plugins/utils/transactions.d.ts +0 -31
  85. package/dist/types-ts4.5/pm-plugins/utils/update-column-widths.d.ts +0 -6
  86. package/dist/types-ts4.5/pm-plugins/utils/update-selection.d.ts +0 -4
  87. package/dist/types-ts4.5/pm-plugins/utils/validation.d.ts +0 -24
  88. package/dist/types-ts4.5/pm-plugins/utils/widget-positions.d.ts +0 -14
  89. package/dist/types-ts4.5/pm-plugins/vanilla-quick-insert.d.ts +0 -21
  90. package/dist/types-ts4.5/ui/block-decoration-utils.d.ts +0 -6
  91. package/dist/types-ts4.5/ui/consts.d.ts +0 -67
  92. package/dist/types-ts4.5/ui/drag-handle-nested-icon.d.ts +0 -12
  93. package/dist/types-ts4.5/ui/drag-handle.d.ts +0 -20
  94. package/dist/types-ts4.5/ui/drag-preview.d.ts +0 -9
  95. package/dist/types-ts4.5/ui/drop-target-layout.d.ts +0 -18
  96. package/dist/types-ts4.5/ui/drop-target.d.ts +0 -22
  97. package/dist/types-ts4.5/ui/global-styles.d.ts +0 -10
  98. package/dist/types-ts4.5/ui/inline-drop-target.d.ts +0 -7
  99. package/dist/types-ts4.5/ui/quick-insert-button.d.ts +0 -24
  100. package/dist/types-ts4.5/ui/utils/anchor-name.d.ts +0 -12
  101. package/dist/types-ts4.5/ui/utils/document-checks.d.ts +0 -5
  102. package/dist/types-ts4.5/ui/utils/dom-attr-name.d.ts +0 -5
  103. package/dist/types-ts4.5/ui/utils/editor-commands.d.ts +0 -2
  104. package/dist/types-ts4.5/ui/visibility-container.d.ts +0 -16
package/CHANGELOG.md CHANGED
@@ -1,5 +1,43 @@
1
1
  # @atlaskit/editor-plugin-block-controls
2
2
 
3
+ ## 13.0.0
4
+
5
+ ### Major Changes
6
+
7
+ - [`f2dc9097319f0`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/f2dc9097319f0) - ###
8
+ Dropped support for _legacy_ Typescript 4 types. **Typescript 5 is now the new minimum**.
9
+
10
+ Removes the `typesVersions` property and `dist/types-ts4.5` directory from the dist.
11
+
12
+ Types are now exclusively via the `"types": "dist/types/index.d.ts"` property.
13
+
14
+ ```diff
15
+ - "typesVersions": {
16
+ - ">=4.5 <4.9": {
17
+ - "*": [
18
+ - "dist/types-ts4.5/*",
19
+ - "dist/types-ts4.5/index.d.ts"
20
+ - ]
21
+ - }
22
+ - },
23
+ ```
24
+
25
+ ### Minor Changes
26
+
27
+ - [`2f16223a8aa3a`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/2f16223a8aa3a) -
28
+ Extend the right-side Remix button hover zone into the empty right margin beside a block, with a
29
+ reserved gap for the Rovo button on the far right.
30
+
31
+ ### Patch Changes
32
+
33
+ - Updated dependencies
34
+
35
+ ## 12.4.2
36
+
37
+ ### Patch Changes
38
+
39
+ - Updated dependencies
40
+
3
41
  ## 12.4.1
4
42
 
5
43
  ### Patch Changes
@@ -6,12 +6,5 @@
6
6
  "sideEffects": [
7
7
  "*.compiled.css"
8
8
  ],
9
- "types": "../../dist/types/entry-points/block-decoration-utils-anchor-name.d.ts",
10
- "typesVersions": {
11
- ">=4.5 <5.9": {
12
- "*": [
13
- "../../dist/types-ts4.5/entry-points/block-decoration-utils-anchor-name.d.ts"
14
- ]
15
- }
16
- }
9
+ "types": "../../dist/types/entry-points/block-decoration-utils-anchor-name.d.ts"
17
10
  }
@@ -6,12 +6,5 @@
6
6
  "sideEffects": [
7
7
  "*.compiled.css"
8
8
  ],
9
- "types": "../../dist/types/entry-points/block-decoration-utils-consts.d.ts",
10
- "typesVersions": {
11
- ">=4.5 <5.9": {
12
- "*": [
13
- "../../dist/types-ts4.5/entry-points/block-decoration-utils-consts.d.ts"
14
- ]
15
- }
16
- }
9
+ "types": "../../dist/types/entry-points/block-decoration-utils-consts.d.ts"
17
10
  }
@@ -6,12 +6,5 @@
6
6
  "sideEffects": [
7
7
  "*.compiled.css"
8
8
  ],
9
- "types": "../../dist/types/entry-points/block-decoration-utils-dom-attr-name.d.ts",
10
- "typesVersions": {
11
- ">=4.5 <5.9": {
12
- "*": [
13
- "../../dist/types-ts4.5/entry-points/block-decoration-utils-dom-attr-name.d.ts"
14
- ]
15
- }
16
- }
9
+ "types": "../../dist/types/entry-points/block-decoration-utils-dom-attr-name.d.ts"
17
10
  }
@@ -6,12 +6,5 @@
6
6
  "sideEffects": [
7
7
  "*.compiled.css"
8
8
  ],
9
- "types": "../../dist/types/entry-points/block-decoration-utils-drag-handle-positions.d.ts",
10
- "typesVersions": {
11
- ">=4.5 <5.9": {
12
- "*": [
13
- "../../dist/types-ts4.5/entry-points/block-decoration-utils-drag-handle-positions.d.ts"
14
- ]
15
- }
16
- }
9
+ "types": "../../dist/types/entry-points/block-decoration-utils-drag-handle-positions.d.ts"
17
10
  }
@@ -6,12 +6,5 @@
6
6
  "sideEffects": [
7
7
  "*.compiled.css"
8
8
  ],
9
- "types": "../dist/types/ui/block-decoration-utils.d.ts",
10
- "typesVersions": {
11
- ">=4.5 <5.9": {
12
- "*": [
13
- "../dist/types-ts4.5/ui/block-decoration-utils.d.ts"
14
- ]
15
- }
16
- }
9
+ "types": "../dist/types/ui/block-decoration-utils.d.ts"
17
10
  }
@@ -6,12 +6,5 @@
6
6
  "sideEffects": [
7
7
  "*.compiled.css"
8
8
  ],
9
- "types": "../../dist/types/entry-points/block-decoration-utils-visibility-container.d.ts",
10
- "typesVersions": {
11
- ">=4.5 <5.9": {
12
- "*": [
13
- "../../dist/types-ts4.5/entry-points/block-decoration-utils-visibility-container.d.ts"
14
- ]
15
- }
16
- }
9
+ "types": "../../dist/types/entry-points/block-decoration-utils-visibility-container.d.ts"
17
10
  }
@@ -6,12 +6,5 @@
6
6
  "sideEffects": [
7
7
  "*.compiled.css"
8
8
  ],
9
- "types": "../../dist/types/entry-points/block-decoration-utils-widget-positions.d.ts",
10
- "typesVersions": {
11
- ">=4.5 <5.9": {
12
- "*": [
13
- "../../dist/types-ts4.5/entry-points/block-decoration-utils-widget-positions.d.ts"
14
- ]
15
- }
16
- }
9
+ "types": "../../dist/types/entry-points/block-decoration-utils-widget-positions.d.ts"
17
10
  }
@@ -6,12 +6,5 @@
6
6
  "sideEffects": [
7
7
  "*.compiled.css"
8
8
  ],
9
- "types": "../dist/types/entry-points/blockControlsPlugin.d.ts",
10
- "typesVersions": {
11
- ">=4.5 <5.9": {
12
- "*": [
13
- "../dist/types-ts4.5/entry-points/blockControlsPlugin.d.ts"
14
- ]
15
- }
16
- }
9
+ "types": "../dist/types/entry-points/blockControlsPlugin.d.ts"
17
10
  }
@@ -6,12 +6,5 @@
6
6
  "sideEffects": [
7
7
  "*.compiled.css"
8
8
  ],
9
- "types": "../dist/types/entry-points/blockControlsPluginType.d.ts",
10
- "typesVersions": {
11
- ">=4.5 <5.9": {
12
- "*": [
13
- "../dist/types-ts4.5/entry-points/blockControlsPluginType.d.ts"
14
- ]
15
- }
16
- }
9
+ "types": "../dist/types/entry-points/blockControlsPluginType.d.ts"
17
10
  }
@@ -90,7 +90,7 @@ var blockControlsPlugin = exports.blockControlsPlugin = function blockControlsPl
90
90
  pmPlugins.push({
91
91
  name: 'blockControlsInteractionTrackingPlugin',
92
92
  plugin: function plugin() {
93
- return (0, _pmPlugin.createInteractionTrackingPlugin)(rightSideControlsEnabled);
93
+ return (0, _pmPlugin.createInteractionTrackingPlugin)(rightSideControlsEnabled, api);
94
94
  }
95
95
  });
96
96
  }
@@ -0,0 +1,8 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.RIGHT_MARGIN_ROVO_GAP_PX = void 0;
7
+ /** Far-right margin width reserved for the Rovo button, where the Remix button must not show. */
8
+ var RIGHT_MARGIN_ROVO_GAP_PX = exports.RIGHT_MARGIN_ROVO_GAP_PX = 80;
@@ -4,8 +4,14 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.handleMouseMove = exports.handleMouseLeave = exports.handleMouseEnter = void 0;
7
+ var _experiments = require("@atlaskit/tmp-editor-statsig/experiments");
8
+ var _handleMouseOver = require("../handle-mouse-over");
7
9
  var _commands = require("./commands");
10
+ var _constants = require("./constants");
8
11
  var _pmPlugin = require("./pm-plugin");
12
+ function _createForOfIteratorHelper(r, e) { var t = "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && "number" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t.return || t.return(); } finally { if (u) throw o; } } }; }
13
+ function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
14
+ function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
9
15
  /** Per-view pending hover state; avoids cross-editor singleton. */
10
16
  var pendingByView = new WeakMap();
11
17
 
@@ -25,11 +31,67 @@ var clearPendingHoverSide = function clearPendingHoverSide(view) {
25
31
  var BLOCK_SELECTORS = '[data-node-anchor], [data-drag-handler-anchor-name]';
26
32
  var RIGHT_EDGE_SELECTOR = '[data-blocks-right-edge-button-container]';
27
33
 
34
+ // Top-level blocks (no block ancestor), matched by anchor attribute so it works under both the
35
+ // legacy and native-anchor schemes.
36
+ var getRootBlocks = function getRootBlocks(view) {
37
+ return Array.from(view.dom.querySelectorAll(BLOCK_SELECTORS)).filter(function (el) {
38
+ var _el$parentElement;
39
+ return !((_el$parentElement = el.parentElement) !== null && _el$parentElement !== void 0 && _el$parentElement.closest(BLOCK_SELECTORS));
40
+ });
41
+ };
42
+
43
+ // Find the root block whose vertical bounds contain clientY. Returns the measured rect so callers
44
+ // can reuse it without re-measuring.
45
+ var findBlockAtY = function findBlockAtY(view, clientY) {
46
+ var _iterator = _createForOfIteratorHelper(getRootBlocks(view)),
47
+ _step;
48
+ try {
49
+ for (_iterator.s(); !(_step = _iterator.n()).done;) {
50
+ var el = _step.value;
51
+ var rect = el.getBoundingClientRect();
52
+ if (clientY >= rect.top && clientY <= rect.bottom) {
53
+ return {
54
+ block: el,
55
+ rect: rect
56
+ };
57
+ }
58
+ }
59
+ } catch (err) {
60
+ _iterator.e(err);
61
+ } finally {
62
+ _iterator.f();
63
+ }
64
+ return null;
65
+ };
66
+ var getRightMarginBoundary = function getRightMarginBoundary(view) {
67
+ var _view$dom$ownerDocume, _view$dom$ownerDocume2;
68
+ return ((_view$dom$ownerDocume = (_view$dom$ownerDocume2 = view.dom.ownerDocument.defaultView) === null || _view$dom$ownerDocume2 === void 0 ? void 0 : _view$dom$ownerDocume2.innerWidth) !== null && _view$dom$ownerDocume !== void 0 ? _view$dom$ownerDocume : Number.POSITIVE_INFINITY) - _constants.RIGHT_MARGIN_ROVO_GAP_PX;
69
+ };
70
+ // not in the right margin
71
+
72
+ // Classify where the cursor sits in the right margin beside the block at its height, running the
73
+ // block lookup once so the caller doesn't traverse the DOM twice per mousemove.
74
+ var classifyRightMarginPosition = function classifyRightMarginPosition(view, event) {
75
+ var found = findBlockAtY(view, event.clientY);
76
+ if (!found) {
77
+ return null;
78
+ }
79
+ if (event.clientX <= found.rect.right) {
80
+ return null;
81
+ }
82
+ return event.clientX > getRightMarginBoundary(view) ? {
83
+ type: 'gap'
84
+ } : {
85
+ type: 'active',
86
+ block: found.block
87
+ };
88
+ };
89
+
28
90
  /**
29
91
  * Process hover position and set left/right side. Only invoked when right-side controls are
30
92
  * enabled (confluence_remix_button_right_side_block_fg); handleMouseMove returns early otherwise.
31
93
  */
32
- var processHoverSide = function processHoverSide(view) {
94
+ var processHoverSide = function processHoverSide(view, api) {
33
95
  var event = pendingByView.get(view);
34
96
  if (!event) {
35
97
  return;
@@ -60,20 +122,45 @@ var processHoverSide = function processHoverSide(view) {
60
122
  return;
61
123
  }
62
124
 
63
- // Primary path: depth-1 block (doc direct child). Decorations-anchor sets [data-drag-handler-anchor-depth="1"]
64
- // on every root block (table, layoutSection, expand, etc.), so we get the whole block without per-type logic.
65
- var blockElement = target === null || target === void 0 ? void 0 : target.closest(BLOCK_SELECTORS);
66
- var depth1Block = blockElement instanceof HTMLElement ? blockElement.closest('[data-drag-handler-anchor-depth="1"]') : null;
67
- var boundsElement = depth1Block instanceof HTMLElement ? depth1Block : editorContentArea;
68
- if (!boundsElement) {
69
- if ((state === null || state === void 0 ? void 0 : state.hoverSide) !== undefined) {
70
- (0, _commands.clearHoverSide)(view);
125
+ // Added right-margin hover, gated so it can be rolled back. When off, fall through to midpoint.
126
+ if ((0, _experiments.editorExperiment)('remix_button_right_margin_hover', true)) {
127
+ var closestBlock = target === null || target === void 0 ? void 0 : target.closest(BLOCK_SELECTORS);
128
+ var blockElement = closestBlock instanceof HTMLElement ? closestBlock : null;
129
+
130
+ // Not over a block: the cursor may be in the right margin beside content.
131
+ var marginZone = blockElement ? null : classifyRightMarginPosition(view, event);
132
+ if ((marginZone === null || marginZone === void 0 ? void 0 : marginZone.type) === 'active' && api) {
133
+ // handleMouseOver only reads event.target, so a target-only stand-in is enough here.
134
+ (0, _handleMouseOver.handleMouseOver)(view, {
135
+ target: marginZone.block
136
+ }, api);
137
+ // mouseenter doesn't fire over the click overlay, so clear isMouseOut here to re-show.
138
+ if (state !== null && state !== void 0 && state.isMouseOut) {
139
+ (0, _commands.mouseEnter)(view);
140
+ }
141
+ if ((state === null || state === void 0 ? void 0 : state.hoverSide) !== 'right') {
142
+ (0, _commands.setHoverSide)(view, 'right');
143
+ }
144
+ return;
71
145
  }
72
- return;
146
+
147
+ // In the Rovo gap, dismiss the controls so the button doesn't linger over the Rovo button.
148
+ if ((marginZone === null || marginZone === void 0 ? void 0 : marginZone.type) === 'gap' || event.clientX > getRightMarginBoundary(view)) {
149
+ if (!(state !== null && state !== void 0 && state.isMouseOut)) {
150
+ (0, _commands.clearHoverSide)(view);
151
+ (0, _commands.mouseLeave)(view);
152
+ }
153
+ return;
154
+ }
155
+
156
+ // Over a block: fall through to the midpoint split so the left half keeps the drag handle and
157
+ // the right half shows the Remix button, matching the experiment-off behaviour.
73
158
  }
74
- var _boundsElement$getBou = boundsElement.getBoundingClientRect(),
75
- left = _boundsElement$getBou.left,
76
- right = _boundsElement$getBou.right;
159
+
160
+ // Pick the side from the content midpoint, keeping the original left/right halves.
161
+ var _editorContentArea$ge = editorContentArea.getBoundingClientRect(),
162
+ left = _editorContentArea$ge.left,
163
+ right = _editorContentArea$ge.right;
77
164
  var midpoint = (left + right) / 2;
78
165
  var nextHoverSide = event.clientX > midpoint ? 'right' : 'left';
79
166
  if ((state === null || state === void 0 ? void 0 : state.hoverSide) !== nextHoverSide) {
@@ -82,6 +169,7 @@ var processHoverSide = function processHoverSide(view) {
82
169
  };
83
170
  var handleMouseMove = exports.handleMouseMove = function handleMouseMove(view, event) {
84
171
  var rightSideControlsEnabled = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
172
+ var api = arguments.length > 3 ? arguments[3] : undefined;
85
173
  var state = (0, _pmPlugin.getInteractionTrackingState)(view.state);
86
174
  // if user has stopped editing and moved their mouse, show block controls again
87
175
  if (state !== null && state !== void 0 && state.isEditing) {
@@ -98,7 +186,7 @@ var handleMouseMove = exports.handleMouseMove = function handleMouseMove(view, e
98
186
  pendingByView.set(view, event);
99
187
  cancelScheduledProcessForView(view);
100
188
  var id = requestAnimationFrame(function () {
101
- processHoverSide(view);
189
+ processHoverSide(view, api);
102
190
  });
103
191
  rafIdByView.set(view, id);
104
192
  return false;
@@ -10,6 +10,7 @@ var _bindEventListener = require("bind-event-listener");
10
10
  var _safePlugin = require("@atlaskit/editor-common/safe-plugin");
11
11
  var _state = require("@atlaskit/editor-prosemirror/state");
12
12
  var _experiments = require("@atlaskit/tmp-editor-statsig/experiments");
13
+ var _constants = require("./constants");
13
14
  var _handleKeyDown = require("./handle-key-down");
14
15
  var _handleMouseMove = require("./handle-mouse-move");
15
16
  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; }
@@ -17,12 +18,39 @@ function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t =
17
18
  /** Elements that extend the editor hover area (block controls, right-edge button, etc.) */
18
19
  var BLOCK_CONTROLS_HOVER_AREA_SELECTOR = '[data-blocks-right-edge-button-container], [data-blocks-drag-handle-container], [data-testid="block-ctrl-drag-handle"], [data-testid="block-ctrl-drag-handle-container"], [data-testid="block-ctrl-decorator-widget"], [data-testid="block-ctrl-quick-insert-button"]';
19
20
  var MOUSE_LEAVE_DEBOUNCE_MS = 200;
21
+
22
+ /** ClickAreaBlock overlay that wraps the editor content and covers the right margin. */
23
+ var CLICK_AREA_SELECTOR = '[data-editor-click-wrapper]';
20
24
  var isMovingToBlockControlsArea = function isMovingToBlockControlsArea(target) {
21
25
  return target instanceof Element && !!target.closest(BLOCK_CONTROLS_HOVER_AREA_SELECTOR);
22
26
  };
27
+
28
+ /**
29
+ * The right margin is covered by the ClickAreaBlock overlay, which sits outside .ak-editor-content-area.
30
+ * Hovering there should still surface the right-side Remix button, so keep controls alive — but only on
31
+ * the right (past the content's right edge), and not in the far-right Rovo gap. The left gutter must
32
+ * dismiss like the experiment-off path, so it is treated as inactive.
33
+ */
34
+ var isOverActiveClickArea = function isOverActiveClickArea(target, clientX) {
35
+ var _clickArea$querySelec, _target$ownerDocument, _target$ownerDocument2;
36
+ if (!(target instanceof Element)) {
37
+ return false;
38
+ }
39
+ var clickArea = target.closest(CLICK_AREA_SELECTOR);
40
+ if (!clickArea) {
41
+ return false;
42
+ }
43
+ var contentRight = (_clickArea$querySelec = clickArea.querySelector('.ak-editor-content-area')) === null || _clickArea$querySelec === void 0 ? void 0 : _clickArea$querySelec.getBoundingClientRect().right;
44
+ if (contentRight !== undefined && clientX <= contentRight) {
45
+ return false;
46
+ }
47
+ var innerWidth = (_target$ownerDocument = (_target$ownerDocument2 = target.ownerDocument.defaultView) === null || _target$ownerDocument2 === void 0 ? void 0 : _target$ownerDocument2.innerWidth) !== null && _target$ownerDocument !== void 0 ? _target$ownerDocument : Number.POSITIVE_INFINITY;
48
+ return clientX <= innerWidth - _constants.RIGHT_MARGIN_ROVO_GAP_PX;
49
+ };
23
50
  var interactionTrackingPluginKey = exports.interactionTrackingPluginKey = new _state.PluginKey('interactionTrackingPlugin');
24
51
  var createInteractionTrackingPlugin = exports.createInteractionTrackingPlugin = function createInteractionTrackingPlugin() {
25
52
  var rightSideControlsEnabled = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
53
+ var api = arguments.length > 1 ? arguments[1] : undefined;
26
54
  return new _safePlugin.SafePlugin({
27
55
  key: interactionTrackingPluginKey,
28
56
  state: {
@@ -66,7 +94,7 @@ var createInteractionTrackingPlugin = exports.createInteractionTrackingPlugin =
66
94
  handleKeyDown: _handleKeyDown.handleKeyDown,
67
95
  handleDOMEvents: {
68
96
  mousemove: function mousemove(view, event) {
69
- return (0, _handleMouseMove.handleMouseMove)(view, event, rightSideControlsEnabled);
97
+ return (0, _handleMouseMove.handleMouseMove)(view, event, rightSideControlsEnabled, api);
70
98
  }
71
99
  }
72
100
  },
@@ -82,22 +110,28 @@ var createInteractionTrackingPlugin = exports.createInteractionTrackingPlugin =
82
110
  x: 0,
83
111
  y: 0
84
112
  };
113
+
114
+ // The active right margin only counts as "still hovering" when our experiment is on;
115
+ // otherwise leaving the content area (e.g. exiting left) must dismiss as on master.
116
+ var marginHoverEnabled = (0, _experiments.editorExperiment)('remix_button_right_margin_hover', true);
85
117
  var scheduleMouseLeave = function scheduleMouseLeave(event) {
86
118
  if (mouseLeaveTimeoutId) {
87
119
  clearTimeout(mouseLeaveTimeoutId);
88
120
  mouseLeaveTimeoutId = null;
89
121
  }
90
122
 
91
- // Don't set isMouseOut when moving to block controls (right-edge button, drag handle, etc.)
92
- if (rightSideControlsEnabled && isMovingToBlockControlsArea(event.relatedTarget)) {
123
+ // Keep controls visible when moving to block controls (or, with the experiment on,
124
+ // the active right margin — the Rovo gap is excluded so controls still clear there).
125
+ if (rightSideControlsEnabled && (isMovingToBlockControlsArea(event.relatedTarget) || marginHoverEnabled && isOverActiveClickArea(event.relatedTarget, event.clientX))) {
93
126
  return;
94
127
  }
95
128
  mouseLeaveTimeoutId = setTimeout(function () {
96
129
  mouseLeaveTimeoutId = null;
97
- // Before dispatching, check if mouse has moved to block controls (e.g. through empty space)
130
+ // Re-check after the debounce: keep controls if the cursor landed on block controls
131
+ // (or, with the experiment on, the active right margin).
98
132
  if (rightSideControlsEnabled && typeof document !== 'undefined') {
99
133
  var el = document.elementFromPoint(lastMousePosition.x, lastMousePosition.y);
100
- if (el && isMovingToBlockControlsArea(el)) {
134
+ if (el && (isMovingToBlockControlsArea(el) || marginHoverEnabled && isOverActiveClickArea(el, lastMousePosition.x))) {
101
135
  return;
102
136
  }
103
137
  }
@@ -119,11 +153,11 @@ var createInteractionTrackingPlugin = exports.createInteractionTrackingPlugin =
119
153
  x: event.clientX,
120
154
  y: event.clientY
121
155
  };
122
- // Use document-level mousemove so we get events when hovering over block
123
- // controls (which may be in portals outside the editor DOM). Without this,
124
- // handleDOMEvents.mousemove only fires when over the editor content.
125
- if (editorContentArea.contains(event.target) || isMovingToBlockControlsArea(event.target)) {
126
- (0, _handleMouseMove.handleMouseMove)(view, event, rightSideControlsEnabled);
156
+ // Catches block controls in portals that handleDOMEvents.mousemove misses.
157
+ // The right-margin overlay is only relevant with the experiment on.
158
+ var overClickArea = marginHoverEnabled && event.target instanceof Element && !!event.target.closest(CLICK_AREA_SELECTOR);
159
+ if (editorContentArea.contains(event.target) || isMovingToBlockControlsArea(event.target) || overClickArea) {
160
+ (0, _handleMouseMove.handleMouseMove)(view, event, rightSideControlsEnabled, api);
127
161
  }
128
162
  },
129
163
  options: {
@@ -77,6 +77,8 @@ var VisibilityContainer = exports.VisibilityContainer = function VisibilityConta
77
77
  rightSideControlsEnabled = _useSharedPluginState.rightSideControlsEnabled;
78
78
  var isViewMode = editorViewMode === 'view';
79
79
  // rightSideControlsEnabled is the single source of truth (confluence_remix_button_right_side_block_fg from preset)
80
+ // Both controls are restricted by side: the drag handle shows on the left half, the Remix button on
81
+ // the right half (and the right margin), matching the midpoint split in handle-mouse-move.
80
82
  var shouldRestrictBySide = rightSideControlsEnabled && controlSide !== undefined && !isViewMode;
81
83
  // Only restrict by side when hoverSide is known (after mousemove). When undefined, show both
82
84
  // controls so drag handle is visible on load and for keyboard-only users.
@@ -79,7 +79,7 @@ export const blockControlsPlugin = ({
79
79
  if (editorExperiment('platform_editor_controls', 'variant1')) {
80
80
  pmPlugins.push({
81
81
  name: 'blockControlsInteractionTrackingPlugin',
82
- plugin: () => createInteractionTrackingPlugin(rightSideControlsEnabled)
82
+ plugin: () => createInteractionTrackingPlugin(rightSideControlsEnabled, api)
83
83
  });
84
84
  }
85
85
  if (editorExperiment('platform_editor_block_menu', true)) {
@@ -0,0 +1,2 @@
1
+ /** Far-right margin width reserved for the Rovo button, where the Remix button must not show. */
2
+ export const RIGHT_MARGIN_ROVO_GAP_PX = 80;
@@ -1,4 +1,7 @@
1
+ import { editorExperiment } from '@atlaskit/tmp-editor-statsig/experiments';
2
+ import { handleMouseOver } from '../handle-mouse-over';
1
3
  import { clearHoverSide, mouseEnter, mouseLeave, setHoverSide, stopEditing } from './commands';
4
+ import { RIGHT_MARGIN_ROVO_GAP_PX } from './constants';
2
5
  import { getInteractionTrackingState } from './pm-plugin';
3
6
 
4
7
  /** Per-view pending hover state; avoids cross-editor singleton. */
@@ -20,11 +23,56 @@ const clearPendingHoverSide = view => {
20
23
  const BLOCK_SELECTORS = '[data-node-anchor], [data-drag-handler-anchor-name]';
21
24
  const RIGHT_EDGE_SELECTOR = '[data-blocks-right-edge-button-container]';
22
25
 
26
+ // Top-level blocks (no block ancestor), matched by anchor attribute so it works under both the
27
+ // legacy and native-anchor schemes.
28
+ const getRootBlocks = view => Array.from(view.dom.querySelectorAll(BLOCK_SELECTORS)).filter(el => {
29
+ var _el$parentElement;
30
+ return !((_el$parentElement = el.parentElement) !== null && _el$parentElement !== void 0 && _el$parentElement.closest(BLOCK_SELECTORS));
31
+ });
32
+
33
+ // Find the root block whose vertical bounds contain clientY. Returns the measured rect so callers
34
+ // can reuse it without re-measuring.
35
+ const findBlockAtY = (view, clientY) => {
36
+ for (const el of getRootBlocks(view)) {
37
+ const rect = el.getBoundingClientRect();
38
+ if (clientY >= rect.top && clientY <= rect.bottom) {
39
+ return {
40
+ block: el,
41
+ rect
42
+ };
43
+ }
44
+ }
45
+ return null;
46
+ };
47
+ const getRightMarginBoundary = view => {
48
+ var _view$dom$ownerDocume, _view$dom$ownerDocume2;
49
+ return ((_view$dom$ownerDocume = (_view$dom$ownerDocume2 = view.dom.ownerDocument.defaultView) === null || _view$dom$ownerDocume2 === void 0 ? void 0 : _view$dom$ownerDocume2.innerWidth) !== null && _view$dom$ownerDocume !== void 0 ? _view$dom$ownerDocume : Number.POSITIVE_INFINITY) - RIGHT_MARGIN_ROVO_GAP_PX;
50
+ };
51
+ // not in the right margin
52
+
53
+ // Classify where the cursor sits in the right margin beside the block at its height, running the
54
+ // block lookup once so the caller doesn't traverse the DOM twice per mousemove.
55
+ const classifyRightMarginPosition = (view, event) => {
56
+ const found = findBlockAtY(view, event.clientY);
57
+ if (!found) {
58
+ return null;
59
+ }
60
+ if (event.clientX <= found.rect.right) {
61
+ return null;
62
+ }
63
+ return event.clientX > getRightMarginBoundary(view) ? {
64
+ type: 'gap'
65
+ } : {
66
+ type: 'active',
67
+ block: found.block
68
+ };
69
+ };
70
+
23
71
  /**
24
72
  * Process hover position and set left/right side. Only invoked when right-side controls are
25
73
  * enabled (confluence_remix_button_right_side_block_fg); handleMouseMove returns early otherwise.
26
74
  */
27
- const processHoverSide = view => {
75
+ const processHoverSide = (view, api) => {
28
76
  const event = pendingByView.get(view);
29
77
  if (!event) {
30
78
  return;
@@ -55,28 +103,53 @@ const processHoverSide = view => {
55
103
  return;
56
104
  }
57
105
 
58
- // Primary path: depth-1 block (doc direct child). Decorations-anchor sets [data-drag-handler-anchor-depth="1"]
59
- // on every root block (table, layoutSection, expand, etc.), so we get the whole block without per-type logic.
60
- const blockElement = target === null || target === void 0 ? void 0 : target.closest(BLOCK_SELECTORS);
61
- const depth1Block = blockElement instanceof HTMLElement ? blockElement.closest('[data-drag-handler-anchor-depth="1"]') : null;
62
- const boundsElement = depth1Block instanceof HTMLElement ? depth1Block : editorContentArea;
63
- if (!boundsElement) {
64
- if ((state === null || state === void 0 ? void 0 : state.hoverSide) !== undefined) {
65
- clearHoverSide(view);
106
+ // Added right-margin hover, gated so it can be rolled back. When off, fall through to midpoint.
107
+ if (editorExperiment('remix_button_right_margin_hover', true)) {
108
+ const closestBlock = target === null || target === void 0 ? void 0 : target.closest(BLOCK_SELECTORS);
109
+ const blockElement = closestBlock instanceof HTMLElement ? closestBlock : null;
110
+
111
+ // Not over a block: the cursor may be in the right margin beside content.
112
+ const marginZone = blockElement ? null : classifyRightMarginPosition(view, event);
113
+ if ((marginZone === null || marginZone === void 0 ? void 0 : marginZone.type) === 'active' && api) {
114
+ // handleMouseOver only reads event.target, so a target-only stand-in is enough here.
115
+ handleMouseOver(view, {
116
+ target: marginZone.block
117
+ }, api);
118
+ // mouseenter doesn't fire over the click overlay, so clear isMouseOut here to re-show.
119
+ if (state !== null && state !== void 0 && state.isMouseOut) {
120
+ mouseEnter(view);
121
+ }
122
+ if ((state === null || state === void 0 ? void 0 : state.hoverSide) !== 'right') {
123
+ setHoverSide(view, 'right');
124
+ }
125
+ return;
66
126
  }
67
- return;
127
+
128
+ // In the Rovo gap, dismiss the controls so the button doesn't linger over the Rovo button.
129
+ if ((marginZone === null || marginZone === void 0 ? void 0 : marginZone.type) === 'gap' || event.clientX > getRightMarginBoundary(view)) {
130
+ if (!(state !== null && state !== void 0 && state.isMouseOut)) {
131
+ clearHoverSide(view);
132
+ mouseLeave(view);
133
+ }
134
+ return;
135
+ }
136
+
137
+ // Over a block: fall through to the midpoint split so the left half keeps the drag handle and
138
+ // the right half shows the Remix button, matching the experiment-off behaviour.
68
139
  }
140
+
141
+ // Pick the side from the content midpoint, keeping the original left/right halves.
69
142
  const {
70
143
  left,
71
144
  right
72
- } = boundsElement.getBoundingClientRect();
145
+ } = editorContentArea.getBoundingClientRect();
73
146
  const midpoint = (left + right) / 2;
74
147
  const nextHoverSide = event.clientX > midpoint ? 'right' : 'left';
75
148
  if ((state === null || state === void 0 ? void 0 : state.hoverSide) !== nextHoverSide) {
76
149
  setHoverSide(view, nextHoverSide);
77
150
  }
78
151
  };
79
- export const handleMouseMove = (view, event, rightSideControlsEnabled = false) => {
152
+ export const handleMouseMove = (view, event, rightSideControlsEnabled = false, api) => {
80
153
  const state = getInteractionTrackingState(view.state);
81
154
  // if user has stopped editing and moved their mouse, show block controls again
82
155
  if (state !== null && state !== void 0 && state.isEditing) {
@@ -93,7 +166,7 @@ export const handleMouseMove = (view, event, rightSideControlsEnabled = false) =
93
166
  pendingByView.set(view, event);
94
167
  cancelScheduledProcessForView(view);
95
168
  const id = requestAnimationFrame(() => {
96
- processHoverSide(view);
169
+ processHoverSide(view, api);
97
170
  });
98
171
  rafIdByView.set(view, id);
99
172
  return false;