@atlaskit/editor-plugin-extension
Version:
editor-plugin-extension plugin for @atlaskit/editor-core
263 lines (260 loc) • 12.7 kB
JavaScript
import _defineProperty from "@babel/runtime/helpers/defineProperty";
import _asyncToGenerator from "@babel/runtime/helpers/asyncToGenerator";
import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
import _typeof from "@babel/runtime/helpers/typeof";
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 _regeneratorRuntime from "@babel/runtime/regenerator";
import React from 'react';
import { getExtensionKeyAndNodeKey } from '@atlaskit/editor-common/extensions';
import { GapCursorSelection } from '@atlaskit/editor-common/selection';
import { NodeSelection, TextSelection } from '@atlaskit/editor-prosemirror/state';
import { CellSelection } from '@atlaskit/editor-tables/cell-selection';
import { buildExtensionNode } from '../editor-actions/actions';
import { clearEditingContext, forceAutoSave, updateState } from '../editor-commands/commands';
import { getPluginState } from '../pm-plugins/plugin-factory';
import { getSelectedExtension } from '../pm-plugins/utils';
import ConfigPanelLoader from './ConfigPanel/ConfigPanelLoader';
import { SaveIndicator } from './SaveIndicator/SaveIndicator';
var areParametersEqual = function areParametersEqual(firstParameters, secondParameters) {
if (_typeof(firstParameters) === 'object' && _typeof(secondParameters) === 'object' && firstParameters !== null && secondParameters !== null) {
var firstKeys = Object.keys(firstParameters);
var secondKeys = Object.keys(secondParameters);
return firstKeys.length === secondKeys.length && firstKeys.every(function (key) {
return firstParameters[key] === secondParameters[key];
});
}
return firstParameters === secondParameters;
};
export var duplicateSelection = function duplicateSelection(selectionToDuplicate, doc) {
if (selectionToDuplicate instanceof NodeSelection) {
return NodeSelection.create(doc, selectionToDuplicate.from);
} else if (selectionToDuplicate instanceof TextSelection) {
return TextSelection.create(doc, selectionToDuplicate.from, selectionToDuplicate.to);
} else if (selectionToDuplicate instanceof GapCursorSelection) {
return new GapCursorSelection(doc.resolve(selectionToDuplicate.from), selectionToDuplicate.side);
} else if (selectionToDuplicate instanceof CellSelection) {
return new CellSelection(doc.resolve(selectionToDuplicate.$anchorCell.pos), doc.resolve(selectionToDuplicate.$headCell.pos));
}
};
export var getContextPanel = function getContextPanel(getEditorView) {
return function (api, featureFlags) {
return function (state) {
var _api$contextPanel;
var nodeWithPos = getSelectedExtension(state, true);
var applyChange = api === null || api === void 0 || (_api$contextPanel = api.contextPanel) === null || _api$contextPanel === void 0 ? void 0 : _api$contextPanel.actions.applyChange;
// Adding checks to bail out early
if (!nodeWithPos) {
return;
}
var extensionState = getPluginState(state);
var autoSaveResolve = extensionState.autoSaveResolve,
autoSaveReject = extensionState.autoSaveReject,
showContextPanel = extensionState.showContextPanel,
extensionProvider = extensionState.extensionProvider,
processParametersBefore = extensionState.processParametersBefore,
processParametersAfter = extensionState.processParametersAfter;
if (extensionState && showContextPanel && extensionProvider && processParametersAfter) {
var _nodeWithPos$node$att = nodeWithPos.node.attrs,
extensionType = _nodeWithPos$node$att.extensionType,
extensionKey = _nodeWithPos$node$att.extensionKey,
parameters = _nodeWithPos$node$att.parameters;
var _getExtensionKeyAndNo = getExtensionKeyAndNodeKey(extensionKey, extensionType),
_getExtensionKeyAndNo2 = _slicedToArray(_getExtensionKeyAndNo, 2),
extKey = _getExtensionKeyAndNo2[0],
nodeKey = _getExtensionKeyAndNo2[1];
var configParams = processParametersBefore ? processParametersBefore(parameters || {}) : parameters;
return /*#__PURE__*/React.createElement(SaveIndicator, {
duration: 5000,
visible: true
}, function (_ref) {
var onSaveStarted = _ref.onSaveStarted,
onSaveEnded = _ref.onSaveEnded;
var editorView = getEditorView === null || getEditorView === void 0 ? void 0 : getEditorView();
if (!editorView) {
return null;
}
return /*#__PURE__*/React.createElement(ConfigPanelLoader, {
api: api,
showHeader: true,
closeOnEsc: true,
extensionType: extensionType,
extensionKey: extKey,
nodeKey: nodeKey,
extensionParameters: parameters,
parameters: configParams,
extensionProvider: extensionProvider,
autoSaveTrigger: autoSaveResolve,
autoSaveReject: autoSaveReject
// eslint-disable-next-line @atlassian/perf-linting/no-unstable-inline-props -- Ignored via go/ees017 (to be fixed)
,
onChange: ( /*#__PURE__*/function () {
var _ref2 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee(updatedParameters) {
return _regeneratorRuntime.wrap(function _callee$(_context) {
while (1) switch (_context.prev = _context.next) {
case 0:
_context.next = 2;
return onChangeAction(editorView, updatedParameters, parameters, nodeWithPos, onSaveStarted);
case 2:
onSaveEnded();
if (autoSaveResolve) {
autoSaveResolve();
}
case 4:
case "end":
return _context.stop();
}
}, _callee);
}));
return function (_x) {
return _ref2.apply(this, arguments);
};
}())
// eslint-disable-next-line @atlassian/perf-linting/no-unstable-inline-props -- Ignored via go/ees017 (to be fixed)
,
onCancel: /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee2() {
return _regeneratorRuntime.wrap(function _callee2$(_context2) {
while (1) switch (_context2.prev = _context2.next) {
case 0:
_context2.prev = 0;
_context2.next = 3;
return new Promise(function (resolve, reject) {
forceAutoSave(applyChange)(resolve, reject)(editorView.state, editorView.dispatch);
});
case 3:
_context2.next = 8;
break;
case 5:
_context2.prev = 5;
_context2.t0 = _context2["catch"](0);
// Even if the save failed, we should proceed with closing the panel
// eslint-disable-next-line no-console
console.error("Autosave failed with error", _context2.t0);
case 8:
clearEditingContext(applyChange)(editorView.state, editorView.dispatch);
case 9:
case "end":
return _context2.stop();
}
}, _callee2, null, [[0, 5]]);
})),
featureFlags: featureFlags
});
});
}
};
};
};
// Added this interface to handle the macroParams on Parameters
export function onChangeAction(_x2) {
return _onChangeAction.apply(this, arguments);
}
function _onChangeAction() {
_onChangeAction = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee3(editorView) {
var updatedParameters,
oldParameters,
nodeWithPos,
onSaving,
_ref4,
processParametersAfter,
processParametersBefore,
unwrappedOldParameters,
key,
_ref5,
previousPositions,
newParameters,
_ref6,
positions,
node,
newNode,
positionUpdated,
transaction,
prevSelection,
selection,
positionsLess,
_args3 = arguments;
return _regeneratorRuntime.wrap(function _callee3$(_context3) {
while (1) switch (_context3.prev = _context3.next) {
case 0:
updatedParameters = _args3.length > 1 && _args3[1] !== undefined ? _args3[1] : {};
oldParameters = _args3.length > 2 && _args3[2] !== undefined ? _args3[2] : {};
nodeWithPos = _args3.length > 3 ? _args3[3] : undefined;
onSaving = _args3.length > 4 ? _args3[4] : undefined;
// WARNING: editorView.state stales quickly, do not unpack
_ref4 = getPluginState(editorView.state), processParametersAfter = _ref4.processParametersAfter, processParametersBefore = _ref4.processParametersBefore;
if (processParametersAfter) {
_context3.next = 7;
break;
}
return _context3.abrupt("return");
case 7:
unwrappedOldParameters = processParametersBefore ? processParametersBefore(oldParameters) : oldParameters;
if (!areParametersEqual(unwrappedOldParameters, updatedParameters)) {
_context3.next = 10;
break;
}
return _context3.abrupt("return");
case 10:
if (onSaving) {
onSaving();
}
key = Date.now();
_ref5 = getPluginState(editorView.state), previousPositions = _ref5.positions;
_context3.next = 15;
return updateState({
positions: _objectSpread(_objectSpread({}, previousPositions), {}, _defineProperty({}, key, nodeWithPos.pos))
})(editorView.state, editorView.dispatch);
case 15:
_context3.next = 17;
return processParametersAfter(updatedParameters);
case 17:
newParameters = _context3.sent;
_ref6 = getPluginState(editorView.state), positions = _ref6.positions;
if (positions) {
_context3.next = 21;
break;
}
return _context3.abrupt("return");
case 21:
if (key in positions) {
_context3.next = 23;
break;
}
return _context3.abrupt("return");
case 23:
node = nodeWithPos.node;
newNode = buildExtensionNode(nodeWithPos.node.toJSON().type, editorView.state.schema, _objectSpread(_objectSpread({}, node.attrs), {}, {
parameters: _objectSpread(_objectSpread({}, oldParameters), newParameters)
}), node.content, node.marks);
if (newNode) {
_context3.next = 27;
break;
}
return _context3.abrupt("return");
case 27:
positionUpdated = positions[key];
transaction = editorView.state.tr.replaceWith(positionUpdated, positionUpdated + newNode.nodeSize, newNode); // Ensure we preserve the selection, tr.replaceWith causes it to be lost in some cases
// when replacing the node
prevSelection = editorView.state.selection;
if (!prevSelection.eq(transaction.selection)) {
selection = duplicateSelection(prevSelection, transaction.doc);
if (selection) {
transaction.setSelection(selection);
}
}
positionsLess = _objectSpread({}, getPluginState(editorView.state).positions);
delete positionsLess[key];
_context3.next = 35;
return updateState({
positions: positionsLess
})(editorView.state, editorView.dispatch);
case 35:
editorView.dispatch(transaction);
case 36:
case "end":
return _context3.stop();
}
}, _callee3);
}));
return _onChangeAction.apply(this, arguments);
}