UNPKG

@atlaskit/editor-plugin-layout

Version:

Layout plugin for @atlaskit/editor-core

274 lines (272 loc) 13.4 kB
import React from 'react'; import { layoutColumn, layoutSection, layoutColumnWithLocalId, layoutSectionWithLocalId } from '@atlaskit/adf-schema'; import { layoutSectionWithSingleColumn, layoutSectionWithSingleColumnLocalId } from '@atlaskit/adf-schema/schema'; import { ACTION, ACTION_SUBJECT, ACTION_SUBJECT_ID, EVENT_TYPE, INPUT_METHOD } from '@atlaskit/editor-common/analytics'; import { TRANSFORM_STRUCTURE_LAYOUT_MENU_ITEM, TRANSFORM_STRUCTURE_MENU_SECTION, TRANSFORM_STRUCTURE_MENU_SECTION_RANK } from '@atlaskit/editor-common/block-menu'; import { layoutMessages, toolbarInsertBlockMessages as messages } from '@atlaskit/editor-common/messages'; import { IconFiveColumnLayout, IconFourColumnLayout, IconLayout, IconOneColumnLayout, IconThreeColumnLayout, IconTwoColumnLayout } from '@atlaskit/editor-common/quick-insert'; import { TextSelection } from '@atlaskit/editor-prosemirror/state'; import { findParentNode } from '@atlaskit/editor-prosemirror/utils'; import { fg } from '@atlaskit/platform-feature-flags'; import { editorExperiment } from '@atlaskit/tmp-editor-statsig/experiments'; var LAYOUT_SECTION_NODE_NAME = 'layoutSection'; import { createDefaultLayoutSection, createMultiColumnLayoutSection, insertLayoutColumnsWithAnalytics } from './pm-plugins/actions'; import { default as createLayoutPlugin } from './pm-plugins/main'; import { pluginKey } from './pm-plugins/plugin-key'; import { default as createLayoutResizingPlugin } from './pm-plugins/resizing'; import { GlobalStylesWrapper } from './ui/global-styles'; import { createLayoutBlockMenuItem } from './ui/LayoutBlockMenuItem'; import { buildToolbar } from './ui/toolbar'; /** * This function is used to set the selection into * the first paragraph of the first column of a layout section. * This function is only intended to be used after inserting a new layout section. * @param tr - transaction * @returns - transaction with the selection set to the first paragraph of the first column */ export var selectIntoLayoutSection = function selectIntoLayoutSection(tr) { var _nodeWithPos$node$fir; if (!editorExperiment('single_column_layouts', true)) { return tr; } var _tr$doc$type$schema$n = tr.doc.type.schema.nodes, layoutSection = _tr$doc$type$schema$n.layoutSection, paragraph = _tr$doc$type$schema$n.paragraph; var nodeWithPos = findParentNode(function (node) { return node.type === layoutSection; })(tr.selection); if (!nodeWithPos || !nodeWithPos.node || nodeWithPos.node.type.name !== 'layoutSection' || ((_nodeWithPos$node$fir = nodeWithPos.node.firstChild) === null || _nodeWithPos$node$fir === void 0 || (_nodeWithPos$node$fir = _nodeWithPos$node$fir.firstChild) === null || _nodeWithPos$node$fir === void 0 ? void 0 : _nodeWithPos$node$fir.type) !== paragraph) { return tr; } // set text selection at the beginning of the layout section // will set the selection to the first column tr.setSelection(TextSelection.create(tr.doc, nodeWithPos.pos)); return tr; }; export var layoutPlugin = function layoutPlugin(_ref) { var _api$analytics; var _ref$config = _ref.config, options = _ref$config === void 0 ? {} : _ref$config, api = _ref.api; var allowAdvancedSingleColumnLayout = editorExperiment('advanced_layouts', true) && editorExperiment('single_column_layouts', true, { exposure: true }); if (editorExperiment('platform_editor_block_menu', true)) { var _api$blockMenu; api === null || api === void 0 || (_api$blockMenu = api.blockMenu) === null || _api$blockMenu === void 0 || _api$blockMenu.actions.registerBlockMenuComponents([{ type: 'block-menu-item', key: TRANSFORM_STRUCTURE_LAYOUT_MENU_ITEM.key, parent: { type: 'block-menu-section', key: TRANSFORM_STRUCTURE_MENU_SECTION.key, rank: TRANSFORM_STRUCTURE_MENU_SECTION_RANK[TRANSFORM_STRUCTURE_LAYOUT_MENU_ITEM.key] }, component: createLayoutBlockMenuItem(api), isHidden: function isHidden() { var _api$blockMenu2; return Boolean(api === null || api === void 0 || (_api$blockMenu2 = api.blockMenu) === null || _api$blockMenu2 === void 0 ? void 0 : _api$blockMenu2.actions.isTransformOptionDisabled(LAYOUT_SECTION_NODE_NAME)); } }]); } return { name: 'layout', nodes: function nodes() { return [{ name: 'layoutSection', node: editorExperiment('advanced_layouts', true) ? fg('platform_editor_adf_with_localid') ? layoutSectionWithSingleColumnLocalId : layoutSectionWithSingleColumn : fg('platform_editor_adf_with_localid') ? layoutSectionWithLocalId : layoutSection }, { name: 'layoutColumn', node: fg('platform_editor_adf_with_localid') ? layoutColumnWithLocalId : layoutColumn }]; }, pmPlugins: function pmPlugins() { var plugins = [{ name: 'layout', plugin: function plugin() { return createLayoutPlugin(options); } }]; if ((options.editorAppearance === 'full-page' || options.editorAppearance === 'full-width' || options.editorAppearance === 'max' && editorExperiment('platform_editor_layout_column_resize_handle', true)) && api && editorExperiment('advanced_layouts', true)) { plugins.push({ name: 'layoutResizing', plugin: function plugin(_ref2) { var portalProviderAPI = _ref2.portalProviderAPI, eventDispatcher = _ref2.eventDispatcher; return createLayoutResizingPlugin(options, api, portalProviderAPI, eventDispatcher); } }); } return plugins; }, actions: { insertLayoutColumns: insertLayoutColumnsWithAnalytics(api === null || api === void 0 || (_api$analytics = api.analytics) === null || _api$analytics === void 0 ? void 0 : _api$analytics.actions) }, pluginsOptions: { floatingToolbar: function floatingToolbar(state, intl) { var _ref3 = pluginKey.getState(state), pos = _ref3.pos, allowBreakout = _ref3.allowBreakout, addSidebarLayouts = _ref3.addSidebarLayouts, allowSingleColumnLayout = _ref3.allowSingleColumnLayout, isResizing = _ref3.isResizing; var shouldHideToolbar = isResizing && editorExperiment('single_column_layouts', true); if (pos !== null && !shouldHideToolbar) { return buildToolbar(state, intl, pos, allowBreakout, addSidebarLayouts, allowSingleColumnLayout, allowAdvancedSingleColumnLayout, api); } return undefined; }, quickInsert: function quickInsert(_ref4) { var formatMessage = _ref4.formatMessage; var withInsertLayoutAnalytics = function withInsertLayoutAnalytics(tr, columnCount) { var _api$analytics2; api === null || api === void 0 || (_api$analytics2 = api.analytics) === null || _api$analytics2 === void 0 || (_api$analytics2 = _api$analytics2.actions) === null || _api$analytics2 === void 0 || _api$analytics2.attachAnalyticsEvent({ action: ACTION.INSERTED, actionSubject: ACTION_SUBJECT.DOCUMENT, actionSubjectId: ACTION_SUBJECT_ID.LAYOUT, attributes: { inputMethod: INPUT_METHOD.QUICK_INSERT, columnCount: columnCount }, eventType: EVENT_TYPE.TRACK })(tr); return tr; }; var advancedSingleColumnOption = allowAdvancedSingleColumnLayout ? [{ id: 'onecolumnlayout', title: formatMessage(layoutMessages.singleColumnAdvancedLayout), description: formatMessage(messages.singleColumnsDescriptionAdvancedLayout), keywords: ['layout', 'column', 'section', 'single column'], priority: 1100, icon: function icon() { return /*#__PURE__*/React.createElement(IconOneColumnLayout, null); }, action: function action(insert, state) { var tr = insert(createMultiColumnLayoutSection(state, 1)); if (fg('platform_editor_column_count_analytics')) { withInsertLayoutAnalytics(tr, 1); } else { withInsertLayoutAnalytics(tr); } selectIntoLayoutSection(tr); return tr; } }] : []; if (editorExperiment('advanced_layouts', true)) { return [].concat(advancedSingleColumnOption, [{ id: 'twocolumnslayout', title: formatMessage(layoutMessages.twoColumnsAdvancedLayout), description: formatMessage(messages.columnsDescriptionAdvancedLayout, { numberOfColumns: 'two' }), keywords: ['layout', 'column', 'section', 'two column'], priority: 1100, icon: function icon() { return /*#__PURE__*/React.createElement(IconTwoColumnLayout, null); }, action: function action(insert, state) { var tr = insert(createMultiColumnLayoutSection(state, 2)); if (fg('platform_editor_column_count_analytics')) { withInsertLayoutAnalytics(tr, 2); } else { withInsertLayoutAnalytics(tr); } selectIntoLayoutSection(tr); return tr; } }, { id: 'threecolumnslayout', title: formatMessage(layoutMessages.threeColumnsAdvancedLayout), description: formatMessage(messages.columnsDescriptionAdvancedLayout, { numberOfColumns: 'three' }), keywords: ['layout', 'column', 'section', 'three column'], priority: 1100, icon: function icon() { return /*#__PURE__*/React.createElement(IconThreeColumnLayout, null); }, action: function action(insert, state) { var tr = insert(createMultiColumnLayoutSection(state, 3)); if (fg('platform_editor_column_count_analytics')) { withInsertLayoutAnalytics(tr, 3); } else { withInsertLayoutAnalytics(tr); } selectIntoLayoutSection(tr); return tr; } }, { id: 'fourcolumnslayout', title: formatMessage(layoutMessages.fourColumns), description: formatMessage(messages.columnsDescriptionAdvancedLayout, { numberOfColumns: 'four' }), keywords: ['layout', 'column', 'section', 'four column'], priority: 1100, icon: function icon() { return /*#__PURE__*/React.createElement(IconFourColumnLayout, null); }, action: function action(insert, state) { var tr = insert(createMultiColumnLayoutSection(state, 4)); if (fg('platform_editor_column_count_analytics')) { withInsertLayoutAnalytics(tr, 4); } else { withInsertLayoutAnalytics(tr); } selectIntoLayoutSection(tr); return tr; } }, { id: 'fivecolumnslayout', title: formatMessage(layoutMessages.fiveColumns), description: formatMessage(messages.columnsDescriptionAdvancedLayout, { numberOfColumns: 'five' }), keywords: ['layout', 'column', 'section', 'five column'], priority: 1100, icon: function icon() { return /*#__PURE__*/React.createElement(IconFiveColumnLayout, null); }, action: function action(insert, state) { var tr = insert(createMultiColumnLayoutSection(state, 5)); if (fg('platform_editor_column_count_analytics')) { withInsertLayoutAnalytics(tr, 5); } else { withInsertLayoutAnalytics(tr); } selectIntoLayoutSection(tr); return tr; } }]); } else { return [{ id: 'layout', title: formatMessage(messages.columns), description: formatMessage(messages.columnsDescription), keywords: ['column', 'section'], priority: 1100, icon: function icon() { return /*#__PURE__*/React.createElement(IconLayout, null); }, action: function action(insert, state) { var _api$analytics3; var tr = insert(createDefaultLayoutSection(state)); api === null || api === void 0 || (_api$analytics3 = api.analytics) === null || _api$analytics3 === void 0 || (_api$analytics3 = _api$analytics3.actions) === null || _api$analytics3 === void 0 || _api$analytics3.attachAnalyticsEvent({ action: ACTION.INSERTED, actionSubject: ACTION_SUBJECT.DOCUMENT, actionSubjectId: ACTION_SUBJECT_ID.LAYOUT, attributes: { inputMethod: INPUT_METHOD.QUICK_INSERT }, eventType: EVENT_TYPE.TRACK })(tr); return tr; } }]; } } }, contentComponent: function contentComponent() { return editorExperiment('advanced_layouts', true) ? /*#__PURE__*/React.createElement(GlobalStylesWrapper, null) : null; } }; };