UNPKG

@atlaskit/editor-plugin-layout

Version:

Layout plugin for @atlaskit/editor-core

234 lines (229 loc) 12.4 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports.default = exports.DEFAULT_LAYOUT = void 0; var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray")); var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty")); var _safePlugin = require("@atlaskit/editor-common/safe-plugin"); var _selection = require("@atlaskit/editor-common/selection"); var _utils = require("@atlaskit/editor-common/utils"); var _keymap = require("@atlaskit/editor-prosemirror/keymap"); var _model = require("@atlaskit/editor-prosemirror/model"); var _state = require("@atlaskit/editor-prosemirror/state"); var _utils2 = require("@atlaskit/editor-prosemirror/utils"); var _view2 = require("@atlaskit/editor-prosemirror/view"); var _experiments = require("@atlaskit/tmp-editor-statsig/experiments"); var _actions = require("./actions"); var _columnResizeDivider = require("./column-resize-divider"); var _consts = require("./consts"); var _pluginKey = require("./plugin-key"); var _resizing = require("./resizing"); var _utils3 = require("./utils"); function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; } function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { (0, _defineProperty2.default)(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; } var DEFAULT_LAYOUT = exports.DEFAULT_LAYOUT = 'two_equal'; var isWholeSelectionInsideLayoutColumn = function isWholeSelectionInsideLayoutColumn(state) { // Since findParentNodeOfType doesn't check if selection.to shares the parent, we do this check ourselves var fromParent = (0, _utils2.findParentNodeOfType)(state.schema.nodes.layoutColumn)(state.selection); if (fromParent) { var isToPosInsideSameLayoutColumn = state.selection.from < fromParent.pos + fromParent.node.nodeSize; return isToPosInsideSameLayoutColumn; } return false; }; var moveCursorToNextColumn = function moveCursorToNextColumn(state, dispatch) { var selection = state.selection; var _state$schema$nodes = state.schema.nodes, layoutColumn = _state$schema$nodes.layoutColumn, layoutSection = _state$schema$nodes.layoutSection; // Ignored via go/ees005 // eslint-disable-next-line @typescript-eslint/no-non-null-assertion var section = (0, _utils2.findParentNodeOfType)(layoutSection)(selection); // Ignored via go/ees005 // eslint-disable-next-line @typescript-eslint/no-non-null-assertion var column = (0, _utils2.findParentNodeOfType)(layoutColumn)(selection); if (column.node !== section.node.lastChild) { var $nextColumn = state.doc.resolve(column.pos + column.node.nodeSize); var shiftedSelection = _state.TextSelection.findFrom($nextColumn, 1); if (dispatch) { dispatch(state.tr.setSelection(shiftedSelection)); } } return true; }; var getNodeDecoration = function getNodeDecoration(pos, node) { return [_view2.Decoration.node(pos, pos + node.nodeSize, { class: 'selected' })]; }; var getInitialPluginState = function getInitialPluginState(options, state) { var maybeLayoutSection = (0, _utils3.getMaybeLayoutSection)(state); var allowBreakout = options.allowBreakout || false; var addSidebarLayouts = options.UNSAFE_addSidebarLayouts || false; var allowSingleColumnLayout = options.UNSAFE_allowSingleColumnLayout || false; var pos = maybeLayoutSection ? maybeLayoutSection.pos : null; var selectedLayout = (0, _actions.getSelectedLayout)(maybeLayoutSection && maybeLayoutSection.node, DEFAULT_LAYOUT); return { pos: pos, allowBreakout: allowBreakout, addSidebarLayouts: addSidebarLayouts, selectedLayout: selectedLayout, allowSingleColumnLayout: allowSingleColumnLayout, isResizing: false }; }; // To prevent a single-column layout, // if a user attempts to delete a layout column and // we will force remove the content instead. // There are some edge cases where user can delete a layout column // see packages/editor/editor-plugin-layout-tests/src/__tests__/unit/delete.ts var handleDeleteLayoutColumn = function handleDeleteLayoutColumn(state, dispatch) { var sel = state.selection; if (sel instanceof _state.NodeSelection && sel.node.type.name === 'layoutColumn' && sel.$from.parent.type.name === 'layoutSection' && sel.$from.parent.childCount === 2 && dispatch && (0, _experiments.editorExperiment)('advanced_layouts', true) && !(0, _experiments.editorExperiment)('single_column_layouts', true)) { var _sel$$from$parent$las, _sel$$from$parent$fir; var tr = state.tr; var layoutContentFragment = sel.$from.parentOffset === 0 ? _model.Fragment.from((_sel$$from$parent$las = sel.$from.parent.lastChild) === null || _sel$$from$parent$las === void 0 ? void 0 : _sel$$from$parent$las.content) : _model.Fragment.from((_sel$$from$parent$fir = sel.$from.parent.firstChild) === null || _sel$$from$parent$fir === void 0 ? void 0 : _sel$$from$parent$fir.content); var parent = (0, _utils2.findParentNodeClosestToPos)(sel.$from, function (node) { return node.type.name === 'layoutSection'; }); if (parent) { var layoutSectionPos = tr.mapping.map(parent.pos); var layoutSectionNodeSize = parent.node.nodeSize; dispatch(state.tr.replaceWith(layoutSectionPos, layoutSectionPos + layoutSectionNodeSize, layoutContentFragment)); return true; } return false; } return false; }; var _default = exports.default = function _default(options) { // Store a reference to the EditorView so widget decorations can dispatch transactions var editorViewRef; return new _safePlugin.SafePlugin({ key: _pluginKey.pluginKey, view: function view(_view) { editorViewRef = _view; return { update: function update(updatedView) { editorViewRef = updatedView; }, destroy: function destroy() { editorViewRef = undefined; } }; }, state: { init: function init(_, state) { return getInitialPluginState(options, state); }, apply: function apply(tr, pluginState, oldState, newState) { var _tr$getMeta, _pluginKey$getState; var isResizing = (0, _experiments.editorExperiment)('single_column_layouts', true) ? (_tr$getMeta = tr.getMeta('is-resizer-resizing')) !== null && _tr$getMeta !== void 0 ? _tr$getMeta : (_pluginKey$getState = _pluginKey.pluginKey.getState(oldState)) === null || _pluginKey$getState === void 0 ? void 0 : _pluginKey$getState.isResizing : false; if (tr.docChanged || tr.selectionSet) { var maybeLayoutSection = (0, _utils3.getMaybeLayoutSection)(newState); var newPluginState = _objectSpread(_objectSpread({}, pluginState), {}, { pos: maybeLayoutSection ? maybeLayoutSection.pos : null, isResizing: isResizing, selectedLayout: (0, _actions.getSelectedLayout)(maybeLayoutSection && maybeLayoutSection.node, // Ignored via go/ees005 // eslint-disable-next-line @typescript-eslint/no-non-null-assertion pluginState.selectedLayout) }); return newPluginState; } return _objectSpread(_objectSpread({}, pluginState), {}, { isResizing: isResizing }); } }, props: { decorations: function decorations(state) { var layoutState = _pluginKey.pluginKey.getState(state); var isLayoutResizingPluginAvailable = _resizing.pluginKey.get(state) !== undefined; if ((0, _experiments.editorExperiment)('advanced_layouts', true) && (0, _experiments.editorExperiment)('platform_editor_layout_column_resize_handle', true) && isLayoutResizingPluginAvailable) { var dividerDecorations = (0, _columnResizeDivider.getColumnDividerDecorations)(state, editorViewRef); var selectedDecorations = layoutState.pos !== null ? getNodeDecoration(layoutState.pos, state.doc.nodeAt(layoutState.pos)) : []; var allDecorations = [].concat((0, _toConsumableArray2.default)(selectedDecorations), (0, _toConsumableArray2.default)(dividerDecorations)); if (allDecorations.length > 0) { return _view2.DecorationSet.create(state.doc, allDecorations); } return undefined; } if (layoutState.pos !== null) { return _view2.DecorationSet.create(state.doc, getNodeDecoration(layoutState.pos, state.doc.nodeAt(layoutState.pos))); } return undefined; }, handleKeyDown: (0, _keymap.keydownHandler)({ Tab: (0, _utils.filterCommand)(isWholeSelectionInsideLayoutColumn, moveCursorToNextColumn), 'Mod-Backspace': handleDeleteLayoutColumn, 'Mod-Delete': handleDeleteLayoutColumn, Backspace: handleDeleteLayoutColumn, Delete: handleDeleteLayoutColumn }), handleClickOn: (0, _selection.createSelectionClickHandler)(['layoutColumn'], function (target) { return target.hasAttribute('data-layout-section') || target.hasAttribute('data-layout-column'); }, { useLongPressSelection: options.useLongPressSelection || false, getNodeSelectionPos: function getNodeSelectionPos(state, nodePos) { return state.doc.resolve(nodePos).before(); } }) }, appendTransaction: function appendTransaction(transactions, _oldState, newState) { var changes = []; transactions.forEach(function (prevTr) { // remap change segments across the transaction set changes.forEach(function (change) { return { from: prevTr.mapping.map(change.from), to: prevTr.mapping.map(change.to), slice: change.slice }; }); // don't consider transactions that don't mutate if (!prevTr.docChanged) { return; } // Skip fixing column sizes for column resize drag transactions if ((0, _experiments.editorExperiment)('platform_editor_layout_column_resize_handle', true) && prevTr.getMeta('layoutColumnResize')) { return; } var change = (0, _actions.fixColumnSizes)(prevTr, newState); if (change) { changes.push(change); } }); if ((0, _experiments.editorExperiment)('advanced_layouts', true) && changes.length === 1) { var _change$slice$content, _change$slice$content2; var change = changes[0]; // When editorExperiment('single_column_layouts', true) is on // delete can create a single column layout // otherwise we replace the single column layout with its content if (!(0, _experiments.editorExperiment)('single_column_layouts', true) && change.slice.content.childCount === 1 && ((_change$slice$content = change.slice.content.firstChild) === null || _change$slice$content === void 0 ? void 0 : _change$slice$content.type.name) === 'layoutColumn' && ((_change$slice$content2 = change.slice.content.firstChild) === null || _change$slice$content2 === void 0 ? void 0 : _change$slice$content2.attrs.width) === _consts.EVEN_DISTRIBUTED_COL_WIDTHS[1]) { var tr = newState.tr; var content = change.slice.content.firstChild.content; tr.replaceWith(change.from - 1, change.to, content); return tr; } } if (changes.length) { var _tr = newState.tr; var selection = newState.selection.toJSON(); changes.forEach(function (change) { _tr.replaceRange(change.from, change.to, change.slice); }); // selecting and deleting across columns in 3 col layouts can remove // a layoutColumn so we fix the structure here _tr = (0, _actions.fixColumnStructure)(newState) || _tr; if (_tr.docChanged) { _tr.setSelection(_state.Selection.fromJSON(_tr.doc, selection)); return _tr; } } return; } }); };