UNPKG

@atlaskit/editor-plugin-block-controls

Version:

Block controls plugin for @atlaskit/editor-core

368 lines (363 loc) 22.8 kB
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 }); } }; };