UNPKG

@atlaskit/editor-plugin-selection-extension

Version:

editor-plugin-selection-extension plugin for @atlaskit/editor-core

333 lines (325 loc) 16.1 kB
"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; } }; } }); } }]; } }; };