UNPKG

@atlaskit/editor-plugin-block-controls

Version:

Block controls plugin for @atlaskit/editor-core

170 lines (167 loc) 7.63 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 { bind } from 'bind-event-listener'; import { SafePlugin } from '@atlaskit/editor-common/safe-plugin'; import { PluginKey } from '@atlaskit/editor-prosemirror/state'; import { editorExperiment } from '@atlaskit/tmp-editor-statsig/experiments'; import { handleKeyDown } from './handle-key-down'; import { handleMouseEnter, handleMouseLeave, handleMouseMove } from './handle-mouse-move'; /** Elements that extend the editor hover area (block controls, right-edge button, etc.) */ var BLOCK_CONTROLS_HOVER_AREA_SELECTOR = '[data-blocks-right-edge-button-container], [data-blocks-drag-handle-container], [data-testid="block-ctrl-drag-handle"], [data-testid="block-ctrl-drag-handle-container"], [data-testid="block-ctrl-decorator-widget"], [data-testid="block-ctrl-quick-insert-button"]'; var MOUSE_LEAVE_DEBOUNCE_MS = 200; var isMovingToBlockControlsArea = function isMovingToBlockControlsArea(target) { return target instanceof Element && !!target.closest(BLOCK_CONTROLS_HOVER_AREA_SELECTOR); }; export var interactionTrackingPluginKey = new PluginKey('interactionTrackingPlugin'); export var createInteractionTrackingPlugin = function createInteractionTrackingPlugin() { var rightSideControlsEnabled = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false; return new SafePlugin({ key: interactionTrackingPluginKey, state: { init: function init() { var state = { isEditing: false }; if (editorExperiment('platform_editor_controls', 'variant1')) { state.isMouseOut = false; } return state; }, apply: function apply(tr, pluginState) { var meta = tr.getMeta(interactionTrackingPluginKey); var newState = {}; switch (meta === null || meta === void 0 ? void 0 : meta.type) { case 'startEditing': newState.isEditing = true; break; case 'stopEditing': newState.isEditing = false; break; case 'mouseLeave': newState.isMouseOut = true; newState.hoverSide = undefined; break; case 'mouseEnter': newState.isMouseOut = false; break; case 'setHoverSide': newState.hoverSide = meta.side; break; case 'clearHoverSide': newState.hoverSide = undefined; break; } return _objectSpread(_objectSpread({}, pluginState), newState); } }, props: { handleKeyDown: handleKeyDown, handleDOMEvents: { mousemove: function mousemove(view, event) { return handleMouseMove(view, event, rightSideControlsEnabled); } } }, view: editorExperiment('platform_editor_controls', 'variant1') ? function (view) { var editorContentArea = view.dom.closest('.ak-editor-content-area'); // rightSideControlsEnabled is the single source of truth (confluence_remix_button_right_side_block_fg from preset) var unbindMouseEnter; var unbindMouseLeave; var unbindDocumentMouseMove; var mouseLeaveTimeoutId = null; var lastMousePosition = { x: 0, y: 0 }; var scheduleMouseLeave = function scheduleMouseLeave(event) { if (mouseLeaveTimeoutId) { clearTimeout(mouseLeaveTimeoutId); mouseLeaveTimeoutId = null; } // Don't set isMouseOut when moving to block controls (right-edge button, drag handle, etc.) if (rightSideControlsEnabled && isMovingToBlockControlsArea(event.relatedTarget)) { return; } mouseLeaveTimeoutId = setTimeout(function () { mouseLeaveTimeoutId = null; // Before dispatching, check if mouse has moved to block controls (e.g. through empty space) if (rightSideControlsEnabled && typeof document !== 'undefined') { var el = document.elementFromPoint(lastMousePosition.x, lastMousePosition.y); if (el && isMovingToBlockControlsArea(el)) { return; } } handleMouseLeave(view, rightSideControlsEnabled); }, MOUSE_LEAVE_DEBOUNCE_MS); }; var cancelScheduledMouseLeave = function cancelScheduledMouseLeave() { if (mouseLeaveTimeoutId) { clearTimeout(mouseLeaveTimeoutId); mouseLeaveTimeoutId = null; } }; if (editorContentArea) { if (rightSideControlsEnabled && typeof document !== 'undefined') { unbindDocumentMouseMove = bind(document, { type: 'mousemove', listener: function listener(event) { lastMousePosition = { x: event.clientX, y: event.clientY }; // Use document-level mousemove so we get events when hovering over block // controls (which may be in portals outside the editor DOM). Without this, // handleDOMEvents.mousemove only fires when over the editor content. if (editorContentArea.contains(event.target) || isMovingToBlockControlsArea(event.target)) { handleMouseMove(view, event, rightSideControlsEnabled); } }, options: { passive: true } }); } unbindMouseEnter = bind(editorContentArea, { type: 'mouseenter', listener: function listener() { if (rightSideControlsEnabled) { cancelScheduledMouseLeave(); } handleMouseEnter(view); } }); unbindMouseLeave = bind(editorContentArea, { type: 'mouseleave', listener: function listener(event) { var e = event; lastMousePosition = { x: e.clientX, y: e.clientY }; if (rightSideControlsEnabled) { scheduleMouseLeave(e); } else { handleMouseLeave(view, false); } } }); } return { destroy: function destroy() { var _unbindMouseEnter, _unbindMouseLeave; if (rightSideControlsEnabled) { var _unbindDocumentMouseM; cancelScheduledMouseLeave(); (_unbindDocumentMouseM = unbindDocumentMouseMove) === null || _unbindDocumentMouseM === void 0 || _unbindDocumentMouseM(); } (_unbindMouseEnter = unbindMouseEnter) === null || _unbindMouseEnter === void 0 || _unbindMouseEnter(); (_unbindMouseLeave = unbindMouseLeave) === null || _unbindMouseLeave === void 0 || _unbindMouseLeave(); } }; } : undefined }); }; export var getInteractionTrackingState = function getInteractionTrackingState(state) { return interactionTrackingPluginKey.getState(state); };