@atlaskit/editor-plugin-block-controls 3.1.2 → 3.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/CHANGELOG.md +9 -0
  2. package/dist/cjs/blockControlsPlugin.js +15 -9
  3. package/dist/cjs/pm-plugins/decorations-quick-insert-button.js +40 -0
  4. package/dist/cjs/pm-plugins/handle-mouse-over.js +24 -5
  5. package/dist/cjs/pm-plugins/main.js +35 -6
  6. package/dist/cjs/pm-plugins/utils/widget-positions.js +25 -0
  7. package/dist/cjs/ui/block-menu.js +7 -4
  8. package/dist/cjs/ui/consts.js +18 -1
  9. package/dist/cjs/ui/drag-handle.js +5 -2
  10. package/dist/cjs/ui/quick-insert-button.js +164 -0
  11. package/dist/es2019/blockControlsPlugin.js +15 -9
  12. package/dist/es2019/pm-plugins/decorations-quick-insert-button.js +29 -0
  13. package/dist/es2019/pm-plugins/handle-mouse-over.js +24 -5
  14. package/dist/es2019/pm-plugins/main.js +35 -7
  15. package/dist/es2019/pm-plugins/utils/widget-positions.js +20 -0
  16. package/dist/es2019/ui/block-menu.js +7 -4
  17. package/dist/es2019/ui/consts.js +17 -0
  18. package/dist/es2019/ui/drag-handle.js +5 -2
  19. package/dist/es2019/ui/quick-insert-button.js +152 -0
  20. package/dist/esm/blockControlsPlugin.js +15 -9
  21. package/dist/esm/pm-plugins/decorations-quick-insert-button.js +33 -0
  22. package/dist/esm/pm-plugins/handle-mouse-over.js +24 -5
  23. package/dist/esm/pm-plugins/main.js +35 -6
  24. package/dist/esm/pm-plugins/utils/widget-positions.js +20 -0
  25. package/dist/esm/ui/block-menu.js +7 -4
  26. package/dist/esm/ui/consts.js +17 -0
  27. package/dist/esm/ui/drag-handle.js +5 -2
  28. package/dist/esm/ui/quick-insert-button.js +154 -0
  29. package/dist/types/blockControlsPluginType.d.ts +7 -1
  30. package/dist/types/pm-plugins/decorations-quick-insert-button.d.ts +7 -0
  31. package/dist/types/pm-plugins/main.d.ts +1 -0
  32. package/dist/types/pm-plugins/utils/widget-positions.d.ts +4 -0
  33. package/dist/types/ui/consts.d.ts +7 -0
  34. package/dist/types/ui/quick-insert-button.d.ts +17 -0
  35. package/dist/types-ts4.5/blockControlsPluginType.d.ts +7 -1
  36. package/dist/types-ts4.5/pm-plugins/decorations-quick-insert-button.d.ts +7 -0
  37. package/dist/types-ts4.5/pm-plugins/main.d.ts +1 -0
  38. package/dist/types-ts4.5/pm-plugins/utils/widget-positions.d.ts +4 -0
  39. package/dist/types-ts4.5/ui/consts.d.ts +7 -0
  40. package/dist/types-ts4.5/ui/quick-insert-button.d.ts +17 -0
  41. package/package.json +2 -2
@@ -21,6 +21,7 @@ import { editorExperiment } from '@atlaskit/tmp-editor-statsig/experiments';
21
21
  import { findNodeDecs, nodeDecorations } from './decorations-anchor';
22
22
  import { dragHandleDecoration, emptyParagraphNodeDecorations, findHandleDec } from './decorations-drag-handle';
23
23
  import { dropTargetDecorations, findDropTargetDecs } from './decorations-drop-target';
24
+ import { findQuickInsertInsertButtonDecoration, quickInsertButtonDecoration } from './decorations-quick-insert-button';
24
25
  import { handleMouseOver } from './handle-mouse-over';
25
26
  import { boundKeydownHandler } from './keymap';
26
27
  import { defaultActiveAnchorTracker } from './utils/active-anchor-tracker';
@@ -150,7 +151,7 @@ export var getDecorations = function getDecorations(state) {
150
151
  return (_key$getState = key.getState(state)) === null || _key$getState === void 0 ? void 0 : _key$getState.decorations;
151
152
  };
152
153
  export var newApply = function newApply(api, formatMessage, tr, currentState, newState, flags, nodeViewPortalProviderAPI, anchorRectCache) {
153
- var _meta$multiSelectDnD, _meta$activeNode, _activeNode, _activeNode2, _meta$activeNode$hand, _meta$isDragging, _meta$isDragging2, _meta$editorHeight, _meta$editorWidthLeft, _meta$editorWidthRigh, _meta$isPMDragging, _meta$isShiftDown;
154
+ var _meta$multiSelectDnD, _meta$activeNode, _activeNode, _activeNode2, _meta$activeNode$hand, _meta$isDragging, _meta$isDragging2, _meta$toggleMenu, _meta$editorHeight, _meta$editorWidthLeft, _meta$editorWidthRigh, _meta$isPMDragging, _meta$isShiftDown;
154
155
  var activeNode = currentState.activeNode,
155
156
  decorations = currentState.decorations,
156
157
  isResizerResizing = currentState.isResizerResizing,
@@ -160,6 +161,7 @@ export var newApply = function newApply(api, formatMessage, tr, currentState, ne
160
161
  editorWidthRight = currentState.editorWidthRight,
161
162
  isDragging = currentState.isDragging,
162
163
  isMenuOpen = currentState.isMenuOpen,
164
+ menuTriggerBy = currentState.menuTriggerBy,
163
165
  isPMDragging = currentState.isPMDragging,
164
166
  isShiftDown = currentState.isShiftDown;
165
167
  var isActiveNodeDeleted = false;
@@ -173,7 +175,10 @@ export var newApply = function newApply(api, formatMessage, tr, currentState, ne
173
175
  activeNode = {
174
176
  pos: mappedPos.pos,
175
177
  anchorName: activeNode.anchorName,
176
- nodeType: activeNode.nodeType
178
+ nodeType: activeNode.nodeType,
179
+ rootPos: activeNode.rootPos,
180
+ rootAnchorName: activeNode.rootAnchorName,
181
+ rootNodeType: activeNode.rootNodeType
177
182
  };
178
183
  }
179
184
  if (multiSelectDnD && flags.isMultiSelectEnabled) {
@@ -245,12 +250,25 @@ export var newApply = function newApply(api, formatMessage, tr, currentState, ne
245
250
  var _activeNode3, _activeNode4;
246
251
  var oldHandle = findHandleDec(decorations, (_activeNode3 = activeNode) === null || _activeNode3 === void 0 ? void 0 : _activeNode3.pos, (_activeNode4 = activeNode) === null || _activeNode4 === void 0 ? void 0 : _activeNode4.pos);
247
252
  decorations = decorations.remove(oldHandle);
253
+ if (editorExperiment('platform_editor_controls', 'variant1')) {
254
+ var _activeNode5, _activeNode6;
255
+ var oldQuickInsertButton = findQuickInsertInsertButtonDecoration(decorations, (_activeNode5 = activeNode) === null || _activeNode5 === void 0 ? void 0 : _activeNode5.rootPos, (_activeNode6 = activeNode) === null || _activeNode6 === void 0 ? void 0 : _activeNode6.rootPos);
256
+ decorations = decorations.remove(oldQuickInsertButton);
257
+ }
248
258
  } else if (api && shouldRecreateHandle) {
249
- var _activeNode5, _activeNode6;
250
- var _oldHandle = findHandleDec(decorations, (_activeNode5 = activeNode) === null || _activeNode5 === void 0 ? void 0 : _activeNode5.pos, (_activeNode6 = activeNode) === null || _activeNode6 === void 0 ? void 0 : _activeNode6.pos);
259
+ var _activeNode7, _activeNode8;
260
+ var _oldHandle = findHandleDec(decorations, (_activeNode7 = activeNode) === null || _activeNode7 === void 0 ? void 0 : _activeNode7.pos, (_activeNode8 = activeNode) === null || _activeNode8 === void 0 ? void 0 : _activeNode8.pos);
251
261
  decorations = decorations.remove(_oldHandle);
252
262
  var handleDec = dragHandleDecoration(api, formatMessage, latestActiveNode === null || latestActiveNode === void 0 ? void 0 : latestActiveNode.pos, latestActiveNode === null || latestActiveNode === void 0 ? void 0 : latestActiveNode.anchorName, latestActiveNode === null || latestActiveNode === void 0 ? void 0 : latestActiveNode.nodeType, nodeViewPortalProviderAPI, latestActiveNode === null || latestActiveNode === void 0 ? void 0 : latestActiveNode.handleOptions);
253
- decorations = decorations.add(newState.doc, [handleDec]);
263
+ if (editorExperiment('platform_editor_controls', 'variant1')) {
264
+ var _activeNode9, _activeNode10;
265
+ var _oldQuickInsertButton = findQuickInsertInsertButtonDecoration(decorations, (_activeNode9 = activeNode) === null || _activeNode9 === void 0 ? void 0 : _activeNode9.rootPos, (_activeNode10 = activeNode) === null || _activeNode10 === void 0 ? void 0 : _activeNode10.rootPos);
266
+ decorations = decorations.remove(_oldQuickInsertButton);
267
+ var quickInsertButton = quickInsertButtonDecoration(api, formatMessage, latestActiveNode === null || latestActiveNode === void 0 ? void 0 : latestActiveNode.rootPos, latestActiveNode === null || latestActiveNode === void 0 ? void 0 : latestActiveNode.anchorName, latestActiveNode === null || latestActiveNode === void 0 ? void 0 : latestActiveNode.nodeType, nodeViewPortalProviderAPI, latestActiveNode === null || latestActiveNode === void 0 ? void 0 : latestActiveNode.rootAnchorName, latestActiveNode === null || latestActiveNode === void 0 ? void 0 : latestActiveNode.rootNodeType);
268
+ decorations = decorations.add(newState.doc, [handleDec, quickInsertButton]);
269
+ } else {
270
+ decorations = decorations.add(newState.doc, [handleDec]);
271
+ }
254
272
  }
255
273
 
256
274
  // Drop targets may be missing when the node count is being changed during a drag
@@ -277,12 +295,23 @@ export var newApply = function newApply(api, formatMessage, tr, currentState, ne
277
295
  }
278
296
  }
279
297
  var newActiveNode = isEmptyDoc || !(meta !== null && meta !== void 0 && meta.activeNode) && findHandleDec(decorations, latestActiveNode === null || latestActiveNode === void 0 ? void 0 : latestActiveNode.pos, latestActiveNode === null || latestActiveNode === void 0 ? void 0 : latestActiveNode.pos).length === 0 ? null : latestActiveNode;
280
- var isMenuOpenNew = editorExperiment('platform_editor_controls', 'variant1') ? meta !== null && meta !== void 0 && meta.closeMenu ? false : meta !== null && meta !== void 0 && meta.toggleMenu ? !isMenuOpen : isMenuOpen : meta !== null && meta !== void 0 && meta.toggleMenu ? !isMenuOpen : isMenuOpen;
298
+ var isMenuOpenNew = isMenuOpen;
299
+ if (editorExperiment('platform_editor_controls', 'variant1')) {
300
+ if (meta !== null && meta !== void 0 && meta.closeMenu) {
301
+ isMenuOpenNew = false;
302
+ } else if (meta !== null && meta !== void 0 && meta.toggleMenu) {
303
+ var isSameAnchor = (meta === null || meta === void 0 ? void 0 : meta.toggleMenu.anchorName) === menuTriggerBy;
304
+ isMenuOpenNew = menuTriggerBy === undefined || isSameAnchor || !isMenuOpen && !isSameAnchor ? !isMenuOpen : isMenuOpen;
305
+ }
306
+ } else if (meta !== null && meta !== void 0 && meta.toggleMenu) {
307
+ isMenuOpenNew = !isMenuOpen;
308
+ }
281
309
  return {
282
310
  decorations: decorations,
283
311
  activeNode: newActiveNode,
284
312
  isDragging: (_meta$isDragging2 = meta === null || meta === void 0 ? void 0 : meta.isDragging) !== null && _meta$isDragging2 !== void 0 ? _meta$isDragging2 : isDragging,
285
313
  isMenuOpen: isMenuOpenNew,
314
+ menuTriggerBy: editorExperiment('platform_editor_controls', 'variant1') ? (meta === null || meta === void 0 || (_meta$toggleMenu = meta.toggleMenu) === null || _meta$toggleMenu === void 0 ? void 0 : _meta$toggleMenu.anchorName) || menuTriggerBy : undefined,
286
315
  editorHeight: (_meta$editorHeight = meta === null || meta === void 0 ? void 0 : meta.editorHeight) !== null && _meta$editorHeight !== void 0 ? _meta$editorHeight : editorHeight,
287
316
  editorWidthLeft: (_meta$editorWidthLeft = meta === null || meta === void 0 ? void 0 : meta.editorWidthLeft) !== null && _meta$editorWidthLeft !== void 0 ? _meta$editorWidthLeft : editorWidthLeft,
288
317
  editorWidthRight: (_meta$editorWidthRigh = meta === null || meta === void 0 ? void 0 : meta.editorWidthRight) !== null && _meta$editorWidthRigh !== void 0 ? _meta$editorWidthRigh : editorWidthRight,
@@ -0,0 +1,20 @@
1
+ import { rootElementGap } from '../../ui/consts';
2
+
3
+ // Adapted from `src/pm-plugins/utils/drag-handle-positions.ts`
4
+ // CHANGES - removed parentNodeType, use only for positioning widgets for top level element
5
+ // CHANGES - removed layout
6
+ // CHANGES - added overrides for constants for widget dimensions
7
+ export var getLeftPositionForRootElement = function getLeftPositionForRootElement(dom, nodeType, widgetDimensions, innerContainer, macroInteractionUpdates) {
8
+ if (!dom) {
9
+ return 'auto';
10
+ }
11
+ if (!innerContainer) {
12
+ return "".concat(dom.offsetLeft - rootElementGap(nodeType) - widgetDimensions.width, "px");
13
+ }
14
+
15
+ // There is a showMacroInteractionDesignUpdates prop in extension node wrapper that can add a relative span under the top level div
16
+ // We need to adjust the left offset position of the drag handle to account for the relative span
17
+ var relativeSpan = macroInteractionUpdates ? dom.querySelector('span.relative') : null;
18
+ var leftAdjustment = relativeSpan ? relativeSpan.offsetLeft : 0;
19
+ return getComputedStyle(innerContainer).transform === 'none' ? "".concat(innerContainer.offsetLeft + leftAdjustment - rootElementGap(nodeType) - widgetDimensions.width, "px") : "".concat(innerContainer.offsetLeft + leftAdjustment - innerContainer.offsetWidth / 2 - rootElementGap(nodeType) - widgetDimensions.width, "px");
20
+ };
@@ -6,7 +6,6 @@ import { ArrowKeyNavigationType, DropdownMenu } from '@atlaskit/editor-common/ui
6
6
  import { akEditorFloatingOverlapPanelZIndex } from '@atlaskit/editor-shared-styles';
7
7
  import { getBlockMenuItems, menuItemsCallback } from './block-menu-items';
8
8
  import { BLOCK_MENU_WIDTH } from './consts';
9
- var dragHandleSelector = '[data-blocks-drag-handle-container="true"] button';
10
9
  var BlockMenu = function BlockMenu(_ref) {
11
10
  var editorView = _ref.editorView,
12
11
  mountPoint = _ref.mountPoint,
@@ -19,7 +18,8 @@ var BlockMenu = function BlockMenu(_ref) {
19
18
  if (!(blockControlsState !== null && blockControlsState !== void 0 && blockControlsState.isMenuOpen)) {
20
19
  return null;
21
20
  }
22
- var targetHandleRef = document.querySelector(dragHandleSelector);
21
+ var activeNodeSelector = "[data-drag-handler-anchor-name=".concat(blockControlsState === null || blockControlsState === void 0 ? void 0 : blockControlsState.menuTriggerBy, "]");
22
+ var targetHandleRef = document.querySelector(activeNodeSelector);
23
23
  var items = getBlockMenuItems(formatMessage);
24
24
  var handleOpenChange = function handleOpenChange(payload) {
25
25
  if (!(payload !== null && payload !== void 0 && payload.isOpen)) {
@@ -33,10 +33,13 @@ var BlockMenu = function BlockMenu(_ref) {
33
33
  if (editorView) {
34
34
  var _menuItemsCallback, _menuItemsCallback$ca;
35
35
  (_menuItemsCallback = menuItemsCallback[item.value.name]) === null || _menuItemsCallback === void 0 || (_menuItemsCallback$ca = _menuItemsCallback.call(menuItemsCallback, api, formatMessage)) === null || _menuItemsCallback$ca === void 0 || _menuItemsCallback$ca(editorView.state, editorView.dispatch, editorView);
36
+ api === null || api === void 0 || api.core.actions.execute(api === null || api === void 0 ? void 0 : api.blockControls.commands.toggleBlockMenu({
37
+ closeMenu: true
38
+ }));
36
39
  }
37
40
  };
38
41
  return /*#__PURE__*/React.createElement(Popup, {
39
- alignX: 'right',
42
+ alignX: 'left',
40
43
  alignY: 'start'
41
44
  // Ignored via go/ees005
42
45
  // eslint-disable-next-line @atlaskit/editor/no-as-casting
@@ -46,7 +49,7 @@ var BlockMenu = function BlockMenu(_ref) {
46
49
  zIndex: akEditorFloatingOverlapPanelZIndex,
47
50
  forcePlacement: true,
48
51
  stick: true,
49
- offset: [-18, 8]
52
+ offset: [-6, 8]
50
53
  }, /*#__PURE__*/React.createElement(DropdownMenu, {
51
54
  mountTo: mountPoint,
52
55
  boundariesElement: boundariesElement,
@@ -28,6 +28,12 @@ export var DRAG_HANDLE_PARAGRAPH_TOP_ADJUSTMENT = 2;
28
28
  * so we allow for some leniency to capture them all. e.g. Table is depth 3.
29
29
  */
30
30
  export var DRAG_HANDLE_MAX_SHIFT_CLICK_DEPTH = 3;
31
+ export var QUICK_INSERT_HEIGHT = 24;
32
+ export var QUICK_INSERT_WIDTH = 24;
33
+ export var QUICK_INSERT_DIMENSIONS = {
34
+ width: QUICK_INSERT_WIDTH,
35
+ height: QUICK_INSERT_HEIGHT
36
+ };
31
37
  var nodeTypeExcludeList = ['embedCard', 'mediaSingle', 'table'];
32
38
  export var dragHandleGap = function dragHandleGap(nodeType, parentNodeType) {
33
39
  if (nodeType === 'layoutSection' && fg('platform_editor_advanced_layouts_post_fix_patch_2')) {
@@ -44,6 +50,17 @@ export var dragHandleGap = function dragHandleGap(nodeType, parentNodeType) {
44
50
  }
45
51
  return DRAG_HANDLE_DEFAULT_GAP;
46
52
  };
53
+
54
+ // use for returning hap only for root level elements
55
+ export var rootElementGap = function rootElementGap(nodeType) {
56
+ if (nodeTypeExcludeList.includes(nodeType)) {
57
+ return DRAG_HANDLE_MAX_GAP;
58
+ }
59
+ if (nodeType === 'layoutSection') {
60
+ return DRAG_HANDLE_MAX_GAP + 12;
61
+ }
62
+ return DRAG_HANDLE_DEFAULT_GAP;
63
+ };
47
64
  export var getNestedNodeLeftPaddingMargin = function getNestedNodeLeftPaddingMargin(nodeType) {
48
65
  switch (nodeType) {
49
66
  case 'bodiedExtension':
@@ -187,9 +187,12 @@ export var DragHandle = function DragHandle(_ref) {
187
187
  tr = selectNode(tr, startPos, nodeType);
188
188
  if (editorExperiment('platform_editor_controls', 'variant1')) {
189
189
  var _api$blockControls;
190
- api === null || api === void 0 || (_api$blockControls = api.blockControls) === null || _api$blockControls === void 0 || _api$blockControls.commands.toggleBlockMenu()({
190
+ api === null || api === void 0 || (_api$blockControls = api.blockControls) === null || _api$blockControls === void 0 || _api$blockControls.commands.toggleBlockMenu({
191
+ anchorName: anchorName
192
+ })({
191
193
  tr: tr
192
194
  });
195
+ e.stopPropagation();
193
196
  }
194
197
  } else if (isTopLevelNode && $anchor.depth <= DRAG_HANDLE_MAX_SHIFT_CLICK_DEPTH && e.shiftKey) {
195
198
  var _api$blockControls2;
@@ -216,7 +219,7 @@ export var DragHandle = function DragHandle(_ref) {
216
219
  return tr;
217
220
  });
218
221
  view.focus();
219
- }, [isMultiSelect, api === null || api === void 0 || (_api$core2 = api.core) === null || _api$core2 === void 0 ? void 0 : _api$core2.actions, api === null || api === void 0 || (_api$analytics2 = api.analytics) === null || _api$analytics2 === void 0 ? void 0 : _api$analytics2.actions, api === null || api === void 0 || (_api$blockControls3 = api.blockControls) === null || _api$blockControls3 === void 0 ? void 0 : _api$blockControls3.commands, view, dragHandleSelected, getPos, multiSelectDnD === null || multiSelectDnD === void 0 ? void 0 : multiSelectDnD.anchor, isTopLevelNode, nodeType]);
222
+ }, [isMultiSelect, api === null || api === void 0 || (_api$core2 = api.core) === null || _api$core2 === void 0 ? void 0 : _api$core2.actions, api === null || api === void 0 || (_api$analytics2 = api.analytics) === null || _api$analytics2 === void 0 ? void 0 : _api$analytics2.actions, api === null || api === void 0 || (_api$blockControls3 = api.blockControls) === null || _api$blockControls3 === void 0 ? void 0 : _api$blockControls3.commands, view, dragHandleSelected, getPos, multiSelectDnD === null || multiSelectDnD === void 0 ? void 0 : multiSelectDnD.anchor, isTopLevelNode, nodeType, anchorName]);
220
223
 
221
224
  // TODO - This needs to be investigated further. Drag preview generation is not always working
222
225
  // as expected with a node selection. This workaround sets the selection to the node on mouseDown,
@@ -0,0 +1,154 @@
1
+ import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
2
+ import React, { useCallback, useEffect, useState } from 'react';
3
+ import { bind } from 'bind-event-listener';
4
+ import { ToolTipContent } from '@atlaskit/editor-common/keymaps';
5
+ import { blockControlsMessages as messages } from '@atlaskit/editor-common/messages';
6
+ import { useSharedPluginStateSelector } from '@atlaskit/editor-common/use-shared-plugin-state-selector';
7
+ import { TextSelection } from '@atlaskit/editor-prosemirror/state';
8
+ import EditorAddIcon from '@atlaskit/icon/glyph/editor/add';
9
+ import { Box, Pressable, xcss } from '@atlaskit/primitives';
10
+ import Tooltip from '@atlaskit/tooltip';
11
+ import { getTopPosition } from '../pm-plugins/utils/drag-handle-positions';
12
+ import { getLeftPositionForRootElement } from '../pm-plugins/utils/widget-positions';
13
+ import { QUICK_INSERT_DIMENSIONS, rootElementGap, topPositionAdjustment } from './consts';
14
+ var buttonStyles = xcss({
15
+ boxSizing: 'border-box',
16
+ display: 'flex',
17
+ flexDirection: 'column',
18
+ justifyContent: 'center',
19
+ alignItems: 'center',
20
+ height: "var(--ds-space-300, 24px)",
21
+ width: "var(--ds-space-300, 24px)",
22
+ border: 'none',
23
+ backgroundColor: 'color.background.neutral',
24
+ borderRadius: '50%',
25
+ color: 'color.text.accent.gray',
26
+ zIndex: 'card',
27
+ outline: 'none',
28
+ ':hover': {
29
+ backgroundColor: 'color.background.neutral.hovered'
30
+ },
31
+ ':active': {
32
+ backgroundColor: 'color.background.neutral.pressed'
33
+ },
34
+ ':focus': {
35
+ outline: "2px solid ".concat("var(--ds-border-focused, #388BFF)")
36
+ }
37
+ });
38
+ var containerStaticStyles = xcss({
39
+ position: 'absolute',
40
+ zIndex: 'card'
41
+ });
42
+
43
+ // TODO: Share prop types between DragHandle - generic enough to create a type for block control decoration
44
+
45
+ export var TypeAheadControl = function TypeAheadControl(_ref) {
46
+ var view = _ref.view,
47
+ api = _ref.api,
48
+ formatMessage = _ref.formatMessage,
49
+ getPos = _ref.getPos,
50
+ nodeType = _ref.nodeType,
51
+ anchorName = _ref.anchorName,
52
+ rootAnchorName = _ref.rootAnchorName,
53
+ rootNodeType = _ref.rootNodeType;
54
+ var macroInteractionUpdates = useSharedPluginStateSelector(api, 'featureFlags.macroInteractionUpdates');
55
+ var _useState = useState({}),
56
+ _useState2 = _slicedToArray(_useState, 2),
57
+ positionStyles = _useState2[0],
58
+ setPositionStyles = _useState2[1];
59
+
60
+ // Adapted from `src/ui/drag-handle.tsx` as positioning logic is similar
61
+ // CHANGES - added an offset so quick insert button can be positioned beside drag handle
62
+ // CHANGES - removed `editorExperiment('nested-dnd', true)` check and rootNodeType calculation
63
+ // CHANGES - replace anchorName with rootAnchorName
64
+ // CHANGES - `removed editorExperiment('advanced_layouts', true) && isLayoutColumn` checks as quick insert button will not be positioned for layout column
65
+ var calculatePosition = useCallback(function () {
66
+ var supportsAnchor = CSS.supports('top', "anchor(".concat(rootAnchorName, " start)")) && CSS.supports('left', "anchor(".concat(rootAnchorName, " start)"));
67
+ var dom = view.dom.querySelector("[data-drag-handler-anchor-name=\"".concat(rootAnchorName, "\"]"));
68
+ var hasResizer = rootNodeType === 'table' || rootNodeType === 'mediaSingle';
69
+ var isExtension = rootNodeType === 'extension' || rootNodeType === 'bodiedExtension';
70
+ var isBlockCard = rootNodeType === 'blockCard';
71
+ var isEmbedCard = rootNodeType === 'embedCard';
72
+ var isMacroInteractionUpdates = macroInteractionUpdates && isExtension;
73
+ var innerContainer = null;
74
+ if (dom) {
75
+ if (isEmbedCard) {
76
+ innerContainer = dom.querySelector('.rich-media-item');
77
+ } else if (hasResizer) {
78
+ innerContainer = dom.querySelector('.resizer-item');
79
+ } else if (isExtension) {
80
+ innerContainer = dom.querySelector('.extension-container[data-layout]');
81
+ } else if (isBlockCard) {
82
+ //specific to datasource blockCard
83
+ innerContainer = dom.querySelector('.datasourceView-content-inner-wrap');
84
+ }
85
+ }
86
+ var isEdgeCase = (hasResizer || isExtension || isEmbedCard || isBlockCard) && innerContainer;
87
+ var neighboringWidthOffset = anchorName === rootAnchorName ? '-16px' : '0px';
88
+ if (supportsAnchor) {
89
+ return {
90
+ left: isEdgeCase ? "calc(anchor(".concat(rootAnchorName, " start) + ").concat(getLeftPositionForRootElement(dom, rootNodeType, QUICK_INSERT_DIMENSIONS, innerContainer, isMacroInteractionUpdates), " + ").concat(neighboringWidthOffset, ")") : "calc(anchor(".concat(rootAnchorName, " start) - ").concat(QUICK_INSERT_DIMENSIONS.width, "px - ").concat(rootElementGap(rootNodeType), "px + ").concat(neighboringWidthOffset, ")"),
91
+ top: "calc(anchor(".concat(rootAnchorName, " start) + ").concat(topPositionAdjustment(rootNodeType), "px)")
92
+ };
93
+ }
94
+ return {
95
+ left: isEdgeCase ? "calc(".concat((dom === null || dom === void 0 ? void 0 : dom.offsetLeft) || 0, "px + ").concat(getLeftPositionForRootElement(dom, rootNodeType, QUICK_INSERT_DIMENSIONS, innerContainer, isMacroInteractionUpdates), " + ").concat(neighboringWidthOffset, ")") : "calc(".concat(getLeftPositionForRootElement(dom, rootNodeType, QUICK_INSERT_DIMENSIONS, innerContainer, isMacroInteractionUpdates), " + ").concat(neighboringWidthOffset, ")"),
96
+ top: getTopPosition(dom, rootNodeType)
97
+ };
98
+ }, [rootAnchorName, view.dom, rootNodeType, macroInteractionUpdates, anchorName]);
99
+ useEffect(function () {
100
+ var cleanUpTransitionListener;
101
+ if (rootNodeType === 'extension' || rootNodeType === 'embedCard') {
102
+ var dom = view.dom.querySelector("[data-drag-handler-anchor-name=\"".concat(rootAnchorName, "\"]"));
103
+ if (!dom) {
104
+ return;
105
+ }
106
+ cleanUpTransitionListener = bind(dom, {
107
+ type: 'transitionend',
108
+ listener: function listener() {
109
+ setPositionStyles(calculatePosition());
110
+ }
111
+ });
112
+ }
113
+ var calcPos = requestAnimationFrame(function () {
114
+ setPositionStyles(calculatePosition());
115
+ });
116
+ return function () {
117
+ var _cleanUpTransitionLis;
118
+ cancelAnimationFrame(calcPos);
119
+ (_cleanUpTransitionLis = cleanUpTransitionListener) === null || _cleanUpTransitionLis === void 0 || _cleanUpTransitionLis();
120
+ };
121
+ }, [calculatePosition, view.dom, rootAnchorName, rootNodeType]);
122
+ return (
123
+ /*#__PURE__*/
124
+ // eslint-disable-next-line @atlaskit/ui-styling-standard/enforce-style-prop
125
+ React.createElement(Box, {
126
+ style: positionStyles,
127
+ xcss: [containerStaticStyles]
128
+ }, /*#__PURE__*/React.createElement(Tooltip, {
129
+ content: /*#__PURE__*/React.createElement(ToolTipContent, {
130
+ description: formatMessage(messages.insert),
131
+ shortcutOverride: "/"
132
+ })
133
+ }, /*#__PURE__*/React.createElement(Pressable, {
134
+ type: "button",
135
+ "aria-label": formatMessage(messages.insert),
136
+ xcss: [buttonStyles],
137
+ onClick: function onClick() {
138
+ var _api$core, _api$quickInsert;
139
+ api === null || api === void 0 || (_api$core = api.core) === null || _api$core === void 0 || _api$core.actions.execute(function (_ref2) {
140
+ var tr = _ref2.tr;
141
+ var start = getPos();
142
+ if (!start) {
143
+ return null;
144
+ }
145
+ return tr.setSelection(TextSelection.create(tr.doc, start));
146
+ });
147
+ api === null || api === void 0 || (_api$quickInsert = api.quickInsert) === null || _api$quickInsert === void 0 || _api$quickInsert.actions.openTypeAhead('blockControl');
148
+ }
149
+ }, /*#__PURE__*/React.createElement(EditorAddIcon, {
150
+ label: "add",
151
+ size: "medium"
152
+ }))))
153
+ );
154
+ };
@@ -14,6 +14,9 @@ export type ActiveNode = {
14
14
  anchorName: string;
15
15
  nodeType: string;
16
16
  handleOptions?: HandleOptions;
17
+ rootPos?: number;
18
+ rootAnchorName?: string;
19
+ rootNodeType?: string;
17
20
  };
18
21
  export type MultiSelectDnD = {
19
22
  anchor: number;
@@ -27,6 +30,7 @@ export interface PluginState {
27
30
  decorations: DecorationSet;
28
31
  isDragging: boolean;
29
32
  isMenuOpen?: boolean;
33
+ menuTriggerBy?: string;
30
34
  editorHeight: number;
31
35
  editorWidthLeft: number;
32
36
  editorWidthRight: number;
@@ -47,6 +51,7 @@ export interface PluginState {
47
51
  export type ReleaseHiddenDecoration = () => boolean | undefined;
48
52
  export type BlockControlsSharedState = {
49
53
  isMenuOpen: boolean;
54
+ menuTriggerBy?: string;
50
55
  activeNode?: ActiveNode;
51
56
  isDragging: boolean;
52
57
  isPMDragging: boolean;
@@ -87,9 +92,10 @@ export type BlockControlsPlugin = NextEditorPlugin<'blockControls', {
87
92
  moveNodeAtCursorPos?: boolean;
88
93
  }) => EditorCommand;
89
94
  moveNode: MoveNode;
90
- showDragHandleAt: (pos: number, anchorName: string, nodeType: string, handleOptions?: HandleOptions) => EditorCommand;
95
+ showDragHandleAt: (pos: number, anchorName: string, nodeType: string, handleOptions?: HandleOptions, rootPos?: number, rootAnchorName?: string, rootNodeType?: string) => EditorCommand;
91
96
  toggleBlockMenu: (options?: {
92
97
  closeMenu?: boolean;
98
+ anchorName?: string;
93
99
  }) => EditorCommand;
94
100
  setNodeDragged: (getPos: () => number | undefined, anchorName: string, nodeType: string) => EditorCommand;
95
101
  setMultiSelectPositions: (anchor?: number, head?: number) => EditorCommand;
@@ -0,0 +1,7 @@
1
+ import { type IntlShape } from 'react-intl-next';
2
+ import type { PortalProviderAPI } from '@atlaskit/editor-common/portal';
3
+ import type { ExtractInjectionAPI } from '@atlaskit/editor-common/types';
4
+ import { Decoration, type DecorationSet } from '@atlaskit/editor-prosemirror/view';
5
+ import type { BlockControlsPlugin } from '../blockControlsPluginType';
6
+ export declare const findQuickInsertInsertButtonDecoration: (decorations: DecorationSet, from?: number, to?: number) => Decoration[];
7
+ export declare const quickInsertButtonDecoration: (api: ExtractInjectionAPI<BlockControlsPlugin>, formatMessage: IntlShape['formatMessage'], rootPos: number, anchorName: string, nodeType: string, nodeViewPortalProviderAPI: PortalProviderAPI, rootAnchorName?: string, rootNodeType?: string) => Decoration;
@@ -18,6 +18,7 @@ export declare const newApply: (api: ExtractInjectionAPI<BlockControlsPlugin> |
18
18
  activeNode: any;
19
19
  isDragging: any;
20
20
  isMenuOpen: boolean | undefined;
21
+ menuTriggerBy: any;
21
22
  editorHeight: any;
22
23
  editorWidthLeft: any;
23
24
  editorWidthRight: any;
@@ -0,0 +1,4 @@
1
+ export declare const getLeftPositionForRootElement: (dom: HTMLElement | null, nodeType: string, widgetDimensions: {
2
+ width: number;
3
+ height: number;
4
+ }, innerContainer?: HTMLElement | null, macroInteractionUpdates?: boolean) => string;
@@ -22,7 +22,14 @@ export declare const DRAG_HANDLE_PARAGRAPH_TOP_ADJUSTMENT = 2;
22
22
  * so we allow for some leniency to capture them all. e.g. Table is depth 3.
23
23
  */
24
24
  export declare const DRAG_HANDLE_MAX_SHIFT_CLICK_DEPTH = 3;
25
+ export declare const QUICK_INSERT_HEIGHT = 24;
26
+ export declare const QUICK_INSERT_WIDTH = 24;
27
+ export declare const QUICK_INSERT_DIMENSIONS: {
28
+ width: number;
29
+ height: number;
30
+ };
25
31
  export declare const dragHandleGap: (nodeType: string, parentNodeType?: string) => number;
32
+ export declare const rootElementGap: (nodeType: string) => number;
26
33
  export declare const getNestedNodeLeftPaddingMargin: (nodeType?: string) => "8px" | "16px" | "20px" | "24px" | "28px" | "40px";
27
34
  export declare const topPositionAdjustment: (nodeType: string) => number;
28
35
  export declare const dropTargetMarginMap: {
@@ -0,0 +1,17 @@
1
+ import React from 'react';
2
+ import { type IntlShape } from 'react-intl-next';
3
+ import type { ExtractInjectionAPI } from '@atlaskit/editor-common/types';
4
+ import type { EditorView } from '@atlaskit/editor-prosemirror/view';
5
+ import type { BlockControlsPlugin } from '../blockControlsPluginType';
6
+ type Props = {
7
+ view: EditorView;
8
+ api: ExtractInjectionAPI<BlockControlsPlugin>;
9
+ formatMessage: IntlShape['formatMessage'];
10
+ getPos: () => number | undefined;
11
+ nodeType: string;
12
+ anchorName: string;
13
+ rootAnchorName?: string;
14
+ rootNodeType: string;
15
+ };
16
+ export declare const TypeAheadControl: ({ view, api, formatMessage, getPos, nodeType, anchorName, rootAnchorName, rootNodeType, }: Props) => React.JSX.Element;
17
+ export {};
@@ -14,6 +14,9 @@ export type ActiveNode = {
14
14
  anchorName: string;
15
15
  nodeType: string;
16
16
  handleOptions?: HandleOptions;
17
+ rootPos?: number;
18
+ rootAnchorName?: string;
19
+ rootNodeType?: string;
17
20
  };
18
21
  export type MultiSelectDnD = {
19
22
  anchor: number;
@@ -27,6 +30,7 @@ export interface PluginState {
27
30
  decorations: DecorationSet;
28
31
  isDragging: boolean;
29
32
  isMenuOpen?: boolean;
33
+ menuTriggerBy?: string;
30
34
  editorHeight: number;
31
35
  editorWidthLeft: number;
32
36
  editorWidthRight: number;
@@ -47,6 +51,7 @@ export interface PluginState {
47
51
  export type ReleaseHiddenDecoration = () => boolean | undefined;
48
52
  export type BlockControlsSharedState = {
49
53
  isMenuOpen: boolean;
54
+ menuTriggerBy?: string;
50
55
  activeNode?: ActiveNode;
51
56
  isDragging: boolean;
52
57
  isPMDragging: boolean;
@@ -87,9 +92,10 @@ export type BlockControlsPlugin = NextEditorPlugin<'blockControls', {
87
92
  moveNodeAtCursorPos?: boolean;
88
93
  }) => EditorCommand;
89
94
  moveNode: MoveNode;
90
- showDragHandleAt: (pos: number, anchorName: string, nodeType: string, handleOptions?: HandleOptions) => EditorCommand;
95
+ showDragHandleAt: (pos: number, anchorName: string, nodeType: string, handleOptions?: HandleOptions, rootPos?: number, rootAnchorName?: string, rootNodeType?: string) => EditorCommand;
91
96
  toggleBlockMenu: (options?: {
92
97
  closeMenu?: boolean;
98
+ anchorName?: string;
93
99
  }) => EditorCommand;
94
100
  setNodeDragged: (getPos: () => number | undefined, anchorName: string, nodeType: string) => EditorCommand;
95
101
  setMultiSelectPositions: (anchor?: number, head?: number) => EditorCommand;
@@ -0,0 +1,7 @@
1
+ import { type IntlShape } from 'react-intl-next';
2
+ import type { PortalProviderAPI } from '@atlaskit/editor-common/portal';
3
+ import type { ExtractInjectionAPI } from '@atlaskit/editor-common/types';
4
+ import { Decoration, type DecorationSet } from '@atlaskit/editor-prosemirror/view';
5
+ import type { BlockControlsPlugin } from '../blockControlsPluginType';
6
+ export declare const findQuickInsertInsertButtonDecoration: (decorations: DecorationSet, from?: number, to?: number) => Decoration[];
7
+ export declare const quickInsertButtonDecoration: (api: ExtractInjectionAPI<BlockControlsPlugin>, formatMessage: IntlShape['formatMessage'], rootPos: number, anchorName: string, nodeType: string, nodeViewPortalProviderAPI: PortalProviderAPI, rootAnchorName?: string, rootNodeType?: string) => Decoration;
@@ -18,6 +18,7 @@ export declare const newApply: (api: ExtractInjectionAPI<BlockControlsPlugin> |
18
18
  activeNode: any;
19
19
  isDragging: any;
20
20
  isMenuOpen: boolean | undefined;
21
+ menuTriggerBy: any;
21
22
  editorHeight: any;
22
23
  editorWidthLeft: any;
23
24
  editorWidthRight: any;
@@ -0,0 +1,4 @@
1
+ export declare const getLeftPositionForRootElement: (dom: HTMLElement | null, nodeType: string, widgetDimensions: {
2
+ width: number;
3
+ height: number;
4
+ }, innerContainer?: HTMLElement | null, macroInteractionUpdates?: boolean) => string;
@@ -22,7 +22,14 @@ export declare const DRAG_HANDLE_PARAGRAPH_TOP_ADJUSTMENT = 2;
22
22
  * so we allow for some leniency to capture them all. e.g. Table is depth 3.
23
23
  */
24
24
  export declare const DRAG_HANDLE_MAX_SHIFT_CLICK_DEPTH = 3;
25
+ export declare const QUICK_INSERT_HEIGHT = 24;
26
+ export declare const QUICK_INSERT_WIDTH = 24;
27
+ export declare const QUICK_INSERT_DIMENSIONS: {
28
+ width: number;
29
+ height: number;
30
+ };
25
31
  export declare const dragHandleGap: (nodeType: string, parentNodeType?: string) => number;
32
+ export declare const rootElementGap: (nodeType: string) => number;
26
33
  export declare const getNestedNodeLeftPaddingMargin: (nodeType?: string) => "8px" | "16px" | "20px" | "24px" | "28px" | "40px";
27
34
  export declare const topPositionAdjustment: (nodeType: string) => number;
28
35
  export declare const dropTargetMarginMap: {
@@ -0,0 +1,17 @@
1
+ import React from 'react';
2
+ import { type IntlShape } from 'react-intl-next';
3
+ import type { ExtractInjectionAPI } from '@atlaskit/editor-common/types';
4
+ import type { EditorView } from '@atlaskit/editor-prosemirror/view';
5
+ import type { BlockControlsPlugin } from '../blockControlsPluginType';
6
+ type Props = {
7
+ view: EditorView;
8
+ api: ExtractInjectionAPI<BlockControlsPlugin>;
9
+ formatMessage: IntlShape['formatMessage'];
10
+ getPos: () => number | undefined;
11
+ nodeType: string;
12
+ anchorName: string;
13
+ rootAnchorName?: string;
14
+ rootNodeType: string;
15
+ };
16
+ export declare const TypeAheadControl: ({ view, api, formatMessage, getPos, nodeType, anchorName, rootAnchorName, rootNodeType, }: Props) => React.JSX.Element;
17
+ export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atlaskit/editor-plugin-block-controls",
3
- "version": "3.1.2",
3
+ "version": "3.1.3",
4
4
  "description": "Block controls plugin for @atlaskit/editor-core",
5
5
  "author": "Atlassian Pty Ltd",
6
6
  "license": "Apache-2.0",
@@ -31,7 +31,7 @@
31
31
  },
32
32
  "dependencies": {
33
33
  "@atlaskit/adf-schema": "^47.2.1",
34
- "@atlaskit/editor-common": "^100.1.0",
34
+ "@atlaskit/editor-common": "^100.2.0",
35
35
  "@atlaskit/editor-plugin-accessibility-utils": "^2.0.0",
36
36
  "@atlaskit/editor-plugin-analytics": "^2.0.0",
37
37
  "@atlaskit/editor-plugin-editor-disabled": "^2.0.0",