@atlaskit/editor-plugin-extension
Version:
editor-plugin-extension plugin for @atlaskit/editor-core
280 lines (279 loc) • 12.7 kB
JavaScript
import _asyncToGenerator from "@babel/runtime/helpers/asyncToGenerator";
import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
import _regeneratorRuntime from "@babel/runtime/regenerator";
import React, { useEffect } from 'react';
import { getExtensionKeyAndNodeKey } from '@atlaskit/editor-common/extensions';
import { useSharedPluginStateWithSelector } from '@atlaskit/editor-common/hooks';
import { Box } from '@atlaskit/primitives/compiled';
import { clearEditingContext, forceAutoSave } from '../editor-commands/commands';
import { getPluginState } from '../pm-plugins/plugin-factory';
import { getSelectedExtension } from '../pm-plugins/utils';
import ConfigPanelLoader from './ConfigPanel/ConfigPanelLoader';
import { CONFIG_PANEL_WIDTH } from './ConfigPanel/constants';
import HeaderAfterIconElement from './ConfigPanel/Header/HeaderAfterIconElement';
import HeaderIcon from './ConfigPanel/Header/HeaderIcon';
import { onChangeAction } from './context-panel';
import { SaveIndicator } from './SaveIndicator/SaveIndicator';
var selector = function selector(states) {
var _states$extensionStat, _states$extensionStat2, _states$extensionStat3;
return {
showContextPanel: (_states$extensionStat = states.extensionState) === null || _states$extensionStat === void 0 ? void 0 : _states$extensionStat.showContextPanel,
extensionProvider: (_states$extensionStat2 = states.extensionState) === null || _states$extensionStat2 === void 0 ? void 0 : _states$extensionStat2.extensionProvider,
processParametersAfter: (_states$extensionStat3 = states.extensionState) === null || _states$extensionStat3 === void 0 ? void 0 : _states$extensionStat3.processParametersAfter
};
};
export function useConfigPanelPluginHook(_ref) {
var editorView = _ref.editorView,
configPanelId = _ref.configPanelId,
api = _ref.api;
var editorState = editorView.state;
var _useSharedPluginState = useSharedPluginStateWithSelector(api, ['extension'], selector),
showContextPanel = _useSharedPluginState.showContextPanel,
extensionProvider = _useSharedPluginState.extensionProvider,
processParametersAfter = _useSharedPluginState.processParametersAfter;
useEffect(function () {
var nodeWithPos = getSelectedExtension(editorState, true);
// Adding checks to bail out early
if (!nodeWithPos) {
hideConfigPanel(configPanelId, api);
return;
}
if (showContextPanel && extensionProvider && processParametersAfter) {
showConfigPanel({
api: api,
configPanelId: configPanelId,
editorView: editorView,
extensionProvider: extensionProvider,
nodeWithPos: nodeWithPos
});
} else {
hideConfigPanel(configPanelId, api);
}
}, [api, configPanelId, editorState, editorView, showContextPanel, extensionProvider, processParametersAfter]);
useEffect(function () {
return function () {
hideConfigPanel(configPanelId, api);
};
}, [api, configPanelId]);
}
export function hideConfigPanel(configPanelId, api) {
var _api$contextPanel;
var closePanelById = api === null || api === void 0 || (_api$contextPanel = api.contextPanel) === null || _api$contextPanel === void 0 || (_api$contextPanel = _api$contextPanel.actions) === null || _api$contextPanel === void 0 ? void 0 : _api$contextPanel.closePanelById;
if (closePanelById) {
closePanelById(configPanelId);
}
}
export function showConfigPanel(_ref2) {
var _api$contextPanel2;
var api = _ref2.api,
configPanelId = _ref2.configPanelId,
editorView = _ref2.editorView,
extensionProvider = _ref2.extensionProvider,
nodeWithPos = _ref2.nodeWithPos;
var showContextPanel = api === null || api === void 0 || (_api$contextPanel2 = api.contextPanel) === null || _api$contextPanel2 === void 0 || (_api$contextPanel2 = _api$contextPanel2.actions) === null || _api$contextPanel2 === void 0 ? void 0 : _api$contextPanel2.showPanel;
if (showContextPanel) {
var nodeAttrs = nodeWithPos === null || nodeWithPos === void 0 ? void 0 : nodeWithPos.node.attrs;
var extensionType = nodeAttrs === null || nodeAttrs === void 0 ? void 0 : nodeAttrs.extensionType;
var extensionKey = nodeAttrs === null || nodeAttrs === void 0 ? void 0 : nodeAttrs.extensionKey;
/**
* Loading extension manifest fails when using
* extensionKey directly from nodeAttrs.
* Always get extensionKey from getExtensionKeyAndNodeKey to load
* extension manifest successfully.
*/
var _getExtensionKeyAndNo = getExtensionKeyAndNodeKey(extensionKey, extensionType),
_getExtensionKeyAndNo2 = _slicedToArray(_getExtensionKeyAndNo, 2),
extKey = _getExtensionKeyAndNo2[0],
_ = _getExtensionKeyAndNo2[1];
var HeadeIconWrapper = function HeadeIconWrapper() {
return /*#__PURE__*/React.createElement(HeaderIcon, {
extensionProvider: extensionProvider,
extensionKey: extKey,
extensionType: extensionType
});
};
var HeaderAfterIconElementWrapper = function HeaderAfterIconElementWrapper() {
return /*#__PURE__*/React.createElement(HeaderAfterIconElement, {
extensionProvider: extensionProvider,
extensionKey: extKey,
extensionType: extensionType
});
};
var BodyComponent = getContextPanelBodyComponent({
api: api,
editorView: editorView,
extensionProvider: extensionProvider,
nodeWithPos: nodeWithPos
});
showContextPanel({
id: configPanelId,
headerComponentElements: {
HeaderIcon: HeadeIconWrapper,
HeaderAfterIconElement: HeaderAfterIconElementWrapper
},
BodyComponent: BodyComponent,
closeOptions: {
canClosePanel: function () {
var _canClosePanel = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee() {
var extensionState;
return _regeneratorRuntime.wrap(function _callee$(_context) {
while (1) switch (_context.prev = _context.next) {
case 0:
if (!editorView.isDestroyed) {
_context.next = 2;
break;
}
return _context.abrupt("return", true);
case 2:
extensionState = getPluginState(editorView.state);
/**
* If context panel is open, then first update extension plugin state.
* Updating extension plugin state will trigger useEffect in useConfigPanelPluginHook,
* which will call hideConfigPanel.
*/
if (!(extensionState !== null && extensionState !== void 0 && extensionState.showContextPanel)) {
_context.next = 7;
break;
}
_context.next = 6;
return startClosingConfigPanel({
api: api,
editorView: editorView
});
case 6:
return _context.abrupt("return", false);
case 7:
return _context.abrupt("return", true);
case 8:
case "end":
return _context.stop();
}
}, _callee);
}));
function canClosePanel() {
return _canClosePanel.apply(this, arguments);
}
return canClosePanel;
}()
}
}, 'push', CONFIG_PANEL_WIDTH);
}
}
export function startClosingConfigPanel(_x) {
return _startClosingConfigPanel.apply(this, arguments);
}
function _startClosingConfigPanel() {
_startClosingConfigPanel = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee3(_ref3) {
var _api$contextPanel3;
var api, editorView, applyChange;
return _regeneratorRuntime.wrap(function _callee3$(_context3) {
while (1) switch (_context3.prev = _context3.next) {
case 0:
api = _ref3.api, editorView = _ref3.editorView;
applyChange = api === null || api === void 0 || (_api$contextPanel3 = api.contextPanel) === null || _api$contextPanel3 === void 0 ? void 0 : _api$contextPanel3.actions.applyChange; // Even if the save failed, we should proceed with closing the panel
clearEditingContext(applyChange)(editorView.state, editorView.dispatch);
_context3.prev = 3;
_context3.next = 6;
return new Promise(function (resolve, reject) {
forceAutoSave(applyChange)(resolve, reject)(editorView.state, editorView.dispatch);
});
case 6:
_context3.next = 11;
break;
case 8:
_context3.prev = 8;
_context3.t0 = _context3["catch"](3);
// Even if the save failed, we should proceed with closing the panel
// eslint-disable-next-line no-console
console.error("Autosave failed with error", _context3.t0);
case 11:
case "end":
return _context3.stop();
}
}, _callee3, null, [[3, 8]]);
}));
return _startClosingConfigPanel.apply(this, arguments);
}
export var getContextPanelBodyComponent = function getContextPanelBodyComponent(_ref4) {
var _api$featureFlags;
var api = _ref4.api,
editorView = _ref4.editorView,
extensionProvider = _ref4.extensionProvider,
nodeWithPos = _ref4.nodeWithPos;
var featureFlags = (api === null || api === void 0 || (_api$featureFlags = api.featureFlags) === null || _api$featureFlags === void 0 ? void 0 : _api$featureFlags.sharedState.currentState()) || {};
var editorState = editorView.state;
var extensionState = getPluginState(editorState);
var autoSaveResolve = extensionState.autoSaveResolve,
autoSaveReject = extensionState.autoSaveReject,
processParametersBefore = extensionState.processParametersBefore;
var _nodeWithPos$node$att = nodeWithPos.node.attrs,
extensionType = _nodeWithPos$node$att.extensionType,
extensionKey = _nodeWithPos$node$att.extensionKey,
parameters = _nodeWithPos$node$att.parameters;
var _getExtensionKeyAndNo3 = getExtensionKeyAndNodeKey(extensionKey, extensionType),
_getExtensionKeyAndNo4 = _slicedToArray(_getExtensionKeyAndNo3, 2),
extKey = _getExtensionKeyAndNo4[0],
nodeKey = _getExtensionKeyAndNo4[1];
var configParams = processParametersBefore ? processParametersBefore(parameters || {}) : parameters;
return function () {
return /*#__PURE__*/React.createElement(Box, {
padding: "space.200"
}, /*#__PURE__*/React.createElement(SaveIndicator, {
duration: 5000,
visible: true
}, function (_ref5) {
var onSaveStarted = _ref5.onSaveStarted,
onSaveEnded = _ref5.onSaveEnded;
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 _ref6 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee2(updatedParameters) {
return _regeneratorRuntime.wrap(function _callee2$(_context2) {
while (1) switch (_context2.prev = _context2.next) {
case 0:
_context2.next = 2;
return onChangeAction(editorView, updatedParameters, parameters, nodeWithPos, onSaveStarted);
case 2:
onSaveEnded();
if (autoSaveResolve) {
autoSaveResolve();
}
case 4:
case "end":
return _context2.stop();
}
}, _callee2);
}));
return function (_x2) {
return _ref6.apply(this, arguments);
};
}())
// eslint-disable-next-line @atlassian/perf-linting/no-unstable-inline-props -- Ignored via go/ees017 (to be fixed)
,
onCancel: function onCancel() {
return startClosingConfigPanel({
api: api,
editorView: editorView
});
},
featureFlags: featureFlags
// Remove below prop when cleaning platform_editor_ai_object_sidebar_injection FG
// Becuase it will always be true
,
usingObjectSidebarPanel: true
});
}));
};
};