@atlaskit/editor-plugin-block-controls 8.0.15 → 8.1.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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,18 @@
1
1
  # @atlaskit/editor-plugin-block-controls
2
2
 
3
+ ## 8.1.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [`1d31a4729ab09`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/1d31a4729ab09) -
8
+ [ux] Implement nested block menu icon (flagged)
9
+
10
+ ### Patch Changes
11
+
12
+ - [`e00b363b9fa30`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/e00b363b9fa30) -
13
+ [ux] EDITOR-4481 Clean up platform_editor_toolbar_aifc_user_intent_fix
14
+ - Updated dependencies
15
+
3
16
  ## 8.0.15
4
17
 
5
18
  ### Patch Changes
@@ -140,7 +140,7 @@ var blockControlsPlugin = exports.blockControlsPlugin = function blockControlsPl
140
140
  }));
141
141
  if ((menuTriggerBy === undefined || !!menuTriggerBy && menuTriggerBy === (options === null || options === void 0 ? void 0 : options.anchorName)) && currentUserIntent === 'blockMenuOpen') {
142
142
  var state = api === null || api === void 0 ? void 0 : api.blockControls.sharedState.currentState();
143
- if (state !== null && state !== void 0 && state.isSelectedViaDragHandle && (0, _platformFeatureFlags.fg)('platform_editor_toolbar_aifc_user_intent_fix')) {
143
+ if (state !== null && state !== void 0 && state.isSelectedViaDragHandle) {
144
144
  var _api$userIntent4;
145
145
  api === null || api === void 0 || (_api$userIntent4 = api.userIntent) === null || _api$userIntent4 === void 0 || _api$userIntent4.commands.setCurrentUserIntent('dragHandleSelected')({
146
146
  tr: tr
@@ -92,7 +92,7 @@ var dragHandleDecoration = exports.dragHandleDecoration = function dragHandleDec
92
92
  var getPos = function getPos() {
93
93
  try {
94
94
  return getPosUnsafe();
95
- } catch (e) {
95
+ } catch (_unused) {
96
96
  // Ignore errors from getPosUnsafe
97
97
  return undefined;
98
98
  }
@@ -5,7 +5,6 @@ Object.defineProperty(exports, "__esModule", {
5
5
  });
6
6
  exports.handleMouseDown = void 0;
7
7
  var _styles = require("@atlaskit/editor-common/styles");
8
- var _platformFeatureFlags = require("@atlaskit/platform-feature-flags");
9
8
  var _expValEquals = require("@atlaskit/tmp-editor-statsig/exp-val-equals");
10
9
  var _expValEqualsNoExposure = require("@atlaskit/tmp-editor-statsig/exp-val-equals-no-exposure");
11
10
  var handleMouseDown = exports.handleMouseDown = function handleMouseDown(api) {
@@ -45,21 +44,19 @@ var handleMouseDown = exports.handleMouseDown = function handleMouseDown(api) {
45
44
  * When block menu is enabled, reset intent back to 'default' as editor-plugin-block-menu sets the user intent to 'blockMenuOpen', and setting here
46
45
  * causes flickering as this runs before editor-plugin-block-menu.
47
46
  */
48
- if ((0, _platformFeatureFlags.fg)('platform_editor_toolbar_aifc_user_intent_fix')) {
49
- if ((0, _expValEqualsNoExposure.expValEqualsNoExposure)('platform_editor_block_menu', 'isEnabled', true)) {
50
- // if target is drag handle, block menu will be opened
51
- if (!isDragHandle) {
52
- var _api$userIntent;
53
- api === null || api === void 0 || (_api$userIntent = api.userIntent) === null || _api$userIntent === void 0 || _api$userIntent.commands.setCurrentUserIntent('default')({
54
- tr: tr
55
- });
56
- }
57
- } else {
58
- var _api$userIntent2;
59
- (_api$userIntent2 = api.userIntent) === null || _api$userIntent2 === void 0 || _api$userIntent2.commands.setCurrentUserIntent(isDragHandle ? 'dragHandleSelected' : 'default')({
47
+ if ((0, _expValEqualsNoExposure.expValEqualsNoExposure)('platform_editor_block_menu', 'isEnabled', true)) {
48
+ // if target is drag handle, block menu will be opened
49
+ if (!isDragHandle) {
50
+ var _api$userIntent;
51
+ api === null || api === void 0 || (_api$userIntent = api.userIntent) === null || _api$userIntent === void 0 || _api$userIntent.commands.setCurrentUserIntent('default')({
60
52
  tr: tr
61
53
  });
62
54
  }
55
+ } else {
56
+ var _api$userIntent2;
57
+ (_api$userIntent2 = api.userIntent) === null || _api$userIntent2 === void 0 || _api$userIntent2.commands.setCurrentUserIntent(isDragHandle ? 'dragHandleSelected' : 'default')({
58
+ tr: tr
59
+ });
63
60
  }
64
61
  return tr;
65
62
  });
@@ -0,0 +1,64 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.DragHandleNestedIcon = void 0;
7
+ var _react = require("@emotion/react");
8
+ /** @jsxRuntime classic */
9
+ /**
10
+ * @jsxRuntime classic
11
+ * @jsx jsx
12
+ */
13
+ // eslint-disable-next-line @atlaskit/ui-styling-standard/use-compiled -- Ignored via go/DSP-18766
14
+
15
+ var spanStyles = (0, _react.css)({
16
+ display: 'inline-block',
17
+ boxSizing: 'border-box',
18
+ flexShrink: 0
19
+ });
20
+ var svgSizeStyles = (0, _react.css)({
21
+ width: '24px',
22
+ height: '24px'
23
+ });
24
+ var svgStyles = (0, _react.css)({
25
+ color: 'currentColor',
26
+ overflow: 'hidden',
27
+ pointerEvents: 'none',
28
+ verticalAlign: 'bottom'
29
+ });
30
+
31
+ /**
32
+ * Custom 3-dot vertical drag handle icon for nested nodes.
33
+ * Similar to DragHandleVerticalIcon but with only 3 dots instead of 6.
34
+ * Hardcoded to medium size with spacious spacing.
35
+ */
36
+ var DragHandleNestedIcon = exports.DragHandleNestedIcon = function DragHandleNestedIcon() {
37
+ return (0, _react.jsx)("span", {
38
+ "aria-hidden": true,
39
+ css: spanStyles
40
+ }, (0, _react.jsx)("svg", {
41
+ width: 24,
42
+ height: 24,
43
+ viewBox: "-4 -4 24 24",
44
+ fill: "none",
45
+ xmlns: "http://www.w3.org/2000/svg",
46
+ role: "presentation",
47
+ css: [svgStyles, svgSizeStyles]
48
+ }, (0, _react.jsx)("circle", {
49
+ cx: "8",
50
+ cy: "4",
51
+ r: "1.5",
52
+ fill: "currentColor"
53
+ }), (0, _react.jsx)("circle", {
54
+ cx: "8",
55
+ cy: "8",
56
+ r: "1.5",
57
+ fill: "currentColor"
58
+ }), (0, _react.jsx)("circle", {
59
+ cx: "8",
60
+ cy: "12",
61
+ r: "1.5",
62
+ fill: "currentColor"
63
+ })));
64
+ };
@@ -41,6 +41,7 @@ var _dragHandlePositions = require("../pm-plugins/utils/drag-handle-positions");
41
41
  var _getSelection = require("../pm-plugins/utils/getSelection");
42
42
  var _selection2 = require("../pm-plugins/utils/selection");
43
43
  var _consts2 = require("./consts");
44
+ var _dragHandleNestedIcon = require("./drag-handle-nested-icon");
44
45
  var _dragPreview = require("./drag-preview");
45
46
  var _anchorName = require("./utils/anchor-name");
46
47
  var _domAttrName = require("./utils/dom-attr-name");
@@ -447,6 +448,24 @@ var DragHandle = exports.DragHandle = function DragHandle(_ref3) {
447
448
  var start = getPos();
448
449
  var isLayoutColumn = nodeType === 'layoutColumn';
449
450
  var isMultiSelect = (0, _experiments.editorExperiment)('platform_editor_element_drag_and_drop_multiselect', true);
451
+
452
+ // Dynamically calculate if node is top-level based on current position (gated by experiment)
453
+ var isTopLevelNodeDynamic = (0, _react.useMemo)(function () {
454
+ if (!(0, _expValEquals.expValEquals)('platform_editor_nested_drag_handle_icon', 'isEnabled', true)) {
455
+ return isTopLevelNode;
456
+ }
457
+ var pos = getPos();
458
+ if (typeof pos === 'number') {
459
+ var $pos = view.state.doc.resolve(pos);
460
+ return ($pos === null || $pos === void 0 ? void 0 : $pos.parent.type.name) === 'doc';
461
+ }
462
+ return true;
463
+ }, [getPos, view.state.doc, isTopLevelNode]);
464
+
465
+ // Use the dynamic value when experiment is on, otherwise use the prop
466
+ // When cleaning up the experiment, you can safely remove the isTopLevelNode as an prop and
467
+ // just rely on the dynamic value (rename it to isTopLevelNode for simplicitiy)
468
+ var isTopLevelNodeValue = (0, _expValEquals.expValEquals)('platform_editor_nested_drag_handle_icon', 'isEnabled', true) ? isTopLevelNodeDynamic : isTopLevelNode;
450
469
  (0, _react.useEffect)(function () {
451
470
  if ((0, _experiments.editorExperiment)('platform_editor_block_control_optimise_render', true)) {
452
471
  return;
@@ -537,7 +556,7 @@ var DragHandle = exports.DragHandle = function DragHandle(_ref3) {
537
556
  var $anchor = (mSelect === null || mSelect === void 0 ? void 0 : mSelect.anchor) !== undefined ? tr.doc.resolve(mSelect === null || mSelect === void 0 ? void 0 : mSelect.anchor) : tr.selection.$anchor;
538
557
  if (!isMultiSelect || tr.selection.empty || !e.shiftKey) {
539
558
  tr = (0, _getSelection.selectNode)(tr, startPos, nodeType, api);
540
- } else if (isTopLevelNode && $anchor.depth <= _consts2.DRAG_HANDLE_MAX_SHIFT_CLICK_DEPTH && e.shiftKey && (0, _platformFeatureFlags.fg)('platform_editor_elements_dnd_shift_click_select')) {
559
+ } else if (isTopLevelNodeValue && $anchor.depth <= _consts2.DRAG_HANDLE_MAX_SHIFT_CLICK_DEPTH && e.shiftKey && (0, _platformFeatureFlags.fg)('platform_editor_elements_dnd_shift_click_select')) {
541
560
  var _api$blockControls3;
542
561
  var alignAnchorHeadToSel = (0, _selection2.alignAnchorHeadInDirectionOfPos)(tr.selection, startPos);
543
562
  var selectionWithExpandedHead = (0, _selection2.expandSelectionHeadToNodeAtPos)(alignAnchorHeadToSel, startPos);
@@ -562,7 +581,7 @@ var DragHandle = exports.DragHandle = function DragHandle(_ref3) {
562
581
  return tr;
563
582
  });
564
583
  view.focus();
565
- }, [isMultiSelect, api, view, dragHandleSelected, getPos, isTopLevelNode, nodeType]);
584
+ }, [isMultiSelect, api, view, dragHandleSelected, getPos, isTopLevelNodeValue, nodeType]);
566
585
  var handleKeyDown = (0, _react.useCallback)(function (e) {
567
586
  // allow user to use spacebar to select the node
568
587
  if (!e.repeat && e.key === ' ') {
@@ -862,18 +881,18 @@ var DragHandle = exports.DragHandle = function DragHandle(_ref3) {
862
881
  var isEdgeCase = (hasResizer || isExtension || isEmbedCard || isBlockCard) && innerContainer;
863
882
  var isSticky = (0, _dragHandlePositions.shouldBeSticky)(nodeType);
864
883
  if (supportsAnchor) {
865
- var bottom = (0, _experiments.editorExperiment)('platform_editor_controls', 'variant1') ? (0, _dragHandlePositions.getControlBottomCSSValue)(safeAnchorName, isSticky, isTopLevelNode, isLayoutColumn) : {};
884
+ var bottom = (0, _experiments.editorExperiment)('platform_editor_controls', 'variant1') ? (0, _dragHandlePositions.getControlBottomCSSValue)(safeAnchorName, isSticky, isTopLevelNodeValue, isLayoutColumn) : {};
866
885
  return _objectSpread({
867
886
  left: isEdgeCase ? "calc(anchor(".concat(safeAnchorName, " start) + ").concat((0, _dragHandlePositions.getLeftPosition)(dom, nodeType, innerContainer, isMacroInteractionUpdates, parentNodeType), ")") : (0, _experiments.editorExperiment)('advanced_layouts', true) && isLayoutColumn ? "calc((anchor(".concat(safeAnchorName, " right) + anchor(").concat(safeAnchorName, " left))/2 - ").concat(_consts2.DRAG_HANDLE_HEIGHT / 2, "px)") : "calc(anchor(".concat(safeAnchorName, " start) - ").concat(_styles.DRAG_HANDLE_WIDTH, "px - ").concat((0, _consts2.dragHandleGap)(nodeType, parentNodeType), "px)"),
868
887
  top: (0, _experiments.editorExperiment)('advanced_layouts', true) && isLayoutColumn ? "calc(anchor(".concat(safeAnchorName, " top) - ").concat(_styles.DRAG_HANDLE_WIDTH, "px)") : "calc(anchor(".concat(safeAnchorName, " start)+ ").concat((0, _consts2.topPositionAdjustment)((0, _expValEquals.expValEquals)('platform_editor_native_anchor_with_dnd', 'isEnabled', true) ? $pos && $pos.nodeAfter && (0, _decorationsCommon.getNodeTypeWithLevel)($pos.nodeAfter) || nodeType : nodeType), "px)")
869
888
  }, bottom);
870
889
  }
871
- var height = (0, _experiments.editorExperiment)('platform_editor_controls', 'variant1') ? (0, _dragHandlePositions.getControlHeightCSSValue)((0, _dragHandlePositions.getNodeHeight)(dom, safeAnchorName, anchorRectCache) || 0, isSticky, isTopLevelNode, "".concat(_consts2.DRAG_HANDLE_HEIGHT), isLayoutColumn) : {};
890
+ var height = (0, _experiments.editorExperiment)('platform_editor_controls', 'variant1') ? (0, _dragHandlePositions.getControlHeightCSSValue)((0, _dragHandlePositions.getNodeHeight)(dom, safeAnchorName, anchorRectCache) || 0, isSticky, isTopLevelNodeValue, "".concat(_consts2.DRAG_HANDLE_HEIGHT), isLayoutColumn) : {};
872
891
  return _objectSpread({
873
892
  left: isEdgeCase ? "calc(".concat((dom === null || dom === void 0 ? void 0 : dom.offsetLeft) || 0, "px + ").concat((0, _dragHandlePositions.getLeftPosition)(dom, nodeType, innerContainer, isMacroInteractionUpdates, parentNodeType), ")") : (0, _dragHandlePositions.getLeftPosition)(dom, nodeType, innerContainer, isMacroInteractionUpdates, parentNodeType),
874
893
  top: (0, _dragHandlePositions.getTopPosition)(dom, nodeType)
875
894
  }, height);
876
- }, [anchorName, getPos, view, nodeType, macroInteractionUpdates, anchorRectCache, isTopLevelNode, isLayoutColumn, recalculatePosition]);
895
+ }, [anchorName, getPos, view, nodeType, macroInteractionUpdates, anchorRectCache, isTopLevelNodeValue, isLayoutColumn, recalculatePosition]);
877
896
  var calculatePositionOld = (0, _react.useCallback)(function () {
878
897
  var pos = getPos();
879
898
  var $pos = (0, _expValEquals.expValEquals)('platform_editor_native_anchor_with_dnd', 'isEnabled', true) ? typeof pos === 'number' && view.state.doc.resolve(pos) : pos && view.state.doc.resolve(pos);
@@ -908,18 +927,18 @@ var DragHandle = exports.DragHandle = function DragHandle(_ref3) {
908
927
  var isEdgeCase = (hasResizer || isExtension || isEmbedCard || isBlockCard) && innerContainer;
909
928
  var isSticky = (0, _dragHandlePositions.shouldBeSticky)(nodeType);
910
929
  if (supportsAnchor) {
911
- var bottom = (0, _experiments.editorExperiment)('platform_editor_controls', 'variant1') ? (0, _dragHandlePositions.getControlBottomCSSValue)(safeAnchorName, isSticky, isTopLevelNode, isLayoutColumn) : {};
930
+ var bottom = (0, _experiments.editorExperiment)('platform_editor_controls', 'variant1') ? (0, _dragHandlePositions.getControlBottomCSSValue)(safeAnchorName, isSticky, isTopLevelNodeValue, isLayoutColumn) : {};
912
931
  return _objectSpread({
913
932
  left: isEdgeCase ? "calc(anchor(".concat(safeAnchorName, " start) + ").concat((0, _dragHandlePositions.getLeftPosition)(dom, nodeType, innerContainer, isMacroInteractionUpdates, parentNodeType), ")") : (0, _experiments.editorExperiment)('advanced_layouts', true) && isLayoutColumn ? "calc((anchor(".concat(safeAnchorName, " right) + anchor(").concat(safeAnchorName, " left))/2 - ").concat(_consts2.DRAG_HANDLE_HEIGHT / 2, "px)") : "calc(anchor(".concat(safeAnchorName, " start) - ").concat(_styles.DRAG_HANDLE_WIDTH, "px - ").concat((0, _consts2.dragHandleGap)(nodeType, parentNodeType), "px)"),
914
933
  top: (0, _experiments.editorExperiment)('advanced_layouts', true) && isLayoutColumn ? "calc(anchor(".concat(safeAnchorName, " top) - ").concat(_styles.DRAG_HANDLE_WIDTH, "px)") : "calc(anchor(".concat(safeAnchorName, " start) + ").concat((0, _consts2.topPositionAdjustment)((0, _expValEquals.expValEquals)('platform_editor_native_anchor_with_dnd', 'isEnabled', true) ? $pos && $pos.nodeAfter && (0, _decorationsCommon.getNodeTypeWithLevel)($pos.nodeAfter) || nodeType : nodeType), "px)")
915
934
  }, bottom);
916
935
  }
917
- var height = (0, _experiments.editorExperiment)('platform_editor_controls', 'variant1') ? (0, _dragHandlePositions.getControlHeightCSSValue)((0, _dragHandlePositions.getNodeHeight)(dom, safeAnchorName, anchorRectCache) || 0, isSticky, isTopLevelNode, "".concat(_consts2.DRAG_HANDLE_HEIGHT), isLayoutColumn) : {};
936
+ var height = (0, _experiments.editorExperiment)('platform_editor_controls', 'variant1') ? (0, _dragHandlePositions.getControlHeightCSSValue)((0, _dragHandlePositions.getNodeHeight)(dom, safeAnchorName, anchorRectCache) || 0, isSticky, isTopLevelNodeValue, "".concat(_consts2.DRAG_HANDLE_HEIGHT), isLayoutColumn) : {};
918
937
  return _objectSpread({
919
938
  left: isEdgeCase ? "calc(".concat((dom === null || dom === void 0 ? void 0 : dom.offsetLeft) || 0, "px + ").concat((0, _dragHandlePositions.getLeftPosition)(dom, nodeType, innerContainer, isMacroInteractionUpdates, parentNodeType), ")") : (0, _dragHandlePositions.getLeftPosition)(dom, nodeType, innerContainer, isMacroInteractionUpdates, parentNodeType),
920
939
  top: (0, _dragHandlePositions.getTopPosition)(dom, nodeType)
921
940
  }, height);
922
- }, [anchorName, getPos, view, nodeType, blockCardWidth, macroInteractionUpdates, anchorRectCache, isTopLevelNode, isLayoutColumn]);
941
+ }, [anchorName, getPos, view, nodeType, blockCardWidth, macroInteractionUpdates, anchorRectCache, isTopLevelNodeValue, isLayoutColumn]);
923
942
  (0, _react.useEffect)(function () {
924
943
  if ((0, _experiments.editorExperiment)('platform_editor_block_control_optimise_render', true)) {
925
944
  return;
@@ -995,12 +1014,12 @@ var DragHandle = exports.DragHandle = function DragHandle(_ref3) {
995
1014
  }
996
1015
  var mSelect = api === null || api === void 0 || (_api$blockControls$sh4 = api.blockControls.sharedState.currentState()) === null || _api$blockControls$sh4 === void 0 ? void 0 : _api$blockControls$sh4.multiSelectDnD;
997
1016
  var $anchor = (mSelect === null || mSelect === void 0 ? void 0 : mSelect.anchor) !== undefined ? view.state.doc.resolve(mSelect === null || mSelect === void 0 ? void 0 : mSelect.anchor) : view.state.selection.$anchor;
998
- if (isShiftDown && (!isTopLevelNode || isTopLevelNode && $anchor.depth > _consts2.DRAG_HANDLE_MAX_SHIFT_CLICK_DEPTH)) {
1017
+ if (isShiftDown && (!isTopLevelNodeValue || isTopLevelNodeValue && $anchor.depth > _consts2.DRAG_HANDLE_MAX_SHIFT_CLICK_DEPTH)) {
999
1018
  setDragHandleDisabled(true);
1000
1019
  } else {
1001
1020
  setDragHandleDisabled(false);
1002
1021
  }
1003
- }, [api === null || api === void 0 ? void 0 : api.blockControls.sharedState, isMultiSelect, isShiftDown, isTopLevelNode, view]);
1022
+ }, [api === null || api === void 0 ? void 0 : api.blockControls.sharedState, isMultiSelect, isShiftDown, isTopLevelNodeValue, view]);
1004
1023
  var dragHandleMessage = (0, _expValEqualsNoExposure.expValEqualsNoExposure)('platform_editor_block_menu', 'isEnabled', true) ? formatMessage(_messages.blockControlsMessages.dragToMoveClickToOpen, {
1005
1024
  br: (0, _react2.jsx)("br", null)
1006
1025
  }) : formatMessage(_messages.blockControlsMessages.dragToMove);
@@ -1009,7 +1028,7 @@ var DragHandle = exports.DragHandle = function DragHandle(_ref3) {
1009
1028
  var dragHandleAriaLabel = (0, _expValEqualsNoExposure.expValEqualsNoExposure)('platform_editor_block_menu', 'isEnabled', true) ? formatMessage(_messages.blockControlsMessages.dragToMoveClickToOpen, {
1010
1029
  br: ' '
1011
1030
  }) : formatMessage(_messages.blockControlsMessages.dragToMove);
1012
- var helpDescriptors = isTopLevelNode ? [{
1031
+ var helpDescriptors = isTopLevelNodeValue ? [{
1013
1032
  description: dragHandleMessage
1014
1033
  }, {
1015
1034
  description: formatMessage(_messages.blockControlsMessages.moveUp),
@@ -1033,7 +1052,7 @@ var DragHandle = exports.DragHandle = function DragHandle(_ref3) {
1033
1052
  keymap: _keymaps.dragToMoveDown
1034
1053
  }];
1035
1054
  var isParentNodeOfTypeLayout;
1036
- if (!isTopLevelNode) {
1055
+ if (!isTopLevelNodeValue) {
1037
1056
  var pos = getPos();
1038
1057
  if (typeof pos === 'number') {
1039
1058
  var _$pos$parent;
@@ -1113,7 +1132,7 @@ var DragHandle = exports.DragHandle = function DragHandle(_ref3) {
1113
1132
  // eslint-disable-next-line @atlaskit/design-system/no-direct-use-of-web-platform-drag-and-drop
1114
1133
  ,
1115
1134
  onDragStart: handleIconDragStart
1116
- }, (0, _react2.jsx)(_dragHandleVertical.default, {
1135
+ }, (0, _expValEquals.expValEquals)('platform_editor_nested_drag_handle_icon', 'isEnabled', true) && !isTopLevelNodeValue ? (0, _react2.jsx)(_dragHandleNestedIcon.DragHandleNestedIcon, null) : (0, _react2.jsx)(_dragHandleVertical.default, {
1117
1136
  spacing: "spacious",
1118
1137
  label: "",
1119
1138
  size: "small"
@@ -1129,7 +1148,7 @@ var DragHandle = exports.DragHandle = function DragHandle(_ref3) {
1129
1148
  as: "span",
1130
1149
  testId: "block-ctrl-drag-handle-container"
1131
1150
  }, (0, _react2.jsx)("span", {
1132
- css: [tooltipContainerStyles, (0, _dragHandlePositions.shouldMaskNodeControls)(nodeType, isTopLevelNode) && ((0, _expValEquals.expValEquals)('platform_editor_table_sticky_header_improvements', 'cohort', 'test_with_overflow') && (0, _platformFeatureFlags.fg)('platform_editor_table_sticky_header_patch_6') ? tooltipContainerStylesImprovedStickyHeaderWithMask : tooltipContainerStylesStickyHeaderWithMask), !(0, _dragHandlePositions.shouldMaskNodeControls)(nodeType, isTopLevelNode) && tooltipContainerStylesStickyHeaderWithoutMask]
1151
+ css: [tooltipContainerStyles, (0, _dragHandlePositions.shouldMaskNodeControls)(nodeType, isTopLevelNodeValue) && ((0, _expValEquals.expValEquals)('platform_editor_table_sticky_header_improvements', 'cohort', 'test_with_overflow') && (0, _platformFeatureFlags.fg)('platform_editor_table_sticky_header_patch_6') ? tooltipContainerStylesImprovedStickyHeaderWithMask : tooltipContainerStylesStickyHeaderWithMask), !(0, _dragHandlePositions.shouldMaskNodeControls)(nodeType, isTopLevelNodeValue) && tooltipContainerStylesStickyHeaderWithoutMask]
1133
1152
  }, (0, _react2.jsx)(_tooltip.default, {
1134
1153
  content: (0, _react2.jsx)(_keymaps.TooltipContentWithMultipleShortcuts, {
1135
1154
  helpDescriptors: helpDescriptors
@@ -1143,7 +1162,7 @@ var DragHandle = exports.DragHandle = function DragHandle(_ref3) {
1143
1162
  });
1144
1163
  }
1145
1164
  }, (0, _react2.jsx)("span", {
1146
- css: [(0, _dragHandlePositions.shouldMaskNodeControls)(nodeType, isTopLevelNode) && buttonWrapperStyles, buttonWrapperStylesPatch]
1165
+ css: [(0, _dragHandlePositions.shouldMaskNodeControls)(nodeType, isTopLevelNodeValue) && buttonWrapperStyles, buttonWrapperStylesPatch]
1147
1166
  }, renderButton()))));
1148
1167
  };
1149
1168
  var stickyWithoutTooltip = function stickyWithoutTooltip() {
@@ -1155,9 +1174,9 @@ var DragHandle = exports.DragHandle = function DragHandle(_ref3) {
1155
1174
  as: "span",
1156
1175
  testId: "block-ctrl-drag-handle-container"
1157
1176
  }, (0, _react2.jsx)("span", {
1158
- css: [tooltipContainerStyles, (0, _dragHandlePositions.shouldMaskNodeControls)(nodeType, isTopLevelNode) && tooltipContainerStylesStickyHeaderWithMask, !(0, _dragHandlePositions.shouldMaskNodeControls)(nodeType, isTopLevelNode) && tooltipContainerStylesStickyHeaderWithoutMask]
1177
+ css: [tooltipContainerStyles, (0, _dragHandlePositions.shouldMaskNodeControls)(nodeType, isTopLevelNodeValue) && tooltipContainerStylesStickyHeaderWithMask, !(0, _dragHandlePositions.shouldMaskNodeControls)(nodeType, isTopLevelNodeValue) && tooltipContainerStylesStickyHeaderWithoutMask]
1159
1178
  }, (0, _react2.jsx)("span", {
1160
- css: [(0, _dragHandlePositions.shouldMaskNodeControls)(nodeType, isTopLevelNode) && buttonWrapperStyles, buttonWrapperStylesPatch]
1179
+ css: [(0, _dragHandlePositions.shouldMaskNodeControls)(nodeType, isTopLevelNodeValue) && buttonWrapperStyles, buttonWrapperStylesPatch]
1161
1180
  }, renderButton())));
1162
1181
  };
1163
1182
  var buttonWithTooltip = function buttonWithTooltip() {
@@ -1187,6 +1206,7 @@ var DragHandleWithVisibility = exports.DragHandleWithVisibility = function DragH
1187
1206
  anchorName = _ref10.anchorName,
1188
1207
  nodeType = _ref10.nodeType,
1189
1208
  handleOptions = _ref10.handleOptions,
1209
+ isTopLevelNode = _ref10.isTopLevelNode,
1190
1210
  anchorRectCache = _ref10.anchorRectCache;
1191
1211
  return (0, _react2.jsx)(_visibilityContainer.VisibilityContainer, {
1192
1212
  api: api
@@ -1198,6 +1218,7 @@ var DragHandleWithVisibility = exports.DragHandleWithVisibility = function DragH
1198
1218
  anchorName: anchorName,
1199
1219
  nodeType: nodeType,
1200
1220
  handleOptions: handleOptions,
1221
+ isTopLevelNode: isTopLevelNode,
1201
1222
  anchorRectCache: anchorRectCache
1202
1223
  }));
1203
1224
  };
@@ -134,7 +134,7 @@ export const blockControlsPlugin = ({
134
134
  });
135
135
  if ((menuTriggerBy === undefined || !!menuTriggerBy && menuTriggerBy === (options === null || options === void 0 ? void 0 : options.anchorName)) && currentUserIntent === 'blockMenuOpen') {
136
136
  const state = api === null || api === void 0 ? void 0 : api.blockControls.sharedState.currentState();
137
- if (state !== null && state !== void 0 && state.isSelectedViaDragHandle && fg('platform_editor_toolbar_aifc_user_intent_fix')) {
137
+ if (state !== null && state !== void 0 && state.isSelectedViaDragHandle) {
138
138
  var _api$userIntent4;
139
139
  api === null || api === void 0 ? void 0 : (_api$userIntent4 = api.userIntent) === null || _api$userIntent4 === void 0 ? void 0 : _api$userIntent4.commands.setCurrentUserIntent('dragHandleSelected')({
140
140
  tr
@@ -83,7 +83,7 @@ export const dragHandleDecoration = ({
83
83
  const getPos = () => {
84
84
  try {
85
85
  return getPosUnsafe();
86
- } catch (e) {
86
+ } catch {
87
87
  // Ignore errors from getPosUnsafe
88
88
  return undefined;
89
89
  }
@@ -1,5 +1,4 @@
1
1
  import { DRAG_HANDLE_SELECTOR } from '@atlaskit/editor-common/styles';
2
- import { fg } from '@atlaskit/platform-feature-flags';
3
2
  import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
4
3
  import { expValEqualsNoExposure } from '@atlaskit/tmp-editor-statsig/exp-val-equals-no-exposure';
5
4
  export const handleMouseDown = api => (view, event) => {
@@ -39,21 +38,19 @@ export const handleMouseDown = api => (view, event) => {
39
38
  * When block menu is enabled, reset intent back to 'default' as editor-plugin-block-menu sets the user intent to 'blockMenuOpen', and setting here
40
39
  * causes flickering as this runs before editor-plugin-block-menu.
41
40
  */
42
- if (fg('platform_editor_toolbar_aifc_user_intent_fix')) {
43
- if (expValEqualsNoExposure('platform_editor_block_menu', 'isEnabled', true)) {
44
- // if target is drag handle, block menu will be opened
45
- if (!isDragHandle) {
46
- var _api$userIntent;
47
- api === null || api === void 0 ? void 0 : (_api$userIntent = api.userIntent) === null || _api$userIntent === void 0 ? void 0 : _api$userIntent.commands.setCurrentUserIntent('default')({
48
- tr
49
- });
50
- }
51
- } else {
52
- var _api$userIntent2;
53
- (_api$userIntent2 = api.userIntent) === null || _api$userIntent2 === void 0 ? void 0 : _api$userIntent2.commands.setCurrentUserIntent(isDragHandle ? 'dragHandleSelected' : 'default')({
41
+ if (expValEqualsNoExposure('platform_editor_block_menu', 'isEnabled', true)) {
42
+ // if target is drag handle, block menu will be opened
43
+ if (!isDragHandle) {
44
+ var _api$userIntent;
45
+ api === null || api === void 0 ? void 0 : (_api$userIntent = api.userIntent) === null || _api$userIntent === void 0 ? void 0 : _api$userIntent.commands.setCurrentUserIntent('default')({
54
46
  tr
55
47
  });
56
48
  }
49
+ } else {
50
+ var _api$userIntent2;
51
+ (_api$userIntent2 = api.userIntent) === null || _api$userIntent2 === void 0 ? void 0 : _api$userIntent2.commands.setCurrentUserIntent(isDragHandle ? 'dragHandleSelected' : 'default')({
52
+ tr
53
+ });
57
54
  }
58
55
  return tr;
59
56
  });
@@ -0,0 +1,57 @@
1
+ /** @jsxRuntime classic */
2
+ /**
3
+ * @jsxRuntime classic
4
+ * @jsx jsx
5
+ */
6
+ // eslint-disable-next-line @atlaskit/ui-styling-standard/use-compiled -- Ignored via go/DSP-18766
7
+ import { css, jsx } from '@emotion/react';
8
+ const spanStyles = css({
9
+ display: 'inline-block',
10
+ boxSizing: 'border-box',
11
+ flexShrink: 0
12
+ });
13
+ const svgSizeStyles = css({
14
+ width: '24px',
15
+ height: '24px'
16
+ });
17
+ const svgStyles = css({
18
+ color: 'currentColor',
19
+ overflow: 'hidden',
20
+ pointerEvents: 'none',
21
+ verticalAlign: 'bottom'
22
+ });
23
+
24
+ /**
25
+ * Custom 3-dot vertical drag handle icon for nested nodes.
26
+ * Similar to DragHandleVerticalIcon but with only 3 dots instead of 6.
27
+ * Hardcoded to medium size with spacious spacing.
28
+ */
29
+ export const DragHandleNestedIcon = () => {
30
+ return jsx("span", {
31
+ "aria-hidden": true,
32
+ css: spanStyles
33
+ }, jsx("svg", {
34
+ width: 24,
35
+ height: 24,
36
+ viewBox: "-4 -4 24 24",
37
+ fill: "none",
38
+ xmlns: "http://www.w3.org/2000/svg",
39
+ role: "presentation",
40
+ css: [svgStyles, svgSizeStyles]
41
+ }, jsx("circle", {
42
+ cx: "8",
43
+ cy: "4",
44
+ r: "1.5",
45
+ fill: "currentColor"
46
+ }), jsx("circle", {
47
+ cx: "8",
48
+ cy: "8",
49
+ r: "1.5",
50
+ fill: "currentColor"
51
+ }), jsx("circle", {
52
+ cx: "8",
53
+ cy: "12",
54
+ r: "1.5",
55
+ fill: "currentColor"
56
+ })));
57
+ };
@@ -39,6 +39,7 @@ import { getControlBottomCSSValue, getControlHeightCSSValue, getLeftPosition, ge
39
39
  import { isHandleCorrelatedToSelection, selectNode } from '../pm-plugins/utils/getSelection';
40
40
  import { adjustSelectionBoundsForEdgePositions, alignAnchorHeadInDirectionOfPos, expandSelectionHeadToNodeAtPos } from '../pm-plugins/utils/selection';
41
41
  import { DRAG_HANDLE_BORDER_RADIUS, DRAG_HANDLE_HEIGHT, DRAG_HANDLE_MAX_SHIFT_CLICK_DEPTH, DRAG_HANDLE_ZINDEX, dragHandleGap, nodeMargins, spacingBetweenNodesForPreview, STICKY_CONTROLS_TOP_MARGIN, STICKY_CONTROLS_TOP_MARGIN_FOR_STICKY_HEADER, topPositionAdjustment } from './consts';
42
+ import { DragHandleNestedIcon } from './drag-handle-nested-icon';
42
43
  import { dragPreview } from './drag-preview';
43
44
  import { refreshAnchorName } from './utils/anchor-name';
44
45
  import { getAnchorAttrName } from './utils/dom-attr-name';
@@ -427,6 +428,24 @@ export const DragHandle = ({
427
428
  const start = getPos();
428
429
  const isLayoutColumn = nodeType === 'layoutColumn';
429
430
  const isMultiSelect = editorExperiment('platform_editor_element_drag_and_drop_multiselect', true);
431
+
432
+ // Dynamically calculate if node is top-level based on current position (gated by experiment)
433
+ const isTopLevelNodeDynamic = useMemo(() => {
434
+ if (!expValEquals('platform_editor_nested_drag_handle_icon', 'isEnabled', true)) {
435
+ return isTopLevelNode;
436
+ }
437
+ const pos = getPos();
438
+ if (typeof pos === 'number') {
439
+ const $pos = view.state.doc.resolve(pos);
440
+ return ($pos === null || $pos === void 0 ? void 0 : $pos.parent.type.name) === 'doc';
441
+ }
442
+ return true;
443
+ }, [getPos, view.state.doc, isTopLevelNode]);
444
+
445
+ // Use the dynamic value when experiment is on, otherwise use the prop
446
+ // When cleaning up the experiment, you can safely remove the isTopLevelNode as an prop and
447
+ // just rely on the dynamic value (rename it to isTopLevelNode for simplicitiy)
448
+ const isTopLevelNodeValue = expValEquals('platform_editor_nested_drag_handle_icon', 'isEnabled', true) ? isTopLevelNodeDynamic : isTopLevelNode;
430
449
  useEffect(() => {
431
450
  if (editorExperiment('platform_editor_block_control_optimise_render', true)) {
432
451
  return;
@@ -517,7 +536,7 @@ export const DragHandle = ({
517
536
  const $anchor = (mSelect === null || mSelect === void 0 ? void 0 : mSelect.anchor) !== undefined ? tr.doc.resolve(mSelect === null || mSelect === void 0 ? void 0 : mSelect.anchor) : tr.selection.$anchor;
518
537
  if (!isMultiSelect || tr.selection.empty || !e.shiftKey) {
519
538
  tr = selectNode(tr, startPos, nodeType, api);
520
- } else if (isTopLevelNode && $anchor.depth <= DRAG_HANDLE_MAX_SHIFT_CLICK_DEPTH && e.shiftKey && fg('platform_editor_elements_dnd_shift_click_select')) {
539
+ } else if (isTopLevelNodeValue && $anchor.depth <= DRAG_HANDLE_MAX_SHIFT_CLICK_DEPTH && e.shiftKey && fg('platform_editor_elements_dnd_shift_click_select')) {
521
540
  var _api$blockControls3;
522
541
  const alignAnchorHeadToSel = alignAnchorHeadInDirectionOfPos(tr.selection, startPos);
523
542
  const selectionWithExpandedHead = expandSelectionHeadToNodeAtPos(alignAnchorHeadToSel, startPos);
@@ -542,7 +561,7 @@ export const DragHandle = ({
542
561
  return tr;
543
562
  });
544
563
  view.focus();
545
- }, [isMultiSelect, api, view, dragHandleSelected, getPos, isTopLevelNode, nodeType]);
564
+ }, [isMultiSelect, api, view, dragHandleSelected, getPos, isTopLevelNodeValue, nodeType]);
546
565
  const handleKeyDown = useCallback(e => {
547
566
  // allow user to use spacebar to select the node
548
567
  if (!e.repeat && e.key === ' ') {
@@ -847,20 +866,20 @@ export const DragHandle = ({
847
866
  const isEdgeCase = (hasResizer || isExtension || isEmbedCard || isBlockCard) && innerContainer;
848
867
  const isSticky = shouldBeSticky(nodeType);
849
868
  if (supportsAnchor) {
850
- const bottom = editorExperiment('platform_editor_controls', 'variant1') ? getControlBottomCSSValue(safeAnchorName, isSticky, isTopLevelNode, isLayoutColumn) : {};
869
+ const bottom = editorExperiment('platform_editor_controls', 'variant1') ? getControlBottomCSSValue(safeAnchorName, isSticky, isTopLevelNodeValue, isLayoutColumn) : {};
851
870
  return {
852
871
  left: isEdgeCase ? `calc(anchor(${safeAnchorName} start) + ${getLeftPosition(dom, nodeType, innerContainer, isMacroInteractionUpdates, parentNodeType)})` : editorExperiment('advanced_layouts', true) && isLayoutColumn ? `calc((anchor(${safeAnchorName} right) + anchor(${safeAnchorName} left))/2 - ${DRAG_HANDLE_HEIGHT / 2}px)` : `calc(anchor(${safeAnchorName} start) - ${DRAG_HANDLE_WIDTH}px - ${dragHandleGap(nodeType, parentNodeType)}px)`,
853
872
  top: editorExperiment('advanced_layouts', true) && isLayoutColumn ? `calc(anchor(${safeAnchorName} top) - ${DRAG_HANDLE_WIDTH}px)` : `calc(anchor(${safeAnchorName} start)+ ${topPositionAdjustment(expValEquals('platform_editor_native_anchor_with_dnd', 'isEnabled', true) ? $pos && $pos.nodeAfter && getNodeTypeWithLevel($pos.nodeAfter) || nodeType : nodeType)}px)`,
854
873
  ...bottom
855
874
  };
856
875
  }
857
- const height = editorExperiment('platform_editor_controls', 'variant1') ? getControlHeightCSSValue(getNodeHeight(dom, safeAnchorName, anchorRectCache) || 0, isSticky, isTopLevelNode, `${DRAG_HANDLE_HEIGHT}`, isLayoutColumn) : {};
876
+ const height = editorExperiment('platform_editor_controls', 'variant1') ? getControlHeightCSSValue(getNodeHeight(dom, safeAnchorName, anchorRectCache) || 0, isSticky, isTopLevelNodeValue, `${DRAG_HANDLE_HEIGHT}`, isLayoutColumn) : {};
858
877
  return {
859
878
  left: isEdgeCase ? `calc(${(dom === null || dom === void 0 ? void 0 : dom.offsetLeft) || 0}px + ${getLeftPosition(dom, nodeType, innerContainer, isMacroInteractionUpdates, parentNodeType)})` : getLeftPosition(dom, nodeType, innerContainer, isMacroInteractionUpdates, parentNodeType),
860
879
  top: getTopPosition(dom, nodeType),
861
880
  ...height
862
881
  };
863
- }, [anchorName, getPos, view, nodeType, macroInteractionUpdates, anchorRectCache, isTopLevelNode, isLayoutColumn, recalculatePosition]);
882
+ }, [anchorName, getPos, view, nodeType, macroInteractionUpdates, anchorRectCache, isTopLevelNodeValue, isLayoutColumn, recalculatePosition]);
864
883
  const calculatePositionOld = useCallback(() => {
865
884
  const pos = getPos();
866
885
  const $pos = expValEquals('platform_editor_native_anchor_with_dnd', 'isEnabled', true) ? typeof pos === 'number' && view.state.doc.resolve(pos) : pos && view.state.doc.resolve(pos);
@@ -895,20 +914,20 @@ export const DragHandle = ({
895
914
  const isEdgeCase = (hasResizer || isExtension || isEmbedCard || isBlockCard) && innerContainer;
896
915
  const isSticky = shouldBeSticky(nodeType);
897
916
  if (supportsAnchor) {
898
- const bottom = editorExperiment('platform_editor_controls', 'variant1') ? getControlBottomCSSValue(safeAnchorName, isSticky, isTopLevelNode, isLayoutColumn) : {};
917
+ const bottom = editorExperiment('platform_editor_controls', 'variant1') ? getControlBottomCSSValue(safeAnchorName, isSticky, isTopLevelNodeValue, isLayoutColumn) : {};
899
918
  return {
900
919
  left: isEdgeCase ? `calc(anchor(${safeAnchorName} start) + ${getLeftPosition(dom, nodeType, innerContainer, isMacroInteractionUpdates, parentNodeType)})` : editorExperiment('advanced_layouts', true) && isLayoutColumn ? `calc((anchor(${safeAnchorName} right) + anchor(${safeAnchorName} left))/2 - ${DRAG_HANDLE_HEIGHT / 2}px)` : `calc(anchor(${safeAnchorName} start) - ${DRAG_HANDLE_WIDTH}px - ${dragHandleGap(nodeType, parentNodeType)}px)`,
901
920
  top: editorExperiment('advanced_layouts', true) && isLayoutColumn ? `calc(anchor(${safeAnchorName} top) - ${DRAG_HANDLE_WIDTH}px)` : `calc(anchor(${safeAnchorName} start) + ${topPositionAdjustment(expValEquals('platform_editor_native_anchor_with_dnd', 'isEnabled', true) ? $pos && $pos.nodeAfter && getNodeTypeWithLevel($pos.nodeAfter) || nodeType : nodeType)}px)`,
902
921
  ...bottom
903
922
  };
904
923
  }
905
- const height = editorExperiment('platform_editor_controls', 'variant1') ? getControlHeightCSSValue(getNodeHeight(dom, safeAnchorName, anchorRectCache) || 0, isSticky, isTopLevelNode, `${DRAG_HANDLE_HEIGHT}`, isLayoutColumn) : {};
924
+ const height = editorExperiment('platform_editor_controls', 'variant1') ? getControlHeightCSSValue(getNodeHeight(dom, safeAnchorName, anchorRectCache) || 0, isSticky, isTopLevelNodeValue, `${DRAG_HANDLE_HEIGHT}`, isLayoutColumn) : {};
906
925
  return {
907
926
  left: isEdgeCase ? `calc(${(dom === null || dom === void 0 ? void 0 : dom.offsetLeft) || 0}px + ${getLeftPosition(dom, nodeType, innerContainer, isMacroInteractionUpdates, parentNodeType)})` : getLeftPosition(dom, nodeType, innerContainer, isMacroInteractionUpdates, parentNodeType),
908
927
  top: getTopPosition(dom, nodeType),
909
928
  ...height
910
929
  };
911
- }, [anchorName, getPos, view, nodeType, blockCardWidth, macroInteractionUpdates, anchorRectCache, isTopLevelNode, isLayoutColumn]);
930
+ }, [anchorName, getPos, view, nodeType, blockCardWidth, macroInteractionUpdates, anchorRectCache, isTopLevelNodeValue, isLayoutColumn]);
912
931
  useEffect(() => {
913
932
  if (editorExperiment('platform_editor_block_control_optimise_render', true)) {
914
933
  return;
@@ -984,12 +1003,12 @@ export const DragHandle = ({
984
1003
  }
985
1004
  const mSelect = api === null || api === void 0 ? void 0 : (_api$blockControls$sh4 = api.blockControls.sharedState.currentState()) === null || _api$blockControls$sh4 === void 0 ? void 0 : _api$blockControls$sh4.multiSelectDnD;
986
1005
  const $anchor = (mSelect === null || mSelect === void 0 ? void 0 : mSelect.anchor) !== undefined ? view.state.doc.resolve(mSelect === null || mSelect === void 0 ? void 0 : mSelect.anchor) : view.state.selection.$anchor;
987
- if (isShiftDown && (!isTopLevelNode || isTopLevelNode && $anchor.depth > DRAG_HANDLE_MAX_SHIFT_CLICK_DEPTH)) {
1006
+ if (isShiftDown && (!isTopLevelNodeValue || isTopLevelNodeValue && $anchor.depth > DRAG_HANDLE_MAX_SHIFT_CLICK_DEPTH)) {
988
1007
  setDragHandleDisabled(true);
989
1008
  } else {
990
1009
  setDragHandleDisabled(false);
991
1010
  }
992
- }, [api === null || api === void 0 ? void 0 : api.blockControls.sharedState, isMultiSelect, isShiftDown, isTopLevelNode, view]);
1011
+ }, [api === null || api === void 0 ? void 0 : api.blockControls.sharedState, isMultiSelect, isShiftDown, isTopLevelNodeValue, view]);
993
1012
  const dragHandleMessage = expValEqualsNoExposure('platform_editor_block_menu', 'isEnabled', true) ? formatMessage(blockControlsMessages.dragToMoveClickToOpen, {
994
1013
  br: jsx("br", null)
995
1014
  }) : formatMessage(blockControlsMessages.dragToMove);
@@ -998,7 +1017,7 @@ export const DragHandle = ({
998
1017
  const dragHandleAriaLabel = expValEqualsNoExposure('platform_editor_block_menu', 'isEnabled', true) ? formatMessage(blockControlsMessages.dragToMoveClickToOpen, {
999
1018
  br: ' '
1000
1019
  }) : formatMessage(blockControlsMessages.dragToMove);
1001
- let helpDescriptors = isTopLevelNode ? [{
1020
+ let helpDescriptors = isTopLevelNodeValue ? [{
1002
1021
  description: dragHandleMessage
1003
1022
  }, {
1004
1023
  description: formatMessage(blockControlsMessages.moveUp),
@@ -1022,7 +1041,7 @@ export const DragHandle = ({
1022
1041
  keymap: dragToMoveDown
1023
1042
  }];
1024
1043
  let isParentNodeOfTypeLayout;
1025
- if (!isTopLevelNode) {
1044
+ if (!isTopLevelNodeValue) {
1026
1045
  const pos = getPos();
1027
1046
  if (typeof pos === 'number') {
1028
1047
  var _$pos$parent;
@@ -1099,7 +1118,7 @@ export const DragHandle = ({
1099
1118
  // eslint-disable-next-line @atlaskit/design-system/no-direct-use-of-web-platform-drag-and-drop
1100
1119
  ,
1101
1120
  onDragStart: handleIconDragStart
1102
- }, jsx(DragHandleVerticalIcon, {
1121
+ }, expValEquals('platform_editor_nested_drag_handle_icon', 'isEnabled', true) && !isTopLevelNodeValue ? jsx(DragHandleNestedIcon, null) : jsx(DragHandleVerticalIcon, {
1103
1122
  spacing: "spacious",
1104
1123
  label: "",
1105
1124
  size: "small"
@@ -1112,7 +1131,7 @@ export const DragHandle = ({
1112
1131
  as: "span",
1113
1132
  testId: "block-ctrl-drag-handle-container"
1114
1133
  }, jsx("span", {
1115
- css: [tooltipContainerStyles, shouldMaskNodeControls(nodeType, isTopLevelNode) && (expValEquals('platform_editor_table_sticky_header_improvements', 'cohort', 'test_with_overflow') && fg('platform_editor_table_sticky_header_patch_6') ? tooltipContainerStylesImprovedStickyHeaderWithMask : tooltipContainerStylesStickyHeaderWithMask), !shouldMaskNodeControls(nodeType, isTopLevelNode) && tooltipContainerStylesStickyHeaderWithoutMask]
1134
+ css: [tooltipContainerStyles, shouldMaskNodeControls(nodeType, isTopLevelNodeValue) && (expValEquals('platform_editor_table_sticky_header_improvements', 'cohort', 'test_with_overflow') && fg('platform_editor_table_sticky_header_patch_6') ? tooltipContainerStylesImprovedStickyHeaderWithMask : tooltipContainerStylesStickyHeaderWithMask), !shouldMaskNodeControls(nodeType, isTopLevelNodeValue) && tooltipContainerStylesStickyHeaderWithoutMask]
1116
1135
  }, jsx(Tooltip, {
1117
1136
  content: jsx(TooltipContentWithMultipleShortcuts, {
1118
1137
  helpDescriptors: helpDescriptors
@@ -1126,7 +1145,7 @@ export const DragHandle = ({
1126
1145
  });
1127
1146
  }
1128
1147
  }, jsx("span", {
1129
- css: [shouldMaskNodeControls(nodeType, isTopLevelNode) && buttonWrapperStyles, buttonWrapperStylesPatch]
1148
+ css: [shouldMaskNodeControls(nodeType, isTopLevelNodeValue) && buttonWrapperStyles, buttonWrapperStylesPatch]
1130
1149
  }, renderButton()))));
1131
1150
  const stickyWithoutTooltip = () => jsx(Box
1132
1151
  // eslint-disable-next-line @atlaskit/ui-styling-standard/enforce-style-prop
@@ -1136,9 +1155,9 @@ export const DragHandle = ({
1136
1155
  as: "span",
1137
1156
  testId: "block-ctrl-drag-handle-container"
1138
1157
  }, jsx("span", {
1139
- css: [tooltipContainerStyles, shouldMaskNodeControls(nodeType, isTopLevelNode) && tooltipContainerStylesStickyHeaderWithMask, !shouldMaskNodeControls(nodeType, isTopLevelNode) && tooltipContainerStylesStickyHeaderWithoutMask]
1158
+ css: [tooltipContainerStyles, shouldMaskNodeControls(nodeType, isTopLevelNodeValue) && tooltipContainerStylesStickyHeaderWithMask, !shouldMaskNodeControls(nodeType, isTopLevelNodeValue) && tooltipContainerStylesStickyHeaderWithoutMask]
1140
1159
  }, jsx("span", {
1141
- css: [shouldMaskNodeControls(nodeType, isTopLevelNode) && buttonWrapperStyles, buttonWrapperStylesPatch]
1160
+ css: [shouldMaskNodeControls(nodeType, isTopLevelNodeValue) && buttonWrapperStyles, buttonWrapperStylesPatch]
1142
1161
  }, renderButton())));
1143
1162
  const buttonWithTooltip = () => jsx(Tooltip, {
1144
1163
  content: jsx(TooltipContentWithMultipleShortcuts, {
@@ -1165,6 +1184,7 @@ export const DragHandleWithVisibility = ({
1165
1184
  anchorName,
1166
1185
  nodeType,
1167
1186
  handleOptions,
1187
+ isTopLevelNode,
1168
1188
  anchorRectCache
1169
1189
  }) => {
1170
1190
  return jsx(VisibilityContainer, {
@@ -1177,6 +1197,7 @@ export const DragHandleWithVisibility = ({
1177
1197
  anchorName: anchorName,
1178
1198
  nodeType: nodeType,
1179
1199
  handleOptions: handleOptions,
1200
+ isTopLevelNode: isTopLevelNode,
1180
1201
  anchorRectCache: anchorRectCache
1181
1202
  }));
1182
1203
  };
@@ -133,7 +133,7 @@ export var blockControlsPlugin = function blockControlsPlugin(_ref) {
133
133
  }));
134
134
  if ((menuTriggerBy === undefined || !!menuTriggerBy && menuTriggerBy === (options === null || options === void 0 ? void 0 : options.anchorName)) && currentUserIntent === 'blockMenuOpen') {
135
135
  var state = api === null || api === void 0 ? void 0 : api.blockControls.sharedState.currentState();
136
- if (state !== null && state !== void 0 && state.isSelectedViaDragHandle && fg('platform_editor_toolbar_aifc_user_intent_fix')) {
136
+ if (state !== null && state !== void 0 && state.isSelectedViaDragHandle) {
137
137
  var _api$userIntent4;
138
138
  api === null || api === void 0 || (_api$userIntent4 = api.userIntent) === null || _api$userIntent4 === void 0 || _api$userIntent4.commands.setCurrentUserIntent('dragHandleSelected')({
139
139
  tr: tr
@@ -84,7 +84,7 @@ export var dragHandleDecoration = function dragHandleDecoration(_ref) {
84
84
  var getPos = function getPos() {
85
85
  try {
86
86
  return getPosUnsafe();
87
- } catch (e) {
87
+ } catch (_unused) {
88
88
  // Ignore errors from getPosUnsafe
89
89
  return undefined;
90
90
  }
@@ -1,5 +1,4 @@
1
1
  import { DRAG_HANDLE_SELECTOR } from '@atlaskit/editor-common/styles';
2
- import { fg } from '@atlaskit/platform-feature-flags';
3
2
  import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
4
3
  import { expValEqualsNoExposure } from '@atlaskit/tmp-editor-statsig/exp-val-equals-no-exposure';
5
4
  export var handleMouseDown = function handleMouseDown(api) {
@@ -39,21 +38,19 @@ export var handleMouseDown = function handleMouseDown(api) {
39
38
  * When block menu is enabled, reset intent back to 'default' as editor-plugin-block-menu sets the user intent to 'blockMenuOpen', and setting here
40
39
  * causes flickering as this runs before editor-plugin-block-menu.
41
40
  */
42
- if (fg('platform_editor_toolbar_aifc_user_intent_fix')) {
43
- if (expValEqualsNoExposure('platform_editor_block_menu', 'isEnabled', true)) {
44
- // if target is drag handle, block menu will be opened
45
- if (!isDragHandle) {
46
- var _api$userIntent;
47
- api === null || api === void 0 || (_api$userIntent = api.userIntent) === null || _api$userIntent === void 0 || _api$userIntent.commands.setCurrentUserIntent('default')({
48
- tr: tr
49
- });
50
- }
51
- } else {
52
- var _api$userIntent2;
53
- (_api$userIntent2 = api.userIntent) === null || _api$userIntent2 === void 0 || _api$userIntent2.commands.setCurrentUserIntent(isDragHandle ? 'dragHandleSelected' : 'default')({
41
+ if (expValEqualsNoExposure('platform_editor_block_menu', 'isEnabled', true)) {
42
+ // if target is drag handle, block menu will be opened
43
+ if (!isDragHandle) {
44
+ var _api$userIntent;
45
+ api === null || api === void 0 || (_api$userIntent = api.userIntent) === null || _api$userIntent === void 0 || _api$userIntent.commands.setCurrentUserIntent('default')({
54
46
  tr: tr
55
47
  });
56
48
  }
49
+ } else {
50
+ var _api$userIntent2;
51
+ (_api$userIntent2 = api.userIntent) === null || _api$userIntent2 === void 0 || _api$userIntent2.commands.setCurrentUserIntent(isDragHandle ? 'dragHandleSelected' : 'default')({
52
+ tr: tr
53
+ });
57
54
  }
58
55
  return tr;
59
56
  });
@@ -0,0 +1,57 @@
1
+ /** @jsxRuntime classic */
2
+ /**
3
+ * @jsxRuntime classic
4
+ * @jsx jsx
5
+ */
6
+ // eslint-disable-next-line @atlaskit/ui-styling-standard/use-compiled -- Ignored via go/DSP-18766
7
+ import { css, jsx } from '@emotion/react';
8
+ var spanStyles = css({
9
+ display: 'inline-block',
10
+ boxSizing: 'border-box',
11
+ flexShrink: 0
12
+ });
13
+ var svgSizeStyles = css({
14
+ width: '24px',
15
+ height: '24px'
16
+ });
17
+ var svgStyles = css({
18
+ color: 'currentColor',
19
+ overflow: 'hidden',
20
+ pointerEvents: 'none',
21
+ verticalAlign: 'bottom'
22
+ });
23
+
24
+ /**
25
+ * Custom 3-dot vertical drag handle icon for nested nodes.
26
+ * Similar to DragHandleVerticalIcon but with only 3 dots instead of 6.
27
+ * Hardcoded to medium size with spacious spacing.
28
+ */
29
+ export var DragHandleNestedIcon = function DragHandleNestedIcon() {
30
+ return jsx("span", {
31
+ "aria-hidden": true,
32
+ css: spanStyles
33
+ }, jsx("svg", {
34
+ width: 24,
35
+ height: 24,
36
+ viewBox: "-4 -4 24 24",
37
+ fill: "none",
38
+ xmlns: "http://www.w3.org/2000/svg",
39
+ role: "presentation",
40
+ css: [svgStyles, svgSizeStyles]
41
+ }, jsx("circle", {
42
+ cx: "8",
43
+ cy: "4",
44
+ r: "1.5",
45
+ fill: "currentColor"
46
+ }), jsx("circle", {
47
+ cx: "8",
48
+ cy: "8",
49
+ r: "1.5",
50
+ fill: "currentColor"
51
+ }), jsx("circle", {
52
+ cx: "8",
53
+ cy: "12",
54
+ r: "1.5",
55
+ fill: "currentColor"
56
+ })));
57
+ };
@@ -44,6 +44,7 @@ import { getControlBottomCSSValue, getControlHeightCSSValue, getLeftPosition, ge
44
44
  import { isHandleCorrelatedToSelection, selectNode } from '../pm-plugins/utils/getSelection';
45
45
  import { adjustSelectionBoundsForEdgePositions, alignAnchorHeadInDirectionOfPos, expandSelectionHeadToNodeAtPos } from '../pm-plugins/utils/selection';
46
46
  import { DRAG_HANDLE_BORDER_RADIUS, DRAG_HANDLE_HEIGHT, DRAG_HANDLE_MAX_SHIFT_CLICK_DEPTH, DRAG_HANDLE_ZINDEX, dragHandleGap, nodeMargins, spacingBetweenNodesForPreview, STICKY_CONTROLS_TOP_MARGIN, STICKY_CONTROLS_TOP_MARGIN_FOR_STICKY_HEADER, topPositionAdjustment } from './consts';
47
+ import { DragHandleNestedIcon } from './drag-handle-nested-icon';
47
48
  import { dragPreview } from './drag-preview';
48
49
  import { refreshAnchorName } from './utils/anchor-name';
49
50
  import { getAnchorAttrName } from './utils/dom-attr-name';
@@ -444,6 +445,24 @@ export var DragHandle = function DragHandle(_ref3) {
444
445
  var start = getPos();
445
446
  var isLayoutColumn = nodeType === 'layoutColumn';
446
447
  var isMultiSelect = editorExperiment('platform_editor_element_drag_and_drop_multiselect', true);
448
+
449
+ // Dynamically calculate if node is top-level based on current position (gated by experiment)
450
+ var isTopLevelNodeDynamic = useMemo(function () {
451
+ if (!expValEquals('platform_editor_nested_drag_handle_icon', 'isEnabled', true)) {
452
+ return isTopLevelNode;
453
+ }
454
+ var pos = getPos();
455
+ if (typeof pos === 'number') {
456
+ var $pos = view.state.doc.resolve(pos);
457
+ return ($pos === null || $pos === void 0 ? void 0 : $pos.parent.type.name) === 'doc';
458
+ }
459
+ return true;
460
+ }, [getPos, view.state.doc, isTopLevelNode]);
461
+
462
+ // Use the dynamic value when experiment is on, otherwise use the prop
463
+ // When cleaning up the experiment, you can safely remove the isTopLevelNode as an prop and
464
+ // just rely on the dynamic value (rename it to isTopLevelNode for simplicitiy)
465
+ var isTopLevelNodeValue = expValEquals('platform_editor_nested_drag_handle_icon', 'isEnabled', true) ? isTopLevelNodeDynamic : isTopLevelNode;
447
466
  useEffect(function () {
448
467
  if (editorExperiment('platform_editor_block_control_optimise_render', true)) {
449
468
  return;
@@ -534,7 +553,7 @@ export var DragHandle = function DragHandle(_ref3) {
534
553
  var $anchor = (mSelect === null || mSelect === void 0 ? void 0 : mSelect.anchor) !== undefined ? tr.doc.resolve(mSelect === null || mSelect === void 0 ? void 0 : mSelect.anchor) : tr.selection.$anchor;
535
554
  if (!isMultiSelect || tr.selection.empty || !e.shiftKey) {
536
555
  tr = selectNode(tr, startPos, nodeType, api);
537
- } else if (isTopLevelNode && $anchor.depth <= DRAG_HANDLE_MAX_SHIFT_CLICK_DEPTH && e.shiftKey && fg('platform_editor_elements_dnd_shift_click_select')) {
556
+ } else if (isTopLevelNodeValue && $anchor.depth <= DRAG_HANDLE_MAX_SHIFT_CLICK_DEPTH && e.shiftKey && fg('platform_editor_elements_dnd_shift_click_select')) {
538
557
  var _api$blockControls3;
539
558
  var alignAnchorHeadToSel = alignAnchorHeadInDirectionOfPos(tr.selection, startPos);
540
559
  var selectionWithExpandedHead = expandSelectionHeadToNodeAtPos(alignAnchorHeadToSel, startPos);
@@ -559,7 +578,7 @@ export var DragHandle = function DragHandle(_ref3) {
559
578
  return tr;
560
579
  });
561
580
  view.focus();
562
- }, [isMultiSelect, api, view, dragHandleSelected, getPos, isTopLevelNode, nodeType]);
581
+ }, [isMultiSelect, api, view, dragHandleSelected, getPos, isTopLevelNodeValue, nodeType]);
563
582
  var handleKeyDown = useCallback(function (e) {
564
583
  // allow user to use spacebar to select the node
565
584
  if (!e.repeat && e.key === ' ') {
@@ -859,18 +878,18 @@ export var DragHandle = function DragHandle(_ref3) {
859
878
  var isEdgeCase = (hasResizer || isExtension || isEmbedCard || isBlockCard) && innerContainer;
860
879
  var isSticky = shouldBeSticky(nodeType);
861
880
  if (supportsAnchor) {
862
- var bottom = editorExperiment('platform_editor_controls', 'variant1') ? getControlBottomCSSValue(safeAnchorName, isSticky, isTopLevelNode, isLayoutColumn) : {};
881
+ var bottom = editorExperiment('platform_editor_controls', 'variant1') ? getControlBottomCSSValue(safeAnchorName, isSticky, isTopLevelNodeValue, isLayoutColumn) : {};
863
882
  return _objectSpread({
864
883
  left: isEdgeCase ? "calc(anchor(".concat(safeAnchorName, " start) + ").concat(getLeftPosition(dom, nodeType, innerContainer, isMacroInteractionUpdates, parentNodeType), ")") : editorExperiment('advanced_layouts', true) && isLayoutColumn ? "calc((anchor(".concat(safeAnchorName, " right) + anchor(").concat(safeAnchorName, " left))/2 - ").concat(DRAG_HANDLE_HEIGHT / 2, "px)") : "calc(anchor(".concat(safeAnchorName, " start) - ").concat(DRAG_HANDLE_WIDTH, "px - ").concat(dragHandleGap(nodeType, parentNodeType), "px)"),
865
884
  top: editorExperiment('advanced_layouts', true) && isLayoutColumn ? "calc(anchor(".concat(safeAnchorName, " top) - ").concat(DRAG_HANDLE_WIDTH, "px)") : "calc(anchor(".concat(safeAnchorName, " start)+ ").concat(topPositionAdjustment(expValEquals('platform_editor_native_anchor_with_dnd', 'isEnabled', true) ? $pos && $pos.nodeAfter && getNodeTypeWithLevel($pos.nodeAfter) || nodeType : nodeType), "px)")
866
885
  }, bottom);
867
886
  }
868
- var height = editorExperiment('platform_editor_controls', 'variant1') ? getControlHeightCSSValue(getNodeHeight(dom, safeAnchorName, anchorRectCache) || 0, isSticky, isTopLevelNode, "".concat(DRAG_HANDLE_HEIGHT), isLayoutColumn) : {};
887
+ var height = editorExperiment('platform_editor_controls', 'variant1') ? getControlHeightCSSValue(getNodeHeight(dom, safeAnchorName, anchorRectCache) || 0, isSticky, isTopLevelNodeValue, "".concat(DRAG_HANDLE_HEIGHT), isLayoutColumn) : {};
869
888
  return _objectSpread({
870
889
  left: isEdgeCase ? "calc(".concat((dom === null || dom === void 0 ? void 0 : dom.offsetLeft) || 0, "px + ").concat(getLeftPosition(dom, nodeType, innerContainer, isMacroInteractionUpdates, parentNodeType), ")") : getLeftPosition(dom, nodeType, innerContainer, isMacroInteractionUpdates, parentNodeType),
871
890
  top: getTopPosition(dom, nodeType)
872
891
  }, height);
873
- }, [anchorName, getPos, view, nodeType, macroInteractionUpdates, anchorRectCache, isTopLevelNode, isLayoutColumn, recalculatePosition]);
892
+ }, [anchorName, getPos, view, nodeType, macroInteractionUpdates, anchorRectCache, isTopLevelNodeValue, isLayoutColumn, recalculatePosition]);
874
893
  var calculatePositionOld = useCallback(function () {
875
894
  var pos = getPos();
876
895
  var $pos = expValEquals('platform_editor_native_anchor_with_dnd', 'isEnabled', true) ? typeof pos === 'number' && view.state.doc.resolve(pos) : pos && view.state.doc.resolve(pos);
@@ -905,18 +924,18 @@ export var DragHandle = function DragHandle(_ref3) {
905
924
  var isEdgeCase = (hasResizer || isExtension || isEmbedCard || isBlockCard) && innerContainer;
906
925
  var isSticky = shouldBeSticky(nodeType);
907
926
  if (supportsAnchor) {
908
- var bottom = editorExperiment('platform_editor_controls', 'variant1') ? getControlBottomCSSValue(safeAnchorName, isSticky, isTopLevelNode, isLayoutColumn) : {};
927
+ var bottom = editorExperiment('platform_editor_controls', 'variant1') ? getControlBottomCSSValue(safeAnchorName, isSticky, isTopLevelNodeValue, isLayoutColumn) : {};
909
928
  return _objectSpread({
910
929
  left: isEdgeCase ? "calc(anchor(".concat(safeAnchorName, " start) + ").concat(getLeftPosition(dom, nodeType, innerContainer, isMacroInteractionUpdates, parentNodeType), ")") : editorExperiment('advanced_layouts', true) && isLayoutColumn ? "calc((anchor(".concat(safeAnchorName, " right) + anchor(").concat(safeAnchorName, " left))/2 - ").concat(DRAG_HANDLE_HEIGHT / 2, "px)") : "calc(anchor(".concat(safeAnchorName, " start) - ").concat(DRAG_HANDLE_WIDTH, "px - ").concat(dragHandleGap(nodeType, parentNodeType), "px)"),
911
930
  top: editorExperiment('advanced_layouts', true) && isLayoutColumn ? "calc(anchor(".concat(safeAnchorName, " top) - ").concat(DRAG_HANDLE_WIDTH, "px)") : "calc(anchor(".concat(safeAnchorName, " start) + ").concat(topPositionAdjustment(expValEquals('platform_editor_native_anchor_with_dnd', 'isEnabled', true) ? $pos && $pos.nodeAfter && getNodeTypeWithLevel($pos.nodeAfter) || nodeType : nodeType), "px)")
912
931
  }, bottom);
913
932
  }
914
- var height = editorExperiment('platform_editor_controls', 'variant1') ? getControlHeightCSSValue(getNodeHeight(dom, safeAnchorName, anchorRectCache) || 0, isSticky, isTopLevelNode, "".concat(DRAG_HANDLE_HEIGHT), isLayoutColumn) : {};
933
+ var height = editorExperiment('platform_editor_controls', 'variant1') ? getControlHeightCSSValue(getNodeHeight(dom, safeAnchorName, anchorRectCache) || 0, isSticky, isTopLevelNodeValue, "".concat(DRAG_HANDLE_HEIGHT), isLayoutColumn) : {};
915
934
  return _objectSpread({
916
935
  left: isEdgeCase ? "calc(".concat((dom === null || dom === void 0 ? void 0 : dom.offsetLeft) || 0, "px + ").concat(getLeftPosition(dom, nodeType, innerContainer, isMacroInteractionUpdates, parentNodeType), ")") : getLeftPosition(dom, nodeType, innerContainer, isMacroInteractionUpdates, parentNodeType),
917
936
  top: getTopPosition(dom, nodeType)
918
937
  }, height);
919
- }, [anchorName, getPos, view, nodeType, blockCardWidth, macroInteractionUpdates, anchorRectCache, isTopLevelNode, isLayoutColumn]);
938
+ }, [anchorName, getPos, view, nodeType, blockCardWidth, macroInteractionUpdates, anchorRectCache, isTopLevelNodeValue, isLayoutColumn]);
920
939
  useEffect(function () {
921
940
  if (editorExperiment('platform_editor_block_control_optimise_render', true)) {
922
941
  return;
@@ -992,12 +1011,12 @@ export var DragHandle = function DragHandle(_ref3) {
992
1011
  }
993
1012
  var mSelect = api === null || api === void 0 || (_api$blockControls$sh4 = api.blockControls.sharedState.currentState()) === null || _api$blockControls$sh4 === void 0 ? void 0 : _api$blockControls$sh4.multiSelectDnD;
994
1013
  var $anchor = (mSelect === null || mSelect === void 0 ? void 0 : mSelect.anchor) !== undefined ? view.state.doc.resolve(mSelect === null || mSelect === void 0 ? void 0 : mSelect.anchor) : view.state.selection.$anchor;
995
- if (isShiftDown && (!isTopLevelNode || isTopLevelNode && $anchor.depth > DRAG_HANDLE_MAX_SHIFT_CLICK_DEPTH)) {
1014
+ if (isShiftDown && (!isTopLevelNodeValue || isTopLevelNodeValue && $anchor.depth > DRAG_HANDLE_MAX_SHIFT_CLICK_DEPTH)) {
996
1015
  setDragHandleDisabled(true);
997
1016
  } else {
998
1017
  setDragHandleDisabled(false);
999
1018
  }
1000
- }, [api === null || api === void 0 ? void 0 : api.blockControls.sharedState, isMultiSelect, isShiftDown, isTopLevelNode, view]);
1019
+ }, [api === null || api === void 0 ? void 0 : api.blockControls.sharedState, isMultiSelect, isShiftDown, isTopLevelNodeValue, view]);
1001
1020
  var dragHandleMessage = expValEqualsNoExposure('platform_editor_block_menu', 'isEnabled', true) ? formatMessage(blockControlsMessages.dragToMoveClickToOpen, {
1002
1021
  br: jsx("br", null)
1003
1022
  }) : formatMessage(blockControlsMessages.dragToMove);
@@ -1006,7 +1025,7 @@ export var DragHandle = function DragHandle(_ref3) {
1006
1025
  var dragHandleAriaLabel = expValEqualsNoExposure('platform_editor_block_menu', 'isEnabled', true) ? formatMessage(blockControlsMessages.dragToMoveClickToOpen, {
1007
1026
  br: ' '
1008
1027
  }) : formatMessage(blockControlsMessages.dragToMove);
1009
- var helpDescriptors = isTopLevelNode ? [{
1028
+ var helpDescriptors = isTopLevelNodeValue ? [{
1010
1029
  description: dragHandleMessage
1011
1030
  }, {
1012
1031
  description: formatMessage(blockControlsMessages.moveUp),
@@ -1030,7 +1049,7 @@ export var DragHandle = function DragHandle(_ref3) {
1030
1049
  keymap: dragToMoveDown
1031
1050
  }];
1032
1051
  var isParentNodeOfTypeLayout;
1033
- if (!isTopLevelNode) {
1052
+ if (!isTopLevelNodeValue) {
1034
1053
  var pos = getPos();
1035
1054
  if (typeof pos === 'number') {
1036
1055
  var _$pos$parent;
@@ -1110,7 +1129,7 @@ export var DragHandle = function DragHandle(_ref3) {
1110
1129
  // eslint-disable-next-line @atlaskit/design-system/no-direct-use-of-web-platform-drag-and-drop
1111
1130
  ,
1112
1131
  onDragStart: handleIconDragStart
1113
- }, jsx(DragHandleVerticalIcon, {
1132
+ }, expValEquals('platform_editor_nested_drag_handle_icon', 'isEnabled', true) && !isTopLevelNodeValue ? jsx(DragHandleNestedIcon, null) : jsx(DragHandleVerticalIcon, {
1114
1133
  spacing: "spacious",
1115
1134
  label: "",
1116
1135
  size: "small"
@@ -1126,7 +1145,7 @@ export var DragHandle = function DragHandle(_ref3) {
1126
1145
  as: "span",
1127
1146
  testId: "block-ctrl-drag-handle-container"
1128
1147
  }, jsx("span", {
1129
- css: [tooltipContainerStyles, shouldMaskNodeControls(nodeType, isTopLevelNode) && (expValEquals('platform_editor_table_sticky_header_improvements', 'cohort', 'test_with_overflow') && fg('platform_editor_table_sticky_header_patch_6') ? tooltipContainerStylesImprovedStickyHeaderWithMask : tooltipContainerStylesStickyHeaderWithMask), !shouldMaskNodeControls(nodeType, isTopLevelNode) && tooltipContainerStylesStickyHeaderWithoutMask]
1148
+ css: [tooltipContainerStyles, shouldMaskNodeControls(nodeType, isTopLevelNodeValue) && (expValEquals('platform_editor_table_sticky_header_improvements', 'cohort', 'test_with_overflow') && fg('platform_editor_table_sticky_header_patch_6') ? tooltipContainerStylesImprovedStickyHeaderWithMask : tooltipContainerStylesStickyHeaderWithMask), !shouldMaskNodeControls(nodeType, isTopLevelNodeValue) && tooltipContainerStylesStickyHeaderWithoutMask]
1130
1149
  }, jsx(Tooltip, {
1131
1150
  content: jsx(TooltipContentWithMultipleShortcuts, {
1132
1151
  helpDescriptors: helpDescriptors
@@ -1140,7 +1159,7 @@ export var DragHandle = function DragHandle(_ref3) {
1140
1159
  });
1141
1160
  }
1142
1161
  }, jsx("span", {
1143
- css: [shouldMaskNodeControls(nodeType, isTopLevelNode) && buttonWrapperStyles, buttonWrapperStylesPatch]
1162
+ css: [shouldMaskNodeControls(nodeType, isTopLevelNodeValue) && buttonWrapperStyles, buttonWrapperStylesPatch]
1144
1163
  }, renderButton()))));
1145
1164
  };
1146
1165
  var stickyWithoutTooltip = function stickyWithoutTooltip() {
@@ -1152,9 +1171,9 @@ export var DragHandle = function DragHandle(_ref3) {
1152
1171
  as: "span",
1153
1172
  testId: "block-ctrl-drag-handle-container"
1154
1173
  }, jsx("span", {
1155
- css: [tooltipContainerStyles, shouldMaskNodeControls(nodeType, isTopLevelNode) && tooltipContainerStylesStickyHeaderWithMask, !shouldMaskNodeControls(nodeType, isTopLevelNode) && tooltipContainerStylesStickyHeaderWithoutMask]
1174
+ css: [tooltipContainerStyles, shouldMaskNodeControls(nodeType, isTopLevelNodeValue) && tooltipContainerStylesStickyHeaderWithMask, !shouldMaskNodeControls(nodeType, isTopLevelNodeValue) && tooltipContainerStylesStickyHeaderWithoutMask]
1156
1175
  }, jsx("span", {
1157
- css: [shouldMaskNodeControls(nodeType, isTopLevelNode) && buttonWrapperStyles, buttonWrapperStylesPatch]
1176
+ css: [shouldMaskNodeControls(nodeType, isTopLevelNodeValue) && buttonWrapperStyles, buttonWrapperStylesPatch]
1158
1177
  }, renderButton())));
1159
1178
  };
1160
1179
  var buttonWithTooltip = function buttonWithTooltip() {
@@ -1184,6 +1203,7 @@ export var DragHandleWithVisibility = function DragHandleWithVisibility(_ref10)
1184
1203
  anchorName = _ref10.anchorName,
1185
1204
  nodeType = _ref10.nodeType,
1186
1205
  handleOptions = _ref10.handleOptions,
1206
+ isTopLevelNode = _ref10.isTopLevelNode,
1187
1207
  anchorRectCache = _ref10.anchorRectCache;
1188
1208
  return jsx(VisibilityContainer, {
1189
1209
  api: api
@@ -1195,6 +1215,7 @@ export var DragHandleWithVisibility = function DragHandleWithVisibility(_ref10)
1195
1215
  anchorName: anchorName,
1196
1216
  nodeType: nodeType,
1197
1217
  handleOptions: handleOptions,
1218
+ isTopLevelNode: isTopLevelNode,
1198
1219
  anchorRectCache: anchorRectCache
1199
1220
  }));
1200
1221
  };
@@ -0,0 +1,12 @@
1
+ /** @jsxRuntime classic */
2
+ /**
3
+ * @jsxRuntime classic
4
+ * @jsx jsx
5
+ */
6
+ import { jsx } from '@emotion/react';
7
+ /**
8
+ * Custom 3-dot vertical drag handle icon for nested nodes.
9
+ * Similar to DragHandleVerticalIcon but with only 3 dots instead of 6.
10
+ * Hardcoded to medium size with spacious spacing.
11
+ */
12
+ export declare const DragHandleNestedIcon: () => jsx.JSX.Element;
@@ -16,5 +16,5 @@ type DragHandleProps = {
16
16
  view: EditorView;
17
17
  };
18
18
  export declare const DragHandle: ({ view, api, formatMessage, getPos, anchorName, nodeType, handleOptions, isTopLevelNode, anchorRectCache, }: DragHandleProps) => jsx.JSX.Element;
19
- export declare const DragHandleWithVisibility: ({ view, api, formatMessage, getPos, anchorName, nodeType, handleOptions, anchorRectCache, }: DragHandleProps) => jsx.JSX.Element;
19
+ export declare const DragHandleWithVisibility: ({ view, api, formatMessage, getPos, anchorName, nodeType, handleOptions, isTopLevelNode, anchorRectCache, }: DragHandleProps) => jsx.JSX.Element;
20
20
  export {};
@@ -0,0 +1,12 @@
1
+ /** @jsxRuntime classic */
2
+ /**
3
+ * @jsxRuntime classic
4
+ * @jsx jsx
5
+ */
6
+ import { jsx } from '@emotion/react';
7
+ /**
8
+ * Custom 3-dot vertical drag handle icon for nested nodes.
9
+ * Similar to DragHandleVerticalIcon but with only 3 dots instead of 6.
10
+ * Hardcoded to medium size with spacious spacing.
11
+ */
12
+ export declare const DragHandleNestedIcon: () => jsx.JSX.Element;
@@ -16,5 +16,5 @@ type DragHandleProps = {
16
16
  view: EditorView;
17
17
  };
18
18
  export declare const DragHandle: ({ view, api, formatMessage, getPos, anchorName, nodeType, handleOptions, isTopLevelNode, anchorRectCache, }: DragHandleProps) => jsx.JSX.Element;
19
- export declare const DragHandleWithVisibility: ({ view, api, formatMessage, getPos, anchorName, nodeType, handleOptions, anchorRectCache, }: DragHandleProps) => jsx.JSX.Element;
19
+ export declare const DragHandleWithVisibility: ({ view, api, formatMessage, getPos, anchorName, nodeType, handleOptions, isTopLevelNode, anchorRectCache, }: DragHandleProps) => jsx.JSX.Element;
20
20
  export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atlaskit/editor-plugin-block-controls",
3
- "version": "8.0.15",
3
+ "version": "8.1.0",
4
4
  "description": "Block controls plugin for @atlaskit/editor-core",
5
5
  "author": "Atlassian Pty Ltd",
6
6
  "license": "Apache-2.0",
@@ -54,7 +54,7 @@
54
54
  "@atlaskit/pragmatic-drag-and-drop-react-drop-indicator": "^3.2.0",
55
55
  "@atlaskit/primitives": "^17.1.0",
56
56
  "@atlaskit/theme": "^21.0.0",
57
- "@atlaskit/tmp-editor-statsig": "^16.35.0",
57
+ "@atlaskit/tmp-editor-statsig": "^17.0.0",
58
58
  "@atlaskit/tokens": "^10.1.0",
59
59
  "@atlaskit/tooltip": "^20.14.0",
60
60
  "@babel/runtime": "^7.0.0",
@@ -137,9 +137,6 @@
137
137
  "platform_editor_content_mode_button_mvp": {
138
138
  "type": "boolean"
139
139
  },
140
- "platform_editor_toolbar_aifc_user_intent_fix": {
141
- "type": "boolean"
142
- },
143
140
  "platform_editor_table_sticky_header_patch_6": {
144
141
  "type": "boolean"
145
142
  },