UNPKG

@atlaskit/editor-plugin-panel

Version:

Panel plugin for @atlaskit/editor-core.

282 lines (281 loc) 9.63 kB
import React from 'react'; import { extendedPanel, extendedPanelWithLocalId, PanelType } from '@atlaskit/adf-schema'; import { ACTION, ACTION_SUBJECT, ACTION_SUBJECT_ID, EVENT_TYPE, INPUT_METHOD } from '@atlaskit/editor-common/analytics'; import { TRANSFORM_STRUCTURE_PANEL_MENU_ITEM, TRANSFORM_STRUCTURE_MENU_SECTION, TRANSFORM_STRUCTURE_MENU_SECTION_RANK } from '@atlaskit/editor-common/block-menu'; import { insertSelectedItem } from '@atlaskit/editor-common/insert'; import { blockTypeMessages } from '@atlaskit/editor-common/messages'; import { IconCustomPanel, IconPanel, IconPanelError, IconPanelNote, IconPanelSuccess, IconPanelWarning } from '@atlaskit/editor-common/quick-insert'; import { createWrapSelectionTransaction } from '@atlaskit/editor-common/utils'; import { fg } from '@atlaskit/platform-feature-flags'; import { editorExperiment } from '@atlaskit/tmp-editor-statsig/experiments'; import keymap from './pm-plugins/keymaps'; import { createPlugin } from './pm-plugins/main'; import { createPanelBlockMenuItem } from './ui/panelBlockMenuItem'; import { getToolbarConfig } from './ui/toolbar'; const PANEL_NODE_NAME = 'panel'; const panelPlugin = ({ config: { allowCustomPanel = false, allowCustomPanelEdit = false } = {}, api }) => { if (editorExperiment('platform_editor_block_menu', true)) { var _api$blockMenu; api === null || api === void 0 ? void 0 : (_api$blockMenu = api.blockMenu) === null || _api$blockMenu === void 0 ? void 0 : _api$blockMenu.actions.registerBlockMenuComponents([{ type: 'block-menu-item', key: TRANSFORM_STRUCTURE_PANEL_MENU_ITEM.key, parent: { type: 'block-menu-section', key: TRANSFORM_STRUCTURE_MENU_SECTION.key, rank: TRANSFORM_STRUCTURE_MENU_SECTION_RANK[TRANSFORM_STRUCTURE_PANEL_MENU_ITEM.key] }, component: createPanelBlockMenuItem(api), isHidden: () => { var _api$blockMenu2; return Boolean(api === null || api === void 0 ? void 0 : (_api$blockMenu2 = api.blockMenu) === null || _api$blockMenu2 === void 0 ? void 0 : _api$blockMenu2.actions.isTransformOptionDisabled(PANEL_NODE_NAME)); } }]); } return { name: 'panel', nodes() { if (fg('platform_editor_adf_with_localid')) { return [{ name: 'panel', node: { ...extendedPanelWithLocalId(!!allowCustomPanel), definingAsContext: true } }]; } return [{ name: 'panel', node: extendedPanel(!!allowCustomPanel) }]; }, pmPlugins() { return [{ name: 'panel', plugin: ({ providerFactory, dispatch, nodeViewPortalProviderAPI }) => createPlugin(dispatch, providerFactory, { allowCustomPanel, allowCustomPanelEdit }, api, nodeViewPortalProviderAPI) }, { name: 'panelKeyMap', plugin: () => keymap() }]; }, actions: { insertPanel(inputMethod) { return function (state, dispatch) { const tr = createPanelAction({ state, attributes: { panelType: PanelType.INFO }, api, inputMethod }); if (!tr) { return false; } if (dispatch) { dispatch(tr); } return true; }; } }, pluginsOptions: { quickInsert: ({ formatMessage }) => { const quickInsertOptions = [{ id: 'infopanel', title: formatMessage(blockTypeMessages.infoPanel), keywords: ['panel'], description: formatMessage(blockTypeMessages.infoPanelDescription), priority: 800, icon: () => /*#__PURE__*/React.createElement(IconPanel, null), action(typeAheadInsert, state) { return createPanelAction({ state, attributes: { panelType: PanelType.INFO }, api, typeAheadInsert }); } }, { id: 'notepanel', title: formatMessage(blockTypeMessages.notePanel), description: formatMessage(blockTypeMessages.notePanelDescription), priority: 1000, icon: () => /*#__PURE__*/React.createElement(IconPanelNote, null), action(typeAheadInsert, state) { return createPanelAction({ state, attributes: { panelType: PanelType.NOTE }, api, typeAheadInsert }); } }, { id: 'successpanel', title: formatMessage(blockTypeMessages.successPanel), description: formatMessage(blockTypeMessages.successPanelDescription), keywords: ['tip'], priority: 1000, icon: () => /*#__PURE__*/React.createElement(IconPanelSuccess, null), action(typeAheadInsert, state) { return createPanelAction({ state, attributes: { panelType: PanelType.SUCCESS }, api, typeAheadInsert }); } }, { id: 'warningpanel', title: formatMessage(blockTypeMessages.warningPanel), description: formatMessage(blockTypeMessages.warningPanelDescription), priority: 1000, icon: () => /*#__PURE__*/React.createElement(IconPanelWarning, null), action(typeAheadInsert, state) { return createPanelAction({ state, attributes: { panelType: PanelType.WARNING }, api, typeAheadInsert }); } }, { id: 'errorpanel', title: formatMessage(blockTypeMessages.errorPanel), description: formatMessage(blockTypeMessages.errorPanelDescription), priority: 1000, icon: () => /*#__PURE__*/React.createElement(IconPanelError, null), action(typeAheadInsert, state) { return createPanelAction({ state, attributes: { panelType: PanelType.ERROR }, api, typeAheadInsert }); } }]; if (allowCustomPanel && allowCustomPanelEdit) { quickInsertOptions.push({ id: 'custompanel', title: formatMessage(blockTypeMessages.customPanel), description: formatMessage(blockTypeMessages.customPanelDescription), priority: 1000, icon: () => /*#__PURE__*/React.createElement(IconCustomPanel, null), action(typeAheadInsert, state) { return createPanelAction({ state, attributes: { panelType: PanelType.CUSTOM, panelIcon: ':rainbow:', panelIconId: '1f308', panelIconText: '🌈', // Ignored via go/ees007 // eslint-disable-next-line @atlaskit/editor/enforce-todo-comment-format // TODO: https://product-fabric.atlassian.net/browse/DSP-7268 // eslint-disable-next-line @atlaskit/design-system/ensure-design-token-usage panelColor: '#E6FCFF' }, api, typeAheadInsert }); } }); } return quickInsertOptions; }, floatingToolbar: (state, intl, providerFactory) => getToolbarConfig(state, intl, { allowCustomPanel, allowCustomPanelEdit }, providerFactory, api) } }; }; /** * Creates panel action and wrap selection transaction with analytics for the panel insertion. * * @example * const tr = createPanelAction({ * state: editorState, * attributes: { panelType: 'info' }, * }); * if (tr) { * applyTransaction(tr); * } */ function createPanelAction({ state, attributes, api, typeAheadInsert, inputMethod = INPUT_METHOD.QUICK_INSERT }) { var _tr; const { panel } = state.schema.nodes; let tr; // If the selection is empty, we want to insert the panel on a new line if (state.selection.empty) { const node = panel.createAndFill({ ...attributes }); if (!node) { return false; } if (typeAheadInsert !== undefined) { // If the type-ahead insert is provided, we should use that to insert the node tr = typeAheadInsert(node); } else { var _insertSelectedItem; // Otherwise we can use insertSelectedItem to insert the node tr = (_insertSelectedItem = insertSelectedItem(node)(state, state.tr, state.selection.head)) === null || _insertSelectedItem === void 0 ? void 0 : _insertSelectedItem.scrollIntoView(); } } else { tr = createWrapSelectionTransaction({ state, type: panel, nodeAttributes: { ...attributes } }); } if (tr) { var _api$analytics; api === null || api === void 0 ? void 0 : (_api$analytics = api.analytics) === null || _api$analytics === void 0 ? void 0 : _api$analytics.actions.attachAnalyticsEvent({ action: ACTION.INSERTED, actionSubject: ACTION_SUBJECT.DOCUMENT, actionSubjectId: ACTION_SUBJECT_ID.PANEL, attributes: { inputMethod, panelType: attributes.panelType }, eventType: EVENT_TYPE.TRACK })(tr); } return (_tr = tr) !== null && _tr !== void 0 ? _tr : false; } export default panelPlugin;