@atlaskit/editor-plugin-selection-extension
Version:
editor-plugin-selection-extension plugin for @atlaskit/editor-core
333 lines (325 loc) • 16.1 kB
JavaScript
"use strict";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.selectionExtensionPlugin = void 0;
var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
var _react = _interopRequireDefault(require("react"));
var _coreUtils = require("@atlaskit/editor-common/core-utils");
var _messages = require("@atlaskit/editor-common/messages");
var _safePlugin = require("@atlaskit/editor-common/safe-plugin");
var _usePluginStateEffect = require("@atlaskit/editor-common/use-plugin-state-effect");
var _experiments = require("@atlaskit/tmp-editor-statsig/experiments");
var _insertAdfAtEndOfDoc2 = require("./pm-plugins/actions/insertAdfAtEndOfDoc");
var _replaceWithAdf2 = require("./pm-plugins/actions/replaceWithAdf");
var _main = require("./pm-plugins/main");
var _utils = require("./pm-plugins/utils");
var _types = require("./types");
var _SelectionExtensionComponentWrapper = require("./ui/extension/SelectionExtensionComponentWrapper");
var _extensions = require("./ui/extensions");
var _LegacyToolbarComponent = require("./ui/LegacyToolbarComponent");
var _selectionToolbar = require("./ui/selectionToolbar");
var _toolbarComponents = require("./ui/toolbar-components");
var _registerBlockMenuItems = require("./ui/utils/registerBlockMenuItems");
var selectionExtensionPlugin = exports.selectionExtensionPlugin = function selectionExtensionPlugin(_ref) {
var api = _ref.api,
config = _ref.config;
var editorViewRef = {};
var cachedSelection;
var cachedOverflowMenuOptions;
var isToolbarAIFCEnabled = Boolean(api === null || api === void 0 ? void 0 : api.toolbar);
var _ref2 = config || {},
_ref2$extensionList = _ref2.extensionList,
extensionList = _ref2$extensionList === void 0 ? [] : _ref2$extensionList,
_ref2$extensions = _ref2.extensions,
extensions = _ref2$extensions === void 0 ? {} : _ref2$extensions;
var _ref3 = extensions || {},
_ref3$firstParty = _ref3.firstParty,
firstParty = _ref3$firstParty === void 0 ? [] : _ref3$firstParty,
_ref3$external = _ref3.external,
external = _ref3$external === void 0 ? [] : _ref3$external;
if (!isToolbarAIFCEnabled) {
var primaryToolbarItemExtensions = (0, _extensions.getToolbarItemExtensions)(extensionList, 'primaryToolbar');
if (primaryToolbarItemExtensions !== null && primaryToolbarItemExtensions !== void 0 && primaryToolbarItemExtensions.length) {
var _api$primaryToolbar;
api === null || api === void 0 || (_api$primaryToolbar = api.primaryToolbar) === null || _api$primaryToolbar === void 0 || (_api$primaryToolbar = _api$primaryToolbar.actions) === null || _api$primaryToolbar === void 0 || _api$primaryToolbar.registerComponent({
name: 'selectionExtension',
component: function component() {
return /*#__PURE__*/_react.default.createElement(_LegacyToolbarComponent.LegacyPrimaryToolbarComponent, {
primaryToolbarItemExtensions: primaryToolbarItemExtensions
});
}
});
}
}
if ((0, _experiments.editorExperiment)('platform_editor_block_menu', true, {
exposure: true
})) {
(0, _registerBlockMenuItems.registerBlockMenuItems)({
extensionList: extensionList,
api: api,
editorViewRef: editorViewRef
});
}
return {
name: 'selectionExtension',
getSharedState: function getSharedState(editorState) {
if (!editorState) {
return null;
}
return _main.selectionExtensionPluginKey.getState(editorState) || null;
},
commands: {
setActiveExtension: function setActiveExtension(extension) {
return function (_ref4) {
var tr = _ref4.tr;
return tr.setMeta(_main.selectionExtensionPluginKey, {
type: 'set-active-extension',
extension: extension
});
};
},
clearActiveExtension: function clearActiveExtension() {
return function (_ref5) {
var tr = _ref5.tr;
return tr.setMeta(_main.selectionExtensionPluginKey, {
type: 'clear-active-extension'
});
};
}
},
actions: {
replaceWithAdf: function replaceWithAdf(nodeAdf) {
if (!editorViewRef.current) {
return {
status: 'failed-to-replace'
};
}
var _editorViewRef$curren = editorViewRef.current,
state = _editorViewRef$curren.state,
dispatch = _editorViewRef$curren.dispatch;
return (0, _replaceWithAdf2.replaceWithAdf)(nodeAdf, api)(state, dispatch);
},
insertAdfAtEndOfDoc: function insertAdfAtEndOfDoc(nodeAdf) {
if (!editorViewRef.current) {
return {
status: 'failed'
};
}
var _editorViewRef$curren2 = editorViewRef.current,
state = _editorViewRef$curren2.state,
dispatch = _editorViewRef$curren2.dispatch;
return (0, _insertAdfAtEndOfDoc2.insertAdfAtEndOfDoc)(nodeAdf)(state, dispatch);
},
getSelectionAdf: function getSelectionAdf() {
if (!editorViewRef.current) {
return null;
}
var state = editorViewRef.current.state;
if ((0, _experiments.editorExperiment)('platform_editor_block_menu', true, {
exposure: true
})) {
var _api$blockControls;
var selection = (api === null || api === void 0 || (_api$blockControls = api.blockControls) === null || _api$blockControls === void 0 || (_api$blockControls = _api$blockControls.sharedState.currentState()) === null || _api$blockControls === void 0 ? void 0 : _api$blockControls.preservedSelection) || state.selection;
return (0, _utils.getSelectionAdfInfoNew)(selection);
}
var _getSelectionAdfInfo = (0, _utils.getSelectionAdfInfo)(state),
selectionRanges = _getSelectionAdfInfo.selectionRanges,
selectedNodeAdf = _getSelectionAdfInfo.selectedNodeAdf;
return {
selectedNodeAdf: selectedNodeAdf,
selectionRanges: selectionRanges
};
},
getDocumentFromSelection: function getDocumentFromSelection() {
if (!editorViewRef.current) {
return null;
}
var state = editorViewRef.current.state;
if ((0, _experiments.editorExperiment)('platform_editor_block_menu', true, {
exposure: true
})) {
var _api$blockControls2;
var selection = (api === null || api === void 0 || (_api$blockControls2 = api.blockControls) === null || _api$blockControls2 === void 0 || (_api$blockControls2 = _api$blockControls2.sharedState.currentState()) === null || _api$blockControls2 === void 0 ? void 0 : _api$blockControls2.preservedSelection) || state.selection;
return (0, _utils.getFragmentInfoFromSelectionNew)(selection);
}
var _getFragmentInfoFromS = (0, _utils.getFragmentInfoFromSelection)(state),
selectedNodeAdf = _getFragmentInfoFromS.selectedNodeAdf;
return {
selectedNodeAdf: selectedNodeAdf
};
}
},
usePluginHook: function usePluginHook() {
(0, _usePluginStateEffect.usePluginStateEffect)(api, ['selection'], function () {
if ((0, _coreUtils.isSSR)()) {
return;
}
if (isToolbarAIFCEnabled) {
var _api$toolbar;
api === null || api === void 0 || (_api$toolbar = api.toolbar) === null || _api$toolbar === void 0 || _api$toolbar.actions.registerComponents((0, _toolbarComponents.getToolbarComponents)({
api: api,
config: config
}), true);
}
});
},
contentComponent: function contentComponent(_ref6) {
var _api$analytics;
var editorView = _ref6.editorView;
if (!editorView || (0, _coreUtils.isSSR)()) {
return null;
}
return /*#__PURE__*/_react.default.createElement(_SelectionExtensionComponentWrapper.SelectionExtensionComponentWrapper, {
editorView: editorView,
api: api,
editorAnalyticsAPI: api === null || api === void 0 || (_api$analytics = api.analytics) === null || _api$analytics === void 0 ? void 0 : _api$analytics.actions
});
},
pluginsOptions: {
selectionToolbar: isToolbarAIFCEnabled ? undefined : function (state, intl) {
var _api$editorViewMode;
if (!config) {
return;
}
var pageModes = config.pageModes;
// Extensions Config Validation
// Check whether plugin contains any selection extensions
if (!(firstParty !== null && firstParty !== void 0 && firstParty.length) && !(external !== null && external !== void 0 && external.length) && !(extensionList !== null && extensionList !== void 0 && extensionList.length)) {
return;
}
// Content Mode Validation
// Check if pageModes is provided and matches against current content mode
// This will eventually transition from mode to viewMode
var editorViewMode = api === null || api === void 0 || (_api$editorViewMode = api.editorViewMode) === null || _api$editorViewMode === void 0 || (_api$editorViewMode = _api$editorViewMode.sharedState.currentState()) === null || _api$editorViewMode === void 0 ? void 0 : _api$editorViewMode.mode;
if (pageModes) {
// Early Exit: consumer has set pageModes but editorViewMode is undefined
if (!editorViewMode) {
return;
}
// Simplify traversion of pageModes which can be string or array of strings
var showOnModesCollection = Array.isArray(pageModes) ? pageModes : [pageModes];
// Early Exit: consumer has set pageModes but current editorViewMode is not in the collection
if (!showOnModesCollection.includes(editorViewMode)) {
return;
}
}
// Active Extension
// Check if there is an active extension and hide the selection extension dropdown
var selectionExtensionState = _main.selectionExtensionPluginKey.getState(state);
if (selectionExtensionState !== null && selectionExtensionState !== void 0 && selectionExtensionState.activeExtension) {
return;
}
var handleOnExtensionClick = function handleOnExtensionClick(view) {
return function (extension) {
var _extension$onClick, _api$core;
var selection = (0, _utils.getSelectionTextInfo)(view, api);
if (extension.component) {
api === null || api === void 0 || api.core.actions.execute(api === null || api === void 0 ? void 0 : api.selectionExtension.commands.setActiveExtension({
extension: extension,
selection: selection
}));
}
var _getSelectionAdfInfo2 = (0, _utils.getSelectionAdfInfo)(view.state),
selectedNodeAdf = _getSelectionAdfInfo2.selectedNodeAdf,
selectionRanges = _getSelectionAdfInfo2.selectionRanges,
selectedNode = _getSelectionAdfInfo2.selectedNode,
nodePos = _getSelectionAdfInfo2.nodePos;
var onClickCallbackOptions = {
selectedNodeAdf: selectedNodeAdf,
selectionRanges: selectionRanges
};
(_extension$onClick = extension.onClick) === null || _extension$onClick === void 0 || _extension$onClick.call(extension, onClickCallbackOptions);
api === null || api === void 0 || (_api$core = api.core) === null || _api$core === void 0 || _api$core.actions.execute(function (_ref7) {
var tr = _ref7.tr;
tr.setMeta(_main.selectionExtensionPluginKey, {
type: _types.SelectionExtensionActionTypes.SET_SELECTED_NODE,
selectedNode: selectedNode,
nodePos: nodePos
});
return tr;
});
};
};
var convertExtensionToDropdownMenuItem = function convertExtensionToDropdownMenuItem(extension, rank) {
var _extension$isDisabled;
var disabled = (extension === null || extension === void 0 ? void 0 : extension.isDisabled) instanceof Function ? extension === null || extension === void 0 || (_extension$isDisabled = extension.isDisabled) === null || _extension$isDisabled === void 0 ? void 0 : _extension$isDisabled.call(extension, {
selection: editorViewRef.current ? (0, _utils.getSelectionTextInfo)(editorViewRef.current, api) : undefined
}) : extension === null || extension === void 0 ? void 0 : extension.isDisabled;
return {
title: extension.name,
icon: extension.icon ? /*#__PURE__*/_react.default.createElement(extension.icon, {
label: ''
}) : undefined,
disabled: disabled,
rank: rank,
onClick: function onClick() {
editorViewRef.current && handleOnExtensionClick(editorViewRef.current)(extension);
return true;
}
};
};
var getFirstPartyExtensions = function getFirstPartyExtensions(extensions) {
return extensions.map(function (extension) {
return convertExtensionToDropdownMenuItem(extension, 30);
});
};
// Add a heading to the external extensions
var getExternalExtensions = function getExternalExtensions(extensions) {
var externalExtensions = [];
if (extensions !== null && extensions !== void 0 && extensions.length) {
externalExtensions = extensions.map(function (extension) {
return convertExtensionToDropdownMenuItem(extension);
});
var externalExtensionsHeading = {
type: 'overflow-dropdown-heading',
title: intl.formatMessage(_messages.selectionExtensionMessages.externalExtensionsHeading)
};
externalExtensions.unshift(externalExtensionsHeading);
}
return externalExtensions;
};
// NEXT PR: Make sure we cache the whole generated selection toolbar
// also debug this to make sure it's actually preventing unnecessary re-renders / work
if (cachedOverflowMenuOptions && state.selection.eq(cachedSelection)) {
return (0, _selectionToolbar.selectionToolbar)({
overflowOptions: cachedOverflowMenuOptions,
extensionList: extensionList
});
}
var allFirstParty = [].concat((0, _toConsumableArray2.default)(firstParty), (0, _toConsumableArray2.default)((0, _extensions.getMenuItemExtensions)(extensionList, 'first-party')));
var allExternal = [].concat((0, _toConsumableArray2.default)(external), (0, _toConsumableArray2.default)((0, _extensions.getMenuItemExtensions)(extensionList, 'external')));
var groupedExtensionsArray = [].concat((0, _toConsumableArray2.default)(getFirstPartyExtensions(allFirstParty)), (0, _toConsumableArray2.default)(getExternalExtensions(allExternal)));
cachedOverflowMenuOptions = groupedExtensionsArray;
cachedSelection = state.selection;
return (0, _selectionToolbar.selectionToolbar)({
overflowOptions: cachedOverflowMenuOptions,
extensionList: extensionList
});
}
},
pmPlugins: function pmPlugins() {
return [{
name: 'selectionExtension',
plugin: function plugin() {
return (0, _main.createPlugin)();
}
}, {
name: 'selectionExtensionGetEditorViewReferencePlugin',
plugin: function plugin() {
return new _safePlugin.SafePlugin({
view: function view(editorView) {
editorViewRef.current = editorView;
return {
destroy: function destroy() {
delete editorViewRef.current;
}
};
}
});
}
}];
}
};
};