UNPKG

@atlaskit/editor-plugin-decorations

Version:

Decorations plugin for @atlaskit/editor-core

126 lines (124 loc) 4.84 kB
import { SafePlugin } from '@atlaskit/editor-common/safe-plugin'; import { NodeSelection, PluginKey } from '@atlaskit/editor-prosemirror/state'; import { findParentNodeOfType } from '@atlaskit/editor-prosemirror/utils'; import { Decoration, DecorationSet } from '@atlaskit/editor-prosemirror/view'; import { expValEqualsNoExposure } from '@atlaskit/tmp-editor-statsig/exp-val-equals-no-exposure'; import { editorExperiment } from '@atlaskit/tmp-editor-statsig/experiments'; export var decorationStateKey = new PluginKey('decorationPlugin'); export var ACTIONS = /*#__PURE__*/function (ACTIONS) { ACTIONS[ACTIONS["DECORATION_ADD"] = 0] = "DECORATION_ADD"; ACTIONS[ACTIONS["DECORATION_REMOVE"] = 1] = "DECORATION_REMOVE"; return ACTIONS; }({}); export var removeDecoration = function removeDecoration(state, dispatch) { var tr = state.tr; var _ref = decorationStateKey.getState(state), decoration = _ref.decoration; if (decoration && dispatch) { dispatch(tr.setMeta(decorationStateKey, { action: ACTIONS.DECORATION_REMOVE })); return true; } return false; }; export var hoverDecoration = function hoverDecoration(nodeType, add) { var className = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 'danger'; return function (state, dispatch) { var from; var parentNode; if (state.selection instanceof NodeSelection) { var selectedNode = state.selection.node; var nodeTypes = Array.isArray(nodeType) ? nodeType : [nodeType]; var isNodeTypeMatching = nodeTypes.indexOf(selectedNode.type) > -1; // This adds danger styling if the selected node is the one that requires // the decoration to be added, e.g. if a layout is selected and the user // hovers over the layout's delete button. if (isNodeTypeMatching) { from = state.selection.from; parentNode = selectedNode; } } // This adds danger styling if the selection is not a node selection, OR if // the selected node is a child of the one that requires the decoration to // be added, e.g. if a decision item is selected inside a layout and the // user hovers over the layout's delete button. var foundParentNode = findParentNodeOfType(nodeType)(state.selection); if (from === undefined && foundParentNode) { from = foundParentNode.pos; parentNode = foundParentNode.node; } // Note: can't use !from as from could be 0, which is falsy but valid if (from === undefined || parentNode === undefined) { return false; } if (dispatch) { dispatch(state.tr.setMeta(decorationStateKey, { action: add ? ACTIONS.DECORATION_ADD : ACTIONS.DECORATION_REMOVE, data: Decoration.node(from, from + parentNode.nodeSize, { class: className }, { key: 'decorationNode' }) }).setMeta('addToHistory', false)); } return true; }; }; export default (function () { return new SafePlugin({ key: decorationStateKey, state: { init: function init() { return { decoration: undefined }; }, apply: function apply(tr, pluginState) { if (pluginState.decoration && pluginState.decoration instanceof Decoration) { var mapResult = tr.mapping.mapResult(pluginState.decoration.from); if (mapResult.deleted) { pluginState = { decoration: undefined }; } } if (pluginState.decoration && pluginState.decoration instanceof DecorationSet && editorExperiment('platform_editor_block_menu', true)) { pluginState.decoration = pluginState.decoration.map(tr.mapping, tr.doc); } var meta = tr.getMeta(decorationStateKey); if (!meta) { return pluginState; } switch (meta.action) { case ACTIONS.DECORATION_ADD: return { decoration: meta.data, hasDangerDecorations: expValEqualsNoExposure('platform_editor_block_menu', 'isEnabled', true) ? meta.hasDangerDecorations : undefined }; case ACTIONS.DECORATION_REMOVE: return { decoration: undefined, hasDangerDecorations: undefined }; default: return pluginState; } } }, props: { decorations: function decorations(state) { var doc = state.doc; var _ref2 = decorationStateKey.getState(state), decoration = _ref2.decoration; if (decoration instanceof Decoration) { return DecorationSet.create(doc, [decoration]); } if (decoration instanceof DecorationSet && editorExperiment('platform_editor_block_menu', true)) { return decoration; } return null; } } }); });