@atlaskit/editor-plugin-block-controls 7.5.5 → 7.5.7

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,21 @@
1
1
  # @atlaskit/editor-plugin-block-controls
2
2
 
3
+ ## 7.5.7
4
+
5
+ ### Patch Changes
6
+
7
+ - [`2dfcadf1c9593`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/2dfcadf1c9593) -
8
+ [ux] fix drag handle not appearing inside a panel/expand nested in a table
9
+ - Updated dependencies
10
+
11
+ ## 7.5.6
12
+
13
+ ### Patch Changes
14
+
15
+ - [`945cca63ae433`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/945cca63ae433) -
16
+ ED-29335: Fixed drop hints height not right for layout column inline drop targets
17
+ - Updated dependencies
18
+
3
19
  ## 7.5.5
4
20
 
5
21
  ### Patch Changes
@@ -11,6 +11,8 @@ var _uuid = _interopRequireDefault(require("uuid"));
11
11
  var _selection = require("@atlaskit/editor-common/selection");
12
12
  var _utils = require("@atlaskit/editor-common/utils");
13
13
  var _view = require("@atlaskit/editor-prosemirror/view");
14
+ var _platformFeatureFlags = require("@atlaskit/platform-feature-flags");
15
+ var _expValEquals = require("@atlaskit/tmp-editor-statsig/exp-val-equals");
14
16
  var _experiments = require("@atlaskit/tmp-editor-statsig/experiments");
15
17
  var _consts = require("../ui/consts");
16
18
  var _dropTarget = require("../ui/drop-target");
@@ -136,8 +138,9 @@ var createLayoutDropTargetDecoration = exports.createLayoutDropTargetDecoration
136
138
  element.setAttribute('data-blocks-drop-target-container', 'true');
137
139
  element.setAttribute('data-blocks-drop-target-key', key);
138
140
  element.style.clear = 'unset';
141
+ var DropTargetLayoutComponent = (0, _expValEquals.expValEquals)('platform_editor_native_anchor_support', 'isEnabled', true) && (0, _platformFeatureFlags.fg)('editor_native_anchor_update_layout_drop_hint') ? _dropTargetLayout.DropTargetLayoutNativeAnchorSupport : _dropTargetLayout.DropTargetLayout;
139
142
  nodeViewPortalProviderAPI.render(function () {
140
- return /*#__PURE__*/(0, _react.createElement)(_dropTargetLayout.DropTargetLayout, _objectSpread(_objectSpread({}, props), {}, {
143
+ return /*#__PURE__*/(0, _react.createElement)(DropTargetLayoutComponent, _objectSpread(_objectSpread({}, props), {}, {
141
144
  getPos: getPos,
142
145
  anchorRectCache: anchorRectCache
143
146
  }));
@@ -30,9 +30,13 @@ var getNodeSelector = function getNodeSelector(ignoreNodes, ignoreNodeDescendant
30
30
  return "[data-prosemirror-node-name=\"".concat(node, "\"]");
31
31
  });
32
32
  var ignoreNodeDescendantsSelectorList = ignoreNodeDescendants.map(function (node) {
33
+ if (node === 'table' && (0, _platformFeatureFlags.fg)('platform_editor_native_anchor_table_nested_fix')) {
34
+ // Special case for table to exclude its direct descendants
35
+ return ["[data-prosemirror-node-name=\"tableCell\"] > [data-node-anchor]", "[data-prosemirror-node-name=\"tableHeader\"] > [data-node-anchor]"];
36
+ }
33
37
  return "[data-prosemirror-node-name=\"".concat(node, "\"] [data-node-anchor]");
34
38
  });
35
- var ignoreSelector = [].concat((0, _toConsumableArray2.default)(ignoreNodeSelectorList), (0, _toConsumableArray2.default)(ignoreNodeDescendantsSelectorList), ['[data-prosemirror-node-inline="true"]']).join(', ');
39
+ var ignoreSelector = [].concat((0, _toConsumableArray2.default)(ignoreNodeSelectorList), (0, _toConsumableArray2.default)(ignoreNodeDescendantsSelectorList.flat()), ['[data-prosemirror-node-inline="true"]']).join(', ');
36
40
  return "".concat(baseSelector, ":not(").concat(ignoreSelector, ")");
37
41
  };
38
42
  var getDefaultNodeSelector = (0, _memoizeOne.default)(function () {
@@ -99,7 +99,7 @@ var buttonWrapperStylesPatch = (0, _react2.css)({
99
99
 
100
100
  // update color to match quick insert button for new editor controls
101
101
  var dragHandleColor = (0, _react2.css)({
102
- color: "var(--ds-icon-subtle, #626F86)"
102
+ color: "var(--ds-icon-subtle, #505258)"
103
103
  });
104
104
  var dragHandleButtonStyles = (0, _react2.css)({
105
105
  display: 'flex',
@@ -4,7 +4,7 @@ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefau
4
4
  Object.defineProperty(exports, "__esModule", {
5
5
  value: true
6
6
  });
7
- exports.DropTargetLayout = void 0;
7
+ exports.DropTargetLayoutNativeAnchorSupport = exports.DropTargetLayout = void 0;
8
8
  var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
9
9
  var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
10
10
  var _react = require("react");
@@ -130,9 +130,122 @@ var DropTargetLayout = exports.DropTargetLayout = function DropTargetLayout(prop
130
130
  edge: "right",
131
131
  gap: "-".concat(DROP_TARGET_LAYOUT_DROP_ZONE_WIDTH, "px")
132
132
  }) : (isActiveAnchor || (0, _expValEquals.expValEquals)('platform_editor_native_anchor_support', 'isEnabled', true)) && (0, _react2.jsx)("div", {
133
- "data-testid": "block-ctrl-drop-hint"
133
+ "data-testid": "block-ctrl-drop-hint",
134
+ css: dropTargetLayoutHintStyle
135
+ }));
136
+ };
137
+ var DropTargetLayoutNativeAnchorSupport = exports.DropTargetLayoutNativeAnchorSupport = function DropTargetLayoutNativeAnchorSupport(props) {
138
+ var _api$blockControls3;
139
+ var api = props.api,
140
+ getPos = props.getPos,
141
+ parent = props.parent,
142
+ anchorRectCache = props.anchorRectCache;
143
+ var ref = (0, _react.useRef)(null);
144
+ var _useState3 = (0, _react.useState)(false),
145
+ _useState4 = (0, _slicedToArray2.default)(_useState3, 2),
146
+ isDraggedOver = _useState4[0],
147
+ setIsDraggedOver = _useState4[1];
148
+ var anchorName = (0, _decorationsCommon.getNodeAnchor)(parent);
149
+ var _useState5 = (0, _react.useState)(null),
150
+ _useState6 = (0, _slicedToArray2.default)(_useState5, 2),
151
+ nextNodeAnchorName = _useState6[0],
152
+ setNextNodeAnchorName = _useState6[1];
153
+ var readNextNodeAnchor = (0, _react.useCallback)(function () {
154
+ var _ref$current2, _nextElementSibling$g;
155
+ var nextElementSibling = (_ref$current2 = ref.current) === null || _ref$current2 === void 0 || (_ref$current2 = _ref$current2.parentElement) === null || _ref$current2 === void 0 ? void 0 : _ref$current2.nextElementSibling;
156
+ var attrName = (0, _domAttrName.getAnchorAttrName)();
157
+ var nextAnchorName = (_nextElementSibling$g = nextElementSibling === null || nextElementSibling === void 0 ? void 0 : nextElementSibling.getAttribute(attrName)) !== null && _nextElementSibling$g !== void 0 ? _nextElementSibling$g : null;
158
+ setNextNodeAnchorName(function (prev) {
159
+ return prev === nextAnchorName ? prev : nextAnchorName;
160
+ });
161
+ }, []);
162
+ var height = (0, _react.useMemo)(function () {
163
+ if (nextNodeAnchorName) {
164
+ if ((0, _anchorUtils.isAnchorSupported)()) {
165
+ return "anchor-size(".concat(nextNodeAnchorName, " height)");
166
+ } else if (anchorRectCache) {
167
+ var layoutColumnRect = anchorRectCache.getRect(nextNodeAnchorName);
168
+ return "".concat((layoutColumnRect === null || layoutColumnRect === void 0 ? void 0 : layoutColumnRect.height) || 0, "px");
169
+ }
170
+ }
171
+ // Stacked mode fallback: minimal height to avoid oversized hint on first render
172
+ return '0px';
173
+ }, [nextNodeAnchorName, anchorRectCache]);
174
+ (0, _react.useLayoutEffect)(function () {
175
+ var raf = requestAnimationFrame(function () {
176
+ readNextNodeAnchor();
177
+ });
178
+ return function () {
179
+ return cancelAnimationFrame(raf);
180
+ };
181
+ }, [readNextNodeAnchor]);
182
+ var dropTargetStackLayoutHintStyle = (0, _react2.css)((0, _defineProperty2.default)({}, "@container layout-area (max-width:".concat(_editorSharedStyles.layoutBreakpointWidth.MEDIUM - 1, "px)"), {
183
+ // eslint-disable-next-line @atlaskit/ui-styling-standard/no-unsafe-values
184
+ height: height,
185
+ marginTop: "var(--ds-space-050, 4px)"
186
+ }));
187
+ var _useActiveAnchorTrack3 = (0, _activeAnchorTracker.useActiveAnchorTracker)(anchorName),
188
+ _useActiveAnchorTrack4 = (0, _slicedToArray2.default)(_useActiveAnchorTrack3, 1),
189
+ isActiveAnchor = _useActiveAnchorTrack4[0];
190
+ var _ref4 = (api === null || api === void 0 || (_api$blockControls3 = api.blockControls) === null || _api$blockControls3 === void 0 ? void 0 : _api$blockControls3.sharedState.currentState()) || {},
191
+ activeNode = _ref4.activeNode;
192
+ var onDrop = (0, _react.useCallback)(function () {
193
+ if (!activeNode) {
194
+ return;
195
+ }
196
+ var to = getPos();
197
+ var mappedTo;
198
+ if (to !== undefined) {
199
+ var _api$core3, _api$core4;
200
+ var from = activeNode.pos;
201
+ api === null || api === void 0 || (_api$core3 = api.core) === null || _api$core3 === void 0 || _api$core3.actions.execute(function (_ref5) {
202
+ var _api$blockControls4;
203
+ var tr = _ref5.tr;
204
+ api === null || api === void 0 || (_api$blockControls4 = api.blockControls) === null || _api$blockControls4 === void 0 || (_api$blockControls4 = _api$blockControls4.commands) === null || _api$blockControls4 === void 0 || _api$blockControls4.moveToLayout(from, to)({
205
+ tr: tr
206
+ });
207
+ var insertColumnStep = (0, _updateSelection.getInsertLayoutStep)(tr);
208
+ mappedTo = insertColumnStep === null || insertColumnStep === void 0 ? void 0 : insertColumnStep.from;
209
+ return tr;
210
+ });
211
+ api === null || api === void 0 || (_api$core4 = api.core) === null || _api$core4 === void 0 || _api$core4.actions.execute(function (_ref6) {
212
+ var tr = _ref6.tr;
213
+ if (mappedTo !== undefined) {
214
+ (0, _updateSelection.updateSelection)(tr, mappedTo);
215
+ }
216
+ return tr;
217
+ });
218
+ }
219
+ }, [api, getPos, activeNode]);
220
+ (0, _react.useEffect)(function () {
221
+ if (ref.current) {
222
+ return (0, _adapter.dropTargetForElements)({
223
+ element: ref.current,
224
+ onDragEnter: function onDragEnter() {
225
+ setIsDraggedOver(true);
226
+ readNextNodeAnchor();
227
+ },
228
+ onDragLeave: function onDragLeave() {
229
+ setIsDraggedOver(false);
230
+ },
231
+ onDrop: onDrop
232
+ });
233
+ }
234
+ }, [onDrop, readNextNodeAnchor]);
235
+ if ((activeNode === null || activeNode === void 0 ? void 0 : activeNode.nodeType) === 'layoutSection') {
236
+ return null;
237
+ }
238
+ return (0, _react2.jsx)("div", {
239
+ ref: ref
134
240
  // eslint-disable-next-line @atlaskit/design-system/consistent-css-prop-usage
135
241
  ,
242
+ css: [dropTargetLayoutStyle, dropTargetStackLayoutHintStyle],
243
+ "data-testid": "block-ctrl-drop-indicator"
244
+ }, isDraggedOver ? (0, _react2.jsx)(_box.DropIndicator, {
245
+ edge: "right",
246
+ gap: "-".concat(DROP_TARGET_LAYOUT_DROP_ZONE_WIDTH, "px")
247
+ }) : (isActiveAnchor || (0, _expValEquals.expValEquals)('platform_editor_native_anchor_support', 'isEnabled', true)) && (0, _react2.jsx)("div", {
248
+ "data-testid": "block-ctrl-drop-hint",
136
249
  css: dropTargetLayoutHintStyle
137
250
  }));
138
251
  };
@@ -256,7 +256,7 @@ var quickInsertStyles = function quickInsertStyles() {
256
256
  zIndex: _constants.layers.card(),
257
257
  outline: 'none',
258
258
  cursor: 'pointer',
259
- color: "var(--ds-icon-subtle, #626F86)"
259
+ color: "var(--ds-icon-subtle, #505258)"
260
260
  },
261
261
  // eslint-disable-next-line @atlaskit/ui-styling-standard/no-nested-selectors, @atlaskit/ui-styling-standard/no-unsafe-selectors
262
262
  '[data-blocks-quick-insert-container]:has(~ [data-prosemirror-node-name="table"] .pm-table-with-controls tr.sticky) &': {
@@ -270,11 +270,11 @@ var quickInsertStyles = function quickInsertStyles() {
270
270
  },
271
271
  // eslint-disable-next-line @atlaskit/ui-styling-standard/no-nested-selectors
272
272
  '.blocks-quick-insert-button:hover': {
273
- backgroundColor: "var(--ds-background-neutral-subtle-hovered, #091E420F)"
273
+ backgroundColor: "var(--ds-background-neutral-subtle-hovered, #0515240F)"
274
274
  },
275
275
  // eslint-disable-next-line @atlaskit/ui-styling-standard/no-nested-selectors
276
276
  '.blocks-quick-insert-button:active': {
277
- backgroundColor: "var(--ds-background-neutral-subtle-pressed, #091E4224)"
277
+ backgroundColor: "var(--ds-background-neutral-subtle-pressed, #0B120E24)"
278
278
  },
279
279
  // eslint-disable-next-line @atlaskit/ui-styling-standard/no-nested-selectors
280
280
  '.blocks-quick-insert-button:focus': {
@@ -299,7 +299,7 @@ var quickInsertStyles = function quickInsertStyles() {
299
299
  padding: "var(--ds-space-050, 4px)".concat(" 0"),
300
300
  boxSizing: 'border-box',
301
301
  maxWidth: '240px',
302
- backgroundColor: "var(--ds-background-neutral-bold, #44546F)",
302
+ backgroundColor: "var(--ds-background-neutral-bold, #292A2E)",
303
303
  color: "var(--ds-text-inverse, #FFFFFF)",
304
304
  font: "var(--ds-font-body-UNSAFE_small, normal 400 12px/16px ui-sans-serif, -apple-system, BlinkMacSystemFont, \"Segoe UI\", Ubuntu, \"Helvetica Neue\", sans-serif)",
305
305
  insetBlockStart: "var(--ds-space-0, 0px)",
@@ -296,7 +296,7 @@ var TypeAheadControl = exports.TypeAheadControl = function TypeAheadControl(_ref
296
296
  onMouseDown: handleMouseDown
297
297
  }, (0, _react2.jsx)(_add.default, {
298
298
  label: "add",
299
- color: "var(--ds-icon-subtle, #626F86)",
299
+ color: "var(--ds-icon-subtle, #505258)",
300
300
  size: "small"
301
301
  })));
302
302
  };
@@ -4,10 +4,12 @@ import uuid from 'uuid';
4
4
  import { expandSelectionBounds } from '@atlaskit/editor-common/selection';
5
5
  import { isEmptyParagraph } from '@atlaskit/editor-common/utils';
6
6
  import { Decoration } from '@atlaskit/editor-prosemirror/view';
7
+ import { fg } from '@atlaskit/platform-feature-flags';
8
+ import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
7
9
  import { editorExperiment } from '@atlaskit/tmp-editor-statsig/experiments';
8
10
  import { nodeMargins } from '../ui/consts';
9
11
  import { DropTarget, EDITOR_BLOCK_CONTROLS_DROP_INDICATOR_GAP, EDITOR_BLOCK_CONTROLS_DROP_INDICATOR_OFFSET } from '../ui/drop-target';
10
- import { DropTargetLayout } from '../ui/drop-target-layout';
12
+ import { DropTargetLayout, DropTargetLayoutNativeAnchorSupport } from '../ui/drop-target-layout';
11
13
  import { NESTED_DEPTH, TYPE_DROP_TARGET_DEC } from './decorations-common';
12
14
  import { maxLayoutColumnSupported } from './utils/consts';
13
15
  import { canMoveNodeToIndex, canMoveSliceToIndex, isInSameLayout } from './utils/validation';
@@ -125,7 +127,8 @@ export const createLayoutDropTargetDecoration = (pos, props, nodeViewPortalProvi
125
127
  element.setAttribute('data-blocks-drop-target-container', 'true');
126
128
  element.setAttribute('data-blocks-drop-target-key', key);
127
129
  element.style.clear = 'unset';
128
- nodeViewPortalProviderAPI.render(() => /*#__PURE__*/createElement(DropTargetLayout, {
130
+ const DropTargetLayoutComponent = expValEquals('platform_editor_native_anchor_support', 'isEnabled', true) && fg('editor_native_anchor_update_layout_drop_hint') ? DropTargetLayoutNativeAnchorSupport : DropTargetLayout;
131
+ nodeViewPortalProviderAPI.render(() => /*#__PURE__*/createElement(DropTargetLayoutComponent, {
129
132
  ...props,
130
133
  getPos,
131
134
  anchorRectCache
@@ -19,8 +19,14 @@ const getNodeSelector = (ignoreNodes, ignoreNodeDescendants) => {
19
19
  return baseSelector;
20
20
  }
21
21
  const ignoreNodeSelectorList = ignoreNodes.map(node => `[data-prosemirror-node-name="${node}"]`);
22
- const ignoreNodeDescendantsSelectorList = ignoreNodeDescendants.map(node => `[data-prosemirror-node-name="${node}"] [data-node-anchor]`);
23
- const ignoreSelector = [...ignoreNodeSelectorList, ...ignoreNodeDescendantsSelectorList, '[data-prosemirror-node-inline="true"]'].join(', ');
22
+ const ignoreNodeDescendantsSelectorList = ignoreNodeDescendants.map(node => {
23
+ if (node === 'table' && fg('platform_editor_native_anchor_table_nested_fix')) {
24
+ // Special case for table to exclude its direct descendants
25
+ return [`[data-prosemirror-node-name="tableCell"] > [data-node-anchor]`, `[data-prosemirror-node-name="tableHeader"] > [data-node-anchor]`];
26
+ }
27
+ return `[data-prosemirror-node-name="${node}"] [data-node-anchor]`;
28
+ });
29
+ const ignoreSelector = [...ignoreNodeSelectorList, ...ignoreNodeDescendantsSelectorList.flat(), '[data-prosemirror-node-inline="true"]'].join(', ');
24
30
  return `${baseSelector}:not(${ignoreSelector})`;
25
31
  };
26
32
  const getDefaultNodeSelector = memoizeOne(() => {
@@ -91,7 +91,7 @@ const buttonWrapperStylesPatch = css({
91
91
 
92
92
  // update color to match quick insert button for new editor controls
93
93
  const dragHandleColor = css({
94
- color: "var(--ds-icon-subtle, #626F86)"
94
+ color: "var(--ds-icon-subtle, #505258)"
95
95
  });
96
96
  const dragHandleButtonStyles = css({
97
97
  display: 'flex',
@@ -2,7 +2,7 @@
2
2
  * @jsxRuntime classic
3
3
  * @jsx jsx
4
4
  */
5
- import { useCallback, useEffect, useRef, useState } from 'react';
5
+ import { useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState } from 'react';
6
6
 
7
7
  // eslint-disable-next-line @atlaskit/ui-styling-standard/use-compiled
8
8
  import { css, jsx } from '@emotion/react';
@@ -127,9 +127,121 @@ export const DropTargetLayout = props => {
127
127
  edge: "right",
128
128
  gap: `-${DROP_TARGET_LAYOUT_DROP_ZONE_WIDTH}px`
129
129
  }) : (isActiveAnchor || expValEquals('platform_editor_native_anchor_support', 'isEnabled', true)) && jsx("div", {
130
- "data-testid": "block-ctrl-drop-hint"
130
+ "data-testid": "block-ctrl-drop-hint",
131
+ css: dropTargetLayoutHintStyle
132
+ }));
133
+ };
134
+ export const DropTargetLayoutNativeAnchorSupport = props => {
135
+ var _api$blockControls3;
136
+ const {
137
+ api,
138
+ getPos,
139
+ parent,
140
+ anchorRectCache
141
+ } = props;
142
+ const ref = useRef(null);
143
+ const [isDraggedOver, setIsDraggedOver] = useState(false);
144
+ const anchorName = getNodeAnchor(parent);
145
+ const [nextNodeAnchorName, setNextNodeAnchorName] = useState(null);
146
+ const readNextNodeAnchor = useCallback(() => {
147
+ var _ref$current2, _ref$current2$parentE, _nextElementSibling$g;
148
+ const nextElementSibling = (_ref$current2 = ref.current) === null || _ref$current2 === void 0 ? void 0 : (_ref$current2$parentE = _ref$current2.parentElement) === null || _ref$current2$parentE === void 0 ? void 0 : _ref$current2$parentE.nextElementSibling;
149
+ const attrName = getAnchorAttrName();
150
+ const nextAnchorName = (_nextElementSibling$g = nextElementSibling === null || nextElementSibling === void 0 ? void 0 : nextElementSibling.getAttribute(attrName)) !== null && _nextElementSibling$g !== void 0 ? _nextElementSibling$g : null;
151
+ setNextNodeAnchorName(prev => prev === nextAnchorName ? prev : nextAnchorName);
152
+ }, []);
153
+ const height = useMemo(() => {
154
+ if (nextNodeAnchorName) {
155
+ if (isAnchorSupported()) {
156
+ return `anchor-size(${nextNodeAnchorName} height)`;
157
+ } else if (anchorRectCache) {
158
+ const layoutColumnRect = anchorRectCache.getRect(nextNodeAnchorName);
159
+ return `${(layoutColumnRect === null || layoutColumnRect === void 0 ? void 0 : layoutColumnRect.height) || 0}px`;
160
+ }
161
+ }
162
+ // Stacked mode fallback: minimal height to avoid oversized hint on first render
163
+ return '0px';
164
+ }, [nextNodeAnchorName, anchorRectCache]);
165
+ useLayoutEffect(() => {
166
+ const raf = requestAnimationFrame(() => {
167
+ readNextNodeAnchor();
168
+ });
169
+ return () => cancelAnimationFrame(raf);
170
+ }, [readNextNodeAnchor]);
171
+ const dropTargetStackLayoutHintStyle = css({
172
+ // jest warning: JSDOM version (22) doesn't support the new @container CSS rule
173
+ // eslint-disable-next-line @atlaskit/ui-styling-standard/no-container-queries, @atlaskit/ui-styling-standard/no-unsafe-values, @atlaskit/ui-styling-standard/no-imported-style-values
174
+ [`@container layout-area (max-width:${layoutBreakpointWidth.MEDIUM - 1}px)`]: {
175
+ // eslint-disable-next-line @atlaskit/ui-styling-standard/no-unsafe-values
176
+ height,
177
+ marginTop: `${"var(--ds-space-050, 4px)"}`
178
+ }
179
+ });
180
+ const [isActiveAnchor] = useActiveAnchorTracker(anchorName);
181
+ const {
182
+ activeNode
183
+ } = (api === null || api === void 0 ? void 0 : (_api$blockControls3 = api.blockControls) === null || _api$blockControls3 === void 0 ? void 0 : _api$blockControls3.sharedState.currentState()) || {};
184
+ const onDrop = useCallback(() => {
185
+ if (!activeNode) {
186
+ return;
187
+ }
188
+ const to = getPos();
189
+ let mappedTo;
190
+ if (to !== undefined) {
191
+ var _api$core3, _api$core4;
192
+ const {
193
+ pos: from
194
+ } = activeNode;
195
+ api === null || api === void 0 ? void 0 : (_api$core3 = api.core) === null || _api$core3 === void 0 ? void 0 : _api$core3.actions.execute(({
196
+ tr
197
+ }) => {
198
+ var _api$blockControls4, _api$blockControls4$c;
199
+ api === null || api === void 0 ? void 0 : (_api$blockControls4 = api.blockControls) === null || _api$blockControls4 === void 0 ? void 0 : (_api$blockControls4$c = _api$blockControls4.commands) === null || _api$blockControls4$c === void 0 ? void 0 : _api$blockControls4$c.moveToLayout(from, to)({
200
+ tr
201
+ });
202
+ const insertColumnStep = getInsertLayoutStep(tr);
203
+ mappedTo = insertColumnStep === null || insertColumnStep === void 0 ? void 0 : insertColumnStep.from;
204
+ return tr;
205
+ });
206
+ api === null || api === void 0 ? void 0 : (_api$core4 = api.core) === null || _api$core4 === void 0 ? void 0 : _api$core4.actions.execute(({
207
+ tr
208
+ }) => {
209
+ if (mappedTo !== undefined) {
210
+ updateSelection(tr, mappedTo);
211
+ }
212
+ return tr;
213
+ });
214
+ }
215
+ }, [api, getPos, activeNode]);
216
+ useEffect(() => {
217
+ if (ref.current) {
218
+ return dropTargetForElements({
219
+ element: ref.current,
220
+ onDragEnter: () => {
221
+ setIsDraggedOver(true);
222
+ readNextNodeAnchor();
223
+ },
224
+ onDragLeave: () => {
225
+ setIsDraggedOver(false);
226
+ },
227
+ onDrop
228
+ });
229
+ }
230
+ }, [onDrop, readNextNodeAnchor]);
231
+ if ((activeNode === null || activeNode === void 0 ? void 0 : activeNode.nodeType) === 'layoutSection') {
232
+ return null;
233
+ }
234
+ return jsx("div", {
235
+ ref: ref
131
236
  // eslint-disable-next-line @atlaskit/design-system/consistent-css-prop-usage
132
237
  ,
238
+ css: [dropTargetLayoutStyle, dropTargetStackLayoutHintStyle],
239
+ "data-testid": "block-ctrl-drop-indicator"
240
+ }, isDraggedOver ? jsx(DropIndicator, {
241
+ edge: "right",
242
+ gap: `-${DROP_TARGET_LAYOUT_DROP_ZONE_WIDTH}px`
243
+ }) : (isActiveAnchor || expValEquals('platform_editor_native_anchor_support', 'isEnabled', true)) && jsx("div", {
244
+ "data-testid": "block-ctrl-drop-hint",
133
245
  css: dropTargetLayoutHintStyle
134
246
  }));
135
247
  };
@@ -307,7 +307,7 @@ const quickInsertStyles = () => css({
307
307
  zIndex: layers.card(),
308
308
  outline: 'none',
309
309
  cursor: 'pointer',
310
- color: "var(--ds-icon-subtle, #626F86)"
310
+ color: "var(--ds-icon-subtle, #505258)"
311
311
  },
312
312
  // eslint-disable-next-line @atlaskit/ui-styling-standard/no-nested-selectors, @atlaskit/ui-styling-standard/no-unsafe-selectors
313
313
  '[data-blocks-quick-insert-container]:has(~ [data-prosemirror-node-name="table"] .pm-table-with-controls tr.sticky) &': {
@@ -321,11 +321,11 @@ const quickInsertStyles = () => css({
321
321
  },
322
322
  // eslint-disable-next-line @atlaskit/ui-styling-standard/no-nested-selectors
323
323
  '.blocks-quick-insert-button:hover': {
324
- backgroundColor: "var(--ds-background-neutral-subtle-hovered, #091E420F)"
324
+ backgroundColor: "var(--ds-background-neutral-subtle-hovered, #0515240F)"
325
325
  },
326
326
  // eslint-disable-next-line @atlaskit/ui-styling-standard/no-nested-selectors
327
327
  '.blocks-quick-insert-button:active': {
328
- backgroundColor: "var(--ds-background-neutral-subtle-pressed, #091E4224)"
328
+ backgroundColor: "var(--ds-background-neutral-subtle-pressed, #0B120E24)"
329
329
  },
330
330
  // eslint-disable-next-line @atlaskit/ui-styling-standard/no-nested-selectors
331
331
  '.blocks-quick-insert-button:focus': {
@@ -350,7 +350,7 @@ const quickInsertStyles = () => css({
350
350
  padding: `${"var(--ds-space-050, 4px)"} 0`,
351
351
  boxSizing: 'border-box',
352
352
  maxWidth: '240px',
353
- backgroundColor: "var(--ds-background-neutral-bold, #44546F)",
353
+ backgroundColor: "var(--ds-background-neutral-bold, #292A2E)",
354
354
  color: "var(--ds-text-inverse, #FFFFFF)",
355
355
  font: "var(--ds-font-body-UNSAFE_small, normal 400 12px/16px ui-sans-serif, -apple-system, BlinkMacSystemFont, \"Segoe UI\", Ubuntu, \"Helvetica Neue\", sans-serif)",
356
356
  insetBlockStart: "var(--ds-space-0, 0px)",
@@ -291,7 +291,7 @@ export const TypeAheadControl = ({
291
291
  onMouseDown: handleMouseDown
292
292
  }, jsx(AddIcon, {
293
293
  label: "add",
294
- color: "var(--ds-icon-subtle, #626F86)",
294
+ color: "var(--ds-icon-subtle, #505258)",
295
295
  size: "small"
296
296
  })));
297
297
  return jsx(Box
@@ -7,10 +7,12 @@ import uuid from 'uuid';
7
7
  import { expandSelectionBounds } from '@atlaskit/editor-common/selection';
8
8
  import { isEmptyParagraph } from '@atlaskit/editor-common/utils';
9
9
  import { Decoration } from '@atlaskit/editor-prosemirror/view';
10
+ import { fg } from '@atlaskit/platform-feature-flags';
11
+ import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
10
12
  import { editorExperiment } from '@atlaskit/tmp-editor-statsig/experiments';
11
13
  import { nodeMargins } from '../ui/consts';
12
14
  import { DropTarget, EDITOR_BLOCK_CONTROLS_DROP_INDICATOR_GAP, EDITOR_BLOCK_CONTROLS_DROP_INDICATOR_OFFSET } from '../ui/drop-target';
13
- import { DropTargetLayout } from '../ui/drop-target-layout';
15
+ import { DropTargetLayout, DropTargetLayoutNativeAnchorSupport } from '../ui/drop-target-layout';
14
16
  import { NESTED_DEPTH, TYPE_DROP_TARGET_DEC } from './decorations-common';
15
17
  import { maxLayoutColumnSupported } from './utils/consts';
16
18
  import { canMoveNodeToIndex, canMoveSliceToIndex, isInSameLayout } from './utils/validation';
@@ -130,8 +132,9 @@ export var createLayoutDropTargetDecoration = function createLayoutDropTargetDec
130
132
  element.setAttribute('data-blocks-drop-target-container', 'true');
131
133
  element.setAttribute('data-blocks-drop-target-key', key);
132
134
  element.style.clear = 'unset';
135
+ var DropTargetLayoutComponent = expValEquals('platform_editor_native_anchor_support', 'isEnabled', true) && fg('editor_native_anchor_update_layout_drop_hint') ? DropTargetLayoutNativeAnchorSupport : DropTargetLayout;
133
136
  nodeViewPortalProviderAPI.render(function () {
134
- return /*#__PURE__*/createElement(DropTargetLayout, _objectSpread(_objectSpread({}, props), {}, {
137
+ return /*#__PURE__*/createElement(DropTargetLayoutComponent, _objectSpread(_objectSpread({}, props), {}, {
135
138
  getPos: getPos,
136
139
  anchorRectCache: anchorRectCache
137
140
  }));
@@ -23,9 +23,13 @@ var getNodeSelector = function getNodeSelector(ignoreNodes, ignoreNodeDescendant
23
23
  return "[data-prosemirror-node-name=\"".concat(node, "\"]");
24
24
  });
25
25
  var ignoreNodeDescendantsSelectorList = ignoreNodeDescendants.map(function (node) {
26
+ if (node === 'table' && fg('platform_editor_native_anchor_table_nested_fix')) {
27
+ // Special case for table to exclude its direct descendants
28
+ return ["[data-prosemirror-node-name=\"tableCell\"] > [data-node-anchor]", "[data-prosemirror-node-name=\"tableHeader\"] > [data-node-anchor]"];
29
+ }
26
30
  return "[data-prosemirror-node-name=\"".concat(node, "\"] [data-node-anchor]");
27
31
  });
28
- var ignoreSelector = [].concat(_toConsumableArray(ignoreNodeSelectorList), _toConsumableArray(ignoreNodeDescendantsSelectorList), ['[data-prosemirror-node-inline="true"]']).join(', ');
32
+ var ignoreSelector = [].concat(_toConsumableArray(ignoreNodeSelectorList), _toConsumableArray(ignoreNodeDescendantsSelectorList.flat()), ['[data-prosemirror-node-inline="true"]']).join(', ');
29
33
  return "".concat(baseSelector, ":not(").concat(ignoreSelector, ")");
30
34
  };
31
35
  var getDefaultNodeSelector = memoizeOne(function () {
@@ -96,7 +96,7 @@ var buttonWrapperStylesPatch = css({
96
96
 
97
97
  // update color to match quick insert button for new editor controls
98
98
  var dragHandleColor = css({
99
- color: "var(--ds-icon-subtle, #626F86)"
99
+ color: "var(--ds-icon-subtle, #505258)"
100
100
  });
101
101
  var dragHandleButtonStyles = css({
102
102
  display: 'flex',
@@ -4,7 +4,7 @@ import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
4
4
  * @jsxRuntime classic
5
5
  * @jsx jsx
6
6
  */
7
- import { useCallback, useEffect, useRef, useState } from 'react';
7
+ import { useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState } from 'react';
8
8
 
9
9
  // eslint-disable-next-line @atlaskit/ui-styling-standard/use-compiled
10
10
  import { css, jsx } from '@emotion/react';
@@ -123,9 +123,122 @@ export var DropTargetLayout = function DropTargetLayout(props) {
123
123
  edge: "right",
124
124
  gap: "-".concat(DROP_TARGET_LAYOUT_DROP_ZONE_WIDTH, "px")
125
125
  }) : (isActiveAnchor || expValEquals('platform_editor_native_anchor_support', 'isEnabled', true)) && jsx("div", {
126
- "data-testid": "block-ctrl-drop-hint"
126
+ "data-testid": "block-ctrl-drop-hint",
127
+ css: dropTargetLayoutHintStyle
128
+ }));
129
+ };
130
+ export var DropTargetLayoutNativeAnchorSupport = function DropTargetLayoutNativeAnchorSupport(props) {
131
+ var _api$blockControls3;
132
+ var api = props.api,
133
+ getPos = props.getPos,
134
+ parent = props.parent,
135
+ anchorRectCache = props.anchorRectCache;
136
+ var ref = useRef(null);
137
+ var _useState3 = useState(false),
138
+ _useState4 = _slicedToArray(_useState3, 2),
139
+ isDraggedOver = _useState4[0],
140
+ setIsDraggedOver = _useState4[1];
141
+ var anchorName = getNodeAnchor(parent);
142
+ var _useState5 = useState(null),
143
+ _useState6 = _slicedToArray(_useState5, 2),
144
+ nextNodeAnchorName = _useState6[0],
145
+ setNextNodeAnchorName = _useState6[1];
146
+ var readNextNodeAnchor = useCallback(function () {
147
+ var _ref$current2, _nextElementSibling$g;
148
+ var nextElementSibling = (_ref$current2 = ref.current) === null || _ref$current2 === void 0 || (_ref$current2 = _ref$current2.parentElement) === null || _ref$current2 === void 0 ? void 0 : _ref$current2.nextElementSibling;
149
+ var attrName = getAnchorAttrName();
150
+ var nextAnchorName = (_nextElementSibling$g = nextElementSibling === null || nextElementSibling === void 0 ? void 0 : nextElementSibling.getAttribute(attrName)) !== null && _nextElementSibling$g !== void 0 ? _nextElementSibling$g : null;
151
+ setNextNodeAnchorName(function (prev) {
152
+ return prev === nextAnchorName ? prev : nextAnchorName;
153
+ });
154
+ }, []);
155
+ var height = useMemo(function () {
156
+ if (nextNodeAnchorName) {
157
+ if (isAnchorSupported()) {
158
+ return "anchor-size(".concat(nextNodeAnchorName, " height)");
159
+ } else if (anchorRectCache) {
160
+ var layoutColumnRect = anchorRectCache.getRect(nextNodeAnchorName);
161
+ return "".concat((layoutColumnRect === null || layoutColumnRect === void 0 ? void 0 : layoutColumnRect.height) || 0, "px");
162
+ }
163
+ }
164
+ // Stacked mode fallback: minimal height to avoid oversized hint on first render
165
+ return '0px';
166
+ }, [nextNodeAnchorName, anchorRectCache]);
167
+ useLayoutEffect(function () {
168
+ var raf = requestAnimationFrame(function () {
169
+ readNextNodeAnchor();
170
+ });
171
+ return function () {
172
+ return cancelAnimationFrame(raf);
173
+ };
174
+ }, [readNextNodeAnchor]);
175
+ var dropTargetStackLayoutHintStyle = css(_defineProperty({}, "@container layout-area (max-width:".concat(layoutBreakpointWidth.MEDIUM - 1, "px)"), {
176
+ // eslint-disable-next-line @atlaskit/ui-styling-standard/no-unsafe-values
177
+ height: height,
178
+ marginTop: "var(--ds-space-050, 4px)"
179
+ }));
180
+ var _useActiveAnchorTrack3 = useActiveAnchorTracker(anchorName),
181
+ _useActiveAnchorTrack4 = _slicedToArray(_useActiveAnchorTrack3, 1),
182
+ isActiveAnchor = _useActiveAnchorTrack4[0];
183
+ var _ref4 = (api === null || api === void 0 || (_api$blockControls3 = api.blockControls) === null || _api$blockControls3 === void 0 ? void 0 : _api$blockControls3.sharedState.currentState()) || {},
184
+ activeNode = _ref4.activeNode;
185
+ var onDrop = useCallback(function () {
186
+ if (!activeNode) {
187
+ return;
188
+ }
189
+ var to = getPos();
190
+ var mappedTo;
191
+ if (to !== undefined) {
192
+ var _api$core3, _api$core4;
193
+ var from = activeNode.pos;
194
+ api === null || api === void 0 || (_api$core3 = api.core) === null || _api$core3 === void 0 || _api$core3.actions.execute(function (_ref5) {
195
+ var _api$blockControls4;
196
+ var tr = _ref5.tr;
197
+ api === null || api === void 0 || (_api$blockControls4 = api.blockControls) === null || _api$blockControls4 === void 0 || (_api$blockControls4 = _api$blockControls4.commands) === null || _api$blockControls4 === void 0 || _api$blockControls4.moveToLayout(from, to)({
198
+ tr: tr
199
+ });
200
+ var insertColumnStep = getInsertLayoutStep(tr);
201
+ mappedTo = insertColumnStep === null || insertColumnStep === void 0 ? void 0 : insertColumnStep.from;
202
+ return tr;
203
+ });
204
+ api === null || api === void 0 || (_api$core4 = api.core) === null || _api$core4 === void 0 || _api$core4.actions.execute(function (_ref6) {
205
+ var tr = _ref6.tr;
206
+ if (mappedTo !== undefined) {
207
+ updateSelection(tr, mappedTo);
208
+ }
209
+ return tr;
210
+ });
211
+ }
212
+ }, [api, getPos, activeNode]);
213
+ useEffect(function () {
214
+ if (ref.current) {
215
+ return dropTargetForElements({
216
+ element: ref.current,
217
+ onDragEnter: function onDragEnter() {
218
+ setIsDraggedOver(true);
219
+ readNextNodeAnchor();
220
+ },
221
+ onDragLeave: function onDragLeave() {
222
+ setIsDraggedOver(false);
223
+ },
224
+ onDrop: onDrop
225
+ });
226
+ }
227
+ }, [onDrop, readNextNodeAnchor]);
228
+ if ((activeNode === null || activeNode === void 0 ? void 0 : activeNode.nodeType) === 'layoutSection') {
229
+ return null;
230
+ }
231
+ return jsx("div", {
232
+ ref: ref
127
233
  // eslint-disable-next-line @atlaskit/design-system/consistent-css-prop-usage
128
234
  ,
235
+ css: [dropTargetLayoutStyle, dropTargetStackLayoutHintStyle],
236
+ "data-testid": "block-ctrl-drop-indicator"
237
+ }, isDraggedOver ? jsx(DropIndicator, {
238
+ edge: "right",
239
+ gap: "-".concat(DROP_TARGET_LAYOUT_DROP_ZONE_WIDTH, "px")
240
+ }) : (isActiveAnchor || expValEquals('platform_editor_native_anchor_support', 'isEnabled', true)) && jsx("div", {
241
+ "data-testid": "block-ctrl-drop-hint",
129
242
  css: dropTargetLayoutHintStyle
130
243
  }));
131
244
  };
@@ -249,7 +249,7 @@ var quickInsertStyles = function quickInsertStyles() {
249
249
  zIndex: layers.card(),
250
250
  outline: 'none',
251
251
  cursor: 'pointer',
252
- color: "var(--ds-icon-subtle, #626F86)"
252
+ color: "var(--ds-icon-subtle, #505258)"
253
253
  },
254
254
  // eslint-disable-next-line @atlaskit/ui-styling-standard/no-nested-selectors, @atlaskit/ui-styling-standard/no-unsafe-selectors
255
255
  '[data-blocks-quick-insert-container]:has(~ [data-prosemirror-node-name="table"] .pm-table-with-controls tr.sticky) &': {
@@ -263,11 +263,11 @@ var quickInsertStyles = function quickInsertStyles() {
263
263
  },
264
264
  // eslint-disable-next-line @atlaskit/ui-styling-standard/no-nested-selectors
265
265
  '.blocks-quick-insert-button:hover': {
266
- backgroundColor: "var(--ds-background-neutral-subtle-hovered, #091E420F)"
266
+ backgroundColor: "var(--ds-background-neutral-subtle-hovered, #0515240F)"
267
267
  },
268
268
  // eslint-disable-next-line @atlaskit/ui-styling-standard/no-nested-selectors
269
269
  '.blocks-quick-insert-button:active': {
270
- backgroundColor: "var(--ds-background-neutral-subtle-pressed, #091E4224)"
270
+ backgroundColor: "var(--ds-background-neutral-subtle-pressed, #0B120E24)"
271
271
  },
272
272
  // eslint-disable-next-line @atlaskit/ui-styling-standard/no-nested-selectors
273
273
  '.blocks-quick-insert-button:focus': {
@@ -292,7 +292,7 @@ var quickInsertStyles = function quickInsertStyles() {
292
292
  padding: "var(--ds-space-050, 4px)".concat(" 0"),
293
293
  boxSizing: 'border-box',
294
294
  maxWidth: '240px',
295
- backgroundColor: "var(--ds-background-neutral-bold, #44546F)",
295
+ backgroundColor: "var(--ds-background-neutral-bold, #292A2E)",
296
296
  color: "var(--ds-text-inverse, #FFFFFF)",
297
297
  font: "var(--ds-font-body-UNSAFE_small, normal 400 12px/16px ui-sans-serif, -apple-system, BlinkMacSystemFont, \"Segoe UI\", Ubuntu, \"Helvetica Neue\", sans-serif)",
298
298
  insetBlockStart: "var(--ds-space-0, 0px)",
@@ -291,7 +291,7 @@ export var TypeAheadControl = function TypeAheadControl(_ref) {
291
291
  onMouseDown: handleMouseDown
292
292
  }, jsx(AddIcon, {
293
293
  label: "add",
294
- color: "var(--ds-icon-subtle, #626F86)",
294
+ color: "var(--ds-icon-subtle, #505258)",
295
295
  size: "small"
296
296
  })));
297
297
  };
@@ -13,3 +13,6 @@ export type DropTargetLayoutProps = {
13
13
  export declare const DropTargetLayout: (props: DropTargetLayoutProps & {
14
14
  anchorRectCache?: AnchorRectCache;
15
15
  }) => jsx.JSX.Element | null;
16
+ export declare const DropTargetLayoutNativeAnchorSupport: (props: DropTargetLayoutProps & {
17
+ anchorRectCache?: AnchorRectCache;
18
+ }) => jsx.JSX.Element | null;
@@ -13,3 +13,6 @@ export type DropTargetLayoutProps = {
13
13
  export declare const DropTargetLayout: (props: DropTargetLayoutProps & {
14
14
  anchorRectCache?: AnchorRectCache;
15
15
  }) => jsx.JSX.Element | null;
16
+ export declare const DropTargetLayoutNativeAnchorSupport: (props: DropTargetLayoutProps & {
17
+ anchorRectCache?: AnchorRectCache;
18
+ }) => jsx.JSX.Element | null;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atlaskit/editor-plugin-block-controls",
3
- "version": "7.5.5",
3
+ "version": "7.5.7",
4
4
  "description": "Block controls plugin for @atlaskit/editor-core",
5
5
  "author": "Atlassian Pty Ltd",
6
6
  "license": "Apache-2.0",
@@ -33,7 +33,7 @@
33
33
  "@atlaskit/editor-plugin-analytics": "^6.2.0",
34
34
  "@atlaskit/editor-plugin-editor-disabled": "^6.1.0",
35
35
  "@atlaskit/editor-plugin-feature-flags": "^5.0.0",
36
- "@atlaskit/editor-plugin-interaction": "^9.0.0",
36
+ "@atlaskit/editor-plugin-interaction": "^10.0.0",
37
37
  "@atlaskit/editor-plugin-limited-mode": "^3.1.0",
38
38
  "@atlaskit/editor-plugin-metrics": "^7.1.0",
39
39
  "@atlaskit/editor-plugin-quick-insert": "^6.0.0",
@@ -53,9 +53,9 @@
53
53
  "@atlaskit/pragmatic-drag-and-drop-react-drop-indicator": "^3.2.0",
54
54
  "@atlaskit/primitives": "^16.1.0",
55
55
  "@atlaskit/theme": "^21.0.0",
56
- "@atlaskit/tmp-editor-statsig": "^13.31.0",
57
- "@atlaskit/tokens": "^7.1.0",
58
- "@atlaskit/tooltip": "^20.7.0",
56
+ "@atlaskit/tmp-editor-statsig": "^13.32.0",
57
+ "@atlaskit/tokens": "^8.0.0",
58
+ "@atlaskit/tooltip": "^20.8.0",
59
59
  "@babel/runtime": "^7.0.0",
60
60
  "@emotion/react": "^11.7.1",
61
61
  "@popperjs/core": "^2.11.8",
@@ -156,6 +156,12 @@
156
156
  },
157
157
  "platform_editor_toolbar_aifc_user_intent_fix": {
158
158
  "type": "boolean"
159
+ },
160
+ "platform_editor_native_anchor_table_nested_fix": {
161
+ "type": "boolean"
162
+ },
163
+ "editor_native_anchor_update_layout_drop_hint": {
164
+ "type": "boolean"
159
165
  }
160
166
  }
161
167
  }