@atlaskit/editor-plugin-table
Version:
Table plugin for the @atlaskit/editor
237 lines (232 loc) • 10.4 kB
JavaScript
"use strict";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.deleteColumns = void 0;
var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
var _customSteps = require("@atlaskit/custom-steps");
var _analytics = require("@atlaskit/editor-common/analytics");
var _state = require("@atlaskit/editor-prosemirror/state");
var _tableMap = require("@atlaskit/editor-tables/table-map");
var _utils = require("@atlaskit/editor-tables/utils");
var _tableAnalytics = require("../table-analytics");
var _columnWidth = require("./column-width");
var _split = require("./split");
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 deleteColumnsCustomStep = function deleteColumnsCustomStep(rect) {
return function (tr) {
var table = (0, _utils.findTable)(tr.selection);
if (!table) {
return tr;
}
// Need to split all the merge in the ranges (this is the current behaviour)
// Maybe is better to split only the last column?
// TODO: ED-26961 - After talking with Roto about this behaviour, he likes when we dont split the columns, I am keeping this for consistency of the current implementation.
(0, _split.splitCellsInColumns)(tr, table.pos, rect.left, rect.right);
// Delete the columns
var mapStart = tr.mapping.maps.length;
var originalDoc = tr.doc;
var deletedColumns = [];
for (var i = rect.left; i < rect.right; i++) {
var step = _customSteps.AddColumnStep.create(originalDoc, table.pos, i, true);
deletedColumns.push(i);
// Ignored via go/ees005
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
tr.step(step.map(tr.mapping.slice(mapStart)));
}
var tablePosResult = tr.mapping.mapResult(table.pos);
if (tablePosResult.deleted) {
var pos = Math.min(tablePosResult.pos, tr.doc.nodeSize - 1);
tr.setSelection(_state.Selection.near(tr.doc.resolve(pos)));
} else {
var newTable = tr.doc.nodeAt(tablePosResult.pos);
if (newTable) {
var cursorPos = getNextCursorPos(newTable, deletedColumns);
tr.setSelection(_state.Selection.near(tr.doc.resolve(table.pos + cursorPos)));
}
}
return tr;
};
};
var deleteColumnsLegacy = function deleteColumnsLegacy(rect) {
return function (tr) {
var table = (0, _utils.findTable)(tr.selection);
if (!table) {
return tr;
}
var columnsToDelete = [];
for (var i = rect.left; i < rect.right; i++) {
columnsToDelete.push(i);
}
if (!columnsToDelete.length) {
return tr;
}
var map = _tableMap.TableMap.get(table.node);
var rows = [];
var seen = {};
var deletedCells = {};
for (var rowIndex = 0; rowIndex < map.height; rowIndex++) {
var rowCells = [];
var row = table.node.child(rowIndex);
var _loop = function _loop(colIndex) {
var cellPos = map.map[rowIndex * map.width + colIndex];
var cell = table.node.nodeAt(cellPos);
if (!cell) {
return 0; // continue
}
var cellsInColumn = map.cellsInRect({
left: colIndex,
top: 0,
right: colIndex + 1,
bottom: map.height
});
if (columnsToDelete.indexOf(colIndex) === -1) {
// decrement colspans for col-spanning cells that overlap deleted columns
if (cellsInColumn.indexOf(cellPos) > -1 && !seen[cellPos]) {
var overlappingCols = 0;
columnsToDelete.forEach(function (colIndexToDelete) {
if (colIndex < colIndexToDelete && cell.attrs.colspan + colIndex - 1 >= colIndexToDelete) {
overlappingCols += 1;
}
});
if (overlappingCols > 0) {
var attrs = _objectSpread(_objectSpread({}, cell.attrs), {}, {
colspan: cell.attrs.colspan - overlappingCols
});
if (cell.attrs.colwidth) {
var minColIndex = Math.min.apply(Math, columnsToDelete);
var pos = minColIndex > 0 ? minColIndex - map.colCount(cellPos) : 0;
var colwidth = cell.attrs.colwidth.slice() || [];
colwidth.splice(pos, overlappingCols);
attrs.colwidth = colwidth;
}
var newCell = cell.type.createChecked(attrs, cell.content, cell.marks);
rowCells.push(newCell);
seen[cellPos] = true;
return 0; // continue
}
} else if (deletedCells[cellPos]) {
// if we're removing a col-spanning cell, we need to add missing cells to columns to the right
var _attrs = _objectSpread(_objectSpread({}, cell.attrs), {}, {
colspan: 1,
rowspan: 1
});
if (cell.attrs.colwidth) {
var _pos = colIndex > 0 ? colIndex - map.colCount(cellPos) : 0;
_attrs.colwidth = cell.attrs.colwidth.slice().splice(_pos, 1);
}
var _newCell = cell.type.createChecked(_attrs, cell.type.schema.nodes.paragraph.createChecked(), cell.marks);
rowCells.push(_newCell);
return 0; // continue
}
// normal cells that we want to keep
if (!seen[cellPos]) {
seen[cellPos] = true;
rowCells.push(cell);
}
} else if (cellsInColumn.indexOf(cellPos) > -1) {
deletedCells[cellPos] = true;
}
},
_ret;
for (var colIndex = 0; colIndex < map.width; colIndex++) {
_ret = _loop(colIndex);
if (_ret === 0) continue;
}
if (rowCells.length) {
rows.push(row.type.createChecked(row.attrs, rowCells, row.marks));
}
}
if (!rows.length) {
return tr;
}
var newTable = table.node.type.createChecked(table.node.attrs, rows, table.node.marks);
var fixedTable = fixRowSpans(newTable);
if (fixedTable === null) {
return tr;
}
var cursorPos = getNextCursorPos(newTable, columnsToDelete);
return tr.replaceWith(table.pos, table.pos + table.node.nodeSize, fixedTable)
// move cursor to the left of the deleted columns if possible, otherwise - to the first column
.setSelection(_state.Selection.near(tr.doc.resolve(table.pos + cursorPos)));
};
};
function getNextCursorPos(table, deletedColumns) {
var minColumn = Math.min.apply(Math, (0, _toConsumableArray2.default)(deletedColumns));
var nextColumnWithCursor = minColumn > 0 ? minColumn - 1 : 0;
var map = _tableMap.TableMap.get(table);
return map.map[nextColumnWithCursor];
}
// returns an array of numbers, each number indicates the minimum rowSpan in each row
function getMinRowSpans(table) {
var minRowSpans = [];
for (var rowIndex = 0; rowIndex < table.childCount; rowIndex++) {
var rowSpans = [];
var row = table.child(rowIndex);
for (var colIndex = 0; colIndex < row.childCount; colIndex++) {
var cell = row.child(colIndex);
rowSpans.push(cell.attrs.rowspan);
}
minRowSpans[rowIndex] = Math.min.apply(Math, rowSpans);
}
return minRowSpans;
}
function fixRowSpans(table) {
var map = _tableMap.TableMap.get(table);
var minRowSpans = getMinRowSpans(table);
if (!minRowSpans.some(function (rowspan) {
return rowspan > 1;
})) {
return table;
}
var rows = [];
for (var rowIndex = 0; rowIndex < map.height; rowIndex++) {
var row = table.child(rowIndex);
if (minRowSpans[rowIndex] === 1) {
rows.push(row);
} else {
var rowCells = [];
for (var colIndex = 0; colIndex < row.childCount; colIndex++) {
var cell = row.child(colIndex);
var rowspan = cell.attrs.rowspan - minRowSpans[rowIndex] + 1;
if (rowspan < 1) {
return null;
}
var newCell = cell.type.createChecked(_objectSpread(_objectSpread({}, cell.attrs), {}, {
rowspan: rowspan
}), cell.content, cell.marks);
rowCells.push(newCell);
}
rows.push(row.type.createChecked(row.attrs, rowCells, row.marks));
}
}
if (!rows.length) {
return null;
}
return table.type.createChecked(table.attrs, rows, table.marks);
}
var deleteColumns = exports.deleteColumns = function deleteColumns(rect, allowCustomStep, api, view) {
var isTableScalingEnabled = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : false;
var isTableFixedColumnWidthsOptionEnabled = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : false;
var shouldUseIncreasedScalingPercent = arguments.length > 6 && arguments[6] !== undefined ? arguments[6] : false;
var isCommentEditor = arguments.length > 7 && arguments[7] !== undefined ? arguments[7] : false;
return function (tr) {
var updatedTr = tr;
updatedTr.setMeta(_tableAnalytics.META_KEYS.OVERFLOW_TRIGGER, {
name: _analytics.TABLE_OVERFLOW_CHANGE_TRIGGER.DELETED_COLUMN
});
if (allowCustomStep) {
updatedTr = deleteColumnsCustomStep(rect)(updatedTr);
} else {
updatedTr = deleteColumnsLegacy(rect)(updatedTr);
}
var table = (0, _utils.findTable)(updatedTr.selection);
if (table) {
updatedTr = (0, _columnWidth.rescaleColumns)(isTableScalingEnabled, isTableFixedColumnWidthsOptionEnabled, shouldUseIncreasedScalingPercent, api, isCommentEditor)(table, view)(updatedTr);
}
return updatedTr;
};
};