@atlaskit/editor-plugin-decorations
Version:
Decorations plugin for @atlaskit/editor-core
126 lines (124 loc) • 4.84 kB
JavaScript
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;
}
}
});
});