@atlaskit/editor-plugin-block-controls
Version:
Block controls plugin for @atlaskit/editor-core
368 lines (363 loc) • 22.8 kB
JavaScript
import _defineProperty from "@babel/runtime/helpers/defineProperty";
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
import React from 'react';
import { expandSelectionBounds } from '@atlaskit/editor-common/selection';
import { areToolbarFlagsEnabled } from '@atlaskit/editor-common/toolbar-flag-check';
import { TextSelection } from '@atlaskit/editor-prosemirror/state';
import { fg } from '@atlaskit/platform-feature-flags';
import { editorExperiment } from '@atlaskit/tmp-editor-statsig/experiments';
import { handleKeyDownWithPreservedSelection } from './editor-commands/handle-key-down-with-preserved-selection';
import { mapPreservedSelection as _mapPreservedSelection } from './editor-commands/map-preserved-selection';
import { moveNode } from './editor-commands/move-node';
import { moveNodeWithBlockMenu as _moveNodeWithBlockMenu } from './editor-commands/move-node-with-block-menu';
import { moveToLayout } from './editor-commands/move-to-layout';
import { canMoveNodeUpOrDown } from './editor-commands/utils/move-node-utils';
import { firstNodeDecPlugin } from './pm-plugins/first-node-dec-plugin';
import { createInteractionTrackingPlugin, interactionTrackingPluginKey } from './pm-plugins/interaction-tracking/pm-plugin';
import { createPlugin, key } from './pm-plugins/main';
import { startPreservingSelection as _startPreservingSelection, stopPreservingSelection as _stopPreservingSelection } from './pm-plugins/selection-preservation/editor-commands';
import { selectionPreservationPluginKey } from './pm-plugins/selection-preservation/plugin-key';
import { createSelectionPreservationPlugin } from './pm-plugins/selection-preservation/pm-plugin';
import { expandAndUpdateSelection as _expandAndUpdateSelection } from './pm-plugins/utils/expand-and-update-selection';
import { selectNode } from './pm-plugins/utils/getSelection';
import { GlobalStylesWrapper } from './ui/global-styles';
export var blockControlsPlugin = function blockControlsPlugin(_ref) {
var _config$rightSideCont, _config$quickInsertBu;
var api = _ref.api,
config = _ref.config;
var nodeDecorationRegistry = [];
var rightSideControlsEnabled = (_config$rightSideCont = config === null || config === void 0 ? void 0 : config.rightSideControlsEnabled) !== null && _config$rightSideCont !== void 0 ? _config$rightSideCont : false;
var quickInsertButtonEnabled = (_config$quickInsertBu = config === null || config === void 0 ? void 0 : config.quickInsertButtonEnabled) !== null && _config$quickInsertBu !== void 0 ? _config$quickInsertBu : true;
return {
name: 'blockControls',
actions: {
registerNodeDecoration: function registerNodeDecoration(factory) {
nodeDecorationRegistry.push(factory);
},
unregisterNodeDecoration: function unregisterNodeDecoration(type) {
var idx = nodeDecorationRegistry.findIndex(function (f) {
return f.type === type;
});
if (idx !== -1) {
nodeDecorationRegistry.splice(idx, 1);
}
}
},
pmPlugins: function pmPlugins() {
var pmPlugins = [{
name: 'blockControlsPmPlugin',
plugin: function plugin(_ref2) {
var getIntl = _ref2.getIntl,
nodeViewPortalProviderAPI = _ref2.nodeViewPortalProviderAPI;
return createPlugin(api, getIntl, nodeViewPortalProviderAPI, nodeDecorationRegistry, rightSideControlsEnabled, quickInsertButtonEnabled);
}
}];
if (editorExperiment('platform_editor_controls', 'variant1')) {
pmPlugins.push({
name: 'blockControlsInteractionTrackingPlugin',
plugin: function plugin() {
return createInteractionTrackingPlugin(rightSideControlsEnabled);
}
});
}
if (editorExperiment('platform_editor_block_menu', true)) {
pmPlugins.push({
name: 'blockControlsSelectionPreservationPlugin',
plugin: createSelectionPreservationPlugin(api)
});
}
// platform_editor_controls note: quick insert rendering fixes
if (areToolbarFlagsEnabled(Boolean(api === null || api === void 0 ? void 0 : api.toolbar))) {
pmPlugins.push({
name: 'firstNodeDec',
plugin: firstNodeDecPlugin
});
}
return pmPlugins;
},
commands: {
expandAndUpdateSelection: function expandAndUpdateSelection(_ref3) {
var startPos = _ref3.startPos,
selection = _ref3.selection,
isShiftPressed = _ref3.isShiftPressed,
nodeType = _ref3.nodeType;
return function (_ref4) {
var tr = _ref4.tr;
_expandAndUpdateSelection({
tr: tr,
selection: selection,
startPos: startPos,
isShiftPressed: isShiftPressed,
nodeType: nodeType,
api: api
});
return tr;
};
},
moveNode: moveNode(api),
moveToLayout: moveToLayout(api),
showDragHandleAt: function showDragHandleAt(pos, anchorName, nodeType, handleOptions, rootPos, rootAnchorName, rootNodeType) {
return function (_ref5) {
var tr = _ref5.tr;
var currMeta = tr.getMeta(key);
tr.setMeta(key, _objectSpread(_objectSpread({}, currMeta), {}, {
activeNode: {
pos: pos,
anchorName: anchorName,
nodeType: nodeType,
handleOptions: handleOptions,
rootPos: rootPos,
rootAnchorName: rootAnchorName,
rootNodeType: rootNodeType
}
}));
return tr;
};
},
toggleBlockMenu: function toggleBlockMenu(options) {
return function (_ref6) {
var _api$userIntent, _api$blockControls, _options$anchorName, _api$blockControls2;
var tr = _ref6.tr;
if (!editorExperiment('platform_editor_block_menu', true)) {
return tr;
}
var currMeta = tr.getMeta(key);
var currentUserIntent = api === null || api === void 0 || (_api$userIntent = api.userIntent) === null || _api$userIntent === void 0 || (_api$userIntent = _api$userIntent.sharedState.currentState()) === null || _api$userIntent === void 0 ? void 0 : _api$userIntent.currentUserIntent;
var isMenuCurrentlyOpen = api === null || api === void 0 || (_api$blockControls = api.blockControls) === null || _api$blockControls === void 0 || (_api$blockControls = _api$blockControls.sharedState.currentState()) === null || _api$blockControls === void 0 ? void 0 : _api$blockControls.isMenuOpen;
if (options !== null && options !== void 0 && options.closeMenu) {
tr.setMeta(key, _objectSpread(_objectSpread({}, currMeta), {}, {
closeMenu: true
}));
if (currentUserIntent === 'blockMenuOpen') {
var _api$userIntent2;
api === null || api === void 0 || (_api$userIntent2 = api.userIntent) === null || _api$userIntent2 === void 0 || _api$userIntent2.commands.setCurrentUserIntent('default')({
tr: tr
});
}
// When closing the menu, restart the active session timer
if (isMenuCurrentlyOpen && fg('platform_editor_ease_of_use_metrics')) {
var _api$metrics;
api === null || api === void 0 || (_api$metrics = api.metrics) === null || _api$metrics === void 0 || _api$metrics.commands.startActiveSessionTimer()({
tr: tr
});
}
return tr;
}
// Do not open menu on layoutColumn and close opened menu when layoutColumn drag handle is clicked
if (options !== null && options !== void 0 && (_options$anchorName = options.anchorName) !== null && _options$anchorName !== void 0 && _options$anchorName.includes('layoutColumn')) {
if (currentUserIntent === 'blockMenuOpen') {
var _api$userIntent3;
api === null || api === void 0 || (_api$userIntent3 = api.userIntent) === null || _api$userIntent3 === void 0 || _api$userIntent3.commands.setCurrentUserIntent('default')({
tr: tr
});
}
tr.setMeta(key, _objectSpread(_objectSpread({}, currMeta), {}, {
closeMenu: true
}));
// When closing the menu, restart the active session timer
if (isMenuCurrentlyOpen && fg('platform_editor_ease_of_use_metrics')) {
var _api$metrics2;
api === null || api === void 0 || (_api$metrics2 = api.metrics) === null || _api$metrics2 === void 0 || _api$metrics2.commands.startActiveSessionTimer()({
tr: tr
});
}
return tr;
}
var toggleMenuMeta = {
anchorName: options === null || options === void 0 ? void 0 : options.anchorName,
triggerByNode: options === null || options === void 0 ? void 0 : options.triggerByNode
};
var menuTriggerBy = api === null || api === void 0 || (_api$blockControls2 = api.blockControls) === null || _api$blockControls2 === void 0 || (_api$blockControls2 = _api$blockControls2.sharedState.currentState()) === null || _api$blockControls2 === void 0 ? void 0 : _api$blockControls2.menuTriggerBy;
if (options !== null && options !== void 0 && options.anchorName) {
var _canMoveNodeUpOrDown = canMoveNodeUpOrDown(tr),
moveUp = _canMoveNodeUpOrDown.moveUp,
moveDown = _canMoveNodeUpOrDown.moveDown;
toggleMenuMeta = _objectSpread(_objectSpread({}, toggleMenuMeta), {}, {
moveUp: moveUp,
moveDown: moveDown,
openedViaKeyboard: options === null || options === void 0 ? void 0 : options.openedViaKeyboard
});
}
tr.setMeta(key, _objectSpread(_objectSpread({}, currMeta), {}, {
toggleMenu: toggleMenuMeta
}));
if ((menuTriggerBy === undefined || !!menuTriggerBy && menuTriggerBy === (options === null || options === void 0 ? void 0 : options.anchorName)) && currentUserIntent === 'blockMenuOpen') {
var state = api === null || api === void 0 ? void 0 : api.blockControls.sharedState.currentState();
if (state !== null && state !== void 0 && state.isSelectedViaDragHandle) {
var _api$userIntent4;
api === null || api === void 0 || (_api$userIntent4 = api.userIntent) === null || _api$userIntent4 === void 0 || _api$userIntent4.commands.setCurrentUserIntent('dragHandleSelected')({
tr: tr
});
} else {
var _api$userIntent5;
// Toggled from drag handle
api === null || api === void 0 || (_api$userIntent5 = api.userIntent) === null || _api$userIntent5 === void 0 || _api$userIntent5.commands.setCurrentUserIntent('default')({
tr: tr
});
}
// When closing the menu, restart the active session timer
if (fg('platform_editor_ease_of_use_metrics')) {
var _api$metrics3;
api === null || api === void 0 || (_api$metrics3 = api.metrics) === null || _api$metrics3 === void 0 || _api$metrics3.commands.startActiveSessionTimer()({
tr: tr
});
}
} else if (!isMenuCurrentlyOpen) {
// When opening the menu, pause the active session timer
if (fg('platform_editor_ease_of_use_metrics')) {
var _api$metrics4;
api === null || api === void 0 || (_api$metrics4 = api.metrics) === null || _api$metrics4 === void 0 || _api$metrics4.commands.handleIntentToStartEdit({
shouldStartTimer: false,
shouldPersistActiveSession: true
})({
tr: tr
});
}
}
return tr;
};
},
setNodeDragged: function setNodeDragged(getPos, anchorName, nodeType) {
return function (_ref7) {
var _api$userIntent6;
var tr = _ref7.tr;
var pos = getPos();
if (pos === undefined) {
return tr;
}
var currMeta = tr.getMeta(key);
tr.setMeta(key, _objectSpread(_objectSpread({}, currMeta), {}, {
isDragging: true,
activeNode: {
pos: pos,
anchorName: anchorName,
nodeType: nodeType
}
}));
if (fg('platform_editor_ease_of_use_metrics')) {
var _api$metrics5;
api === null || api === void 0 || (_api$metrics5 = api.metrics) === null || _api$metrics5 === void 0 || _api$metrics5.commands.handleIntentToStartEdit({
shouldStartTimer: false,
shouldPersistActiveSession: true
})({
tr: tr
});
}
api === null || api === void 0 || (_api$userIntent6 = api.userIntent) === null || _api$userIntent6 === void 0 || _api$userIntent6.commands.setCurrentUserIntent('dragging')({
tr: tr
});
return tr;
};
},
setMultiSelectPositions: function setMultiSelectPositions(anchor, head) {
return function (_ref8) {
var _api$selection, _$to$nodeBefore, _$from$nodeAfter;
var tr = _ref8.tr;
var _tr$selection = tr.selection,
userAnchor = _tr$selection.anchor,
userHead = _tr$selection.head;
var $expandedAnchor, $expandedHead;
if (anchor !== undefined && head !== undefined) {
$expandedAnchor = tr.doc.resolve(anchor);
$expandedHead = tr.doc.resolve(head);
} else {
var expandedSelection = expandSelectionBounds(tr.selection.$anchor, tr.selection.$head);
$expandedAnchor = expandedSelection.$anchor;
$expandedHead = expandedSelection.$head;
}
api === null || api === void 0 || (_api$selection = api.selection) === null || _api$selection === void 0 || _api$selection.commands.setManualSelection($expandedAnchor.pos, $expandedHead.pos)({
tr: tr
});
var $from = $expandedAnchor.min($expandedHead);
var $to = $expandedAnchor.max($expandedHead);
var expandedNormalisedSel;
if ($from.nodeAfter === $to.nodeBefore) {
selectNode(tr, $from.pos, $expandedAnchor.node().type.name, api);
expandedNormalisedSel = tr.selection;
} else if (((_$to$nodeBefore = $to.nodeBefore) === null || _$to$nodeBefore === void 0 ? void 0 : _$to$nodeBefore.type.name) === 'mediaSingle' || ((_$from$nodeAfter = $from.nodeAfter) === null || _$from$nodeAfter === void 0 ? void 0 : _$from$nodeAfter.type.name) === 'mediaSingle') {
expandedNormalisedSel = new TextSelection($expandedAnchor, $expandedHead);
tr.setSelection(expandedNormalisedSel);
} else {
// this is to normalise the selection's boundaries to inline positions, preventing it from collapsing
expandedNormalisedSel = TextSelection.between($expandedAnchor, $expandedHead);
tr.setSelection(expandedNormalisedSel);
}
var multiSelectDnD = {
anchor: $expandedAnchor.pos,
head: $expandedHead.pos,
textAnchor: expandedNormalisedSel.anchor,
textHead: expandedNormalisedSel.head,
userAnchor: userAnchor,
userHead: userHead
};
var currMeta = tr.getMeta(key);
tr.setMeta(key, _objectSpread(_objectSpread({}, currMeta), {}, {
multiSelectDnD: multiSelectDnD
}));
return tr;
};
},
setSelectedViaDragHandle: function setSelectedViaDragHandle(isSelectedViaDragHandle) {
return function (_ref9) {
var tr = _ref9.tr;
var currMeta = tr.getMeta(key);
return tr.setMeta(key, _objectSpread(_objectSpread({}, currMeta), {}, {
isSelectedViaDragHandle: isSelectedViaDragHandle
}));
};
},
mapPreservedSelection: function mapPreservedSelection(mapping) {
return _mapPreservedSelection(mapping);
},
moveNodeWithBlockMenu: function moveNodeWithBlockMenu(direction) {
return _moveNodeWithBlockMenu(api, direction);
},
handleKeyDownWithPreservedSelection: handleKeyDownWithPreservedSelection(api),
startPreservingSelection: function startPreservingSelection() {
return _startPreservingSelection;
},
stopPreservingSelection: function stopPreservingSelection() {
return _stopPreservingSelection;
}
},
getSharedState: function getSharedState(editorState) {
var _key$getState$isMenuO, _key$getState, _key$getState$menuTri, _key$getState2, _key$getState$menuTri2, _key$getState3, _key$getState$blockMe, _key$getState4, _key$getState$activeN, _key$getState5, _key$getState$activeD, _key$getState6, _key$getState$isDragg, _key$getState7, _key$getState$isPMDra, _key$getState8, _key$getState$multiSe, _key$getState9, _key$getState$isShift, _key$getState0, _key$getState$lastDra, _key$getState1, _interactionTrackingP, _key$getState$isSelec, _key$getState10;
if (!editorState) {
return undefined;
}
var sharedState = {
isMenuOpen: (_key$getState$isMenuO = (_key$getState = key.getState(editorState)) === null || _key$getState === void 0 ? void 0 : _key$getState.isMenuOpen) !== null && _key$getState$isMenuO !== void 0 ? _key$getState$isMenuO : false,
menuTriggerBy: (_key$getState$menuTri = (_key$getState2 = key.getState(editorState)) === null || _key$getState2 === void 0 ? void 0 : _key$getState2.menuTriggerBy) !== null && _key$getState$menuTri !== void 0 ? _key$getState$menuTri : undefined,
menuTriggerByNode: (_key$getState$menuTri2 = (_key$getState3 = key.getState(editorState)) === null || _key$getState3 === void 0 ? void 0 : _key$getState3.menuTriggerByNode) !== null && _key$getState$menuTri2 !== void 0 ? _key$getState$menuTri2 : undefined,
blockMenuOptions: (_key$getState$blockMe = (_key$getState4 = key.getState(editorState)) === null || _key$getState4 === void 0 ? void 0 : _key$getState4.blockMenuOptions) !== null && _key$getState$blockMe !== void 0 ? _key$getState$blockMe : undefined,
activeNode: (_key$getState$activeN = (_key$getState5 = key.getState(editorState)) === null || _key$getState5 === void 0 ? void 0 : _key$getState5.activeNode) !== null && _key$getState$activeN !== void 0 ? _key$getState$activeN : undefined,
activeDropTargetNode: (_key$getState$activeD = (_key$getState6 = key.getState(editorState)) === null || _key$getState6 === void 0 ? void 0 : _key$getState6.activeDropTargetNode) !== null && _key$getState$activeD !== void 0 ? _key$getState$activeD : undefined,
isDragging: (_key$getState$isDragg = (_key$getState7 = key.getState(editorState)) === null || _key$getState7 === void 0 ? void 0 : _key$getState7.isDragging) !== null && _key$getState$isDragg !== void 0 ? _key$getState$isDragg : false,
isPMDragging: (_key$getState$isPMDra = (_key$getState8 = key.getState(editorState)) === null || _key$getState8 === void 0 ? void 0 : _key$getState8.isPMDragging) !== null && _key$getState$isPMDra !== void 0 ? _key$getState$isPMDra : false,
multiSelectDnD: (_key$getState$multiSe = (_key$getState9 = key.getState(editorState)) === null || _key$getState9 === void 0 ? void 0 : _key$getState9.multiSelectDnD) !== null && _key$getState$multiSe !== void 0 ? _key$getState$multiSe : undefined,
isShiftDown: (_key$getState$isShift = (_key$getState0 = key.getState(editorState)) === null || _key$getState0 === void 0 ? void 0 : _key$getState0.isShiftDown) !== null && _key$getState$isShift !== void 0 ? _key$getState$isShift : undefined,
lastDragCancelled: (_key$getState$lastDra = (_key$getState1 = key.getState(editorState)) === null || _key$getState1 === void 0 ? void 0 : _key$getState1.lastDragCancelled) !== null && _key$getState$lastDra !== void 0 ? _key$getState$lastDra : false,
isEditing: (_interactionTrackingP = interactionTrackingPluginKey.getState(editorState)) === null || _interactionTrackingP === void 0 ? void 0 : _interactionTrackingP.isEditing,
isSelectedViaDragHandle: (_key$getState$isSelec = (_key$getState10 = key.getState(editorState)) === null || _key$getState10 === void 0 ? void 0 : _key$getState10.isSelectedViaDragHandle) !== null && _key$getState$isSelec !== void 0 ? _key$getState$isSelec : false
};
if (editorExperiment('platform_editor_controls', 'variant1')) {
var _interactionTrackingP2, _interactionTrackingP3, _interactionTrackingP4;
sharedState.isMouseOut = (_interactionTrackingP2 = (_interactionTrackingP3 = interactionTrackingPluginKey.getState(editorState)) === null || _interactionTrackingP3 === void 0 ? void 0 : _interactionTrackingP3.isMouseOut) !== null && _interactionTrackingP2 !== void 0 ? _interactionTrackingP2 : false;
// rightSideControlsEnabled is the single source of truth (confluence_remix_button_right_side_block_fg from preset)
sharedState.rightSideControlsEnabled = rightSideControlsEnabled;
sharedState.hoverSide = rightSideControlsEnabled ? (_interactionTrackingP4 = interactionTrackingPluginKey.getState(editorState)) === null || _interactionTrackingP4 === void 0 ? void 0 : _interactionTrackingP4.hoverSide : undefined;
}
if (editorExperiment('platform_editor_block_menu', true)) {
var _selectionPreservatio;
sharedState.preservedSelection = (_selectionPreservatio = selectionPreservationPluginKey.getState(editorState)) === null || _selectionPreservatio === void 0 ? void 0 : _selectionPreservatio.preservedSelection;
}
return sharedState;
},
contentComponent: function contentComponent() {
return /*#__PURE__*/React.createElement(GlobalStylesWrapper, {
api: api
});
}
};
};