@atlaskit/editor-plugin-table
Version:
Table plugin for the @atlaskit/editor
215 lines (207 loc) • 10.2 kB
JavaScript
;
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.updateColumnWidths = exports.rescaleColumns = void 0;
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
var _styles = require("@atlaskit/editor-common/styles");
var _transform = require("@atlaskit/editor-prosemirror/transform");
var _tableMap = require("@atlaskit/editor-tables/table-map");
var _colgroup = require("../table-resizing/utils/colgroup");
var _misc = require("../table-resizing/utils/misc");
var _resizeState = require("../table-resizing/utils/resize-state");
var _scaleTable = require("../table-resizing/utils/scale-table");
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; }
/**
* Given a new ResizeState object, create a transaction that replaces and updates the table node based on new state.
* @param resizeState
* @param table
* @param start
* @returns
*/
var updateColumnWidths = exports.updateColumnWidths = function updateColumnWidths(resizeState, table, start, api) {
return function (tr) {
var map = _tableMap.TableMap.get(table);
var updatedCellsAttrs = {};
var steps = [];
// calculating new attributes for each cell
for (var columnIndex = 0; columnIndex < map.width; columnIndex++) {
for (var rowIndex = 0; rowIndex < map.height; rowIndex++) {
var width = resizeState.cols[columnIndex].width;
if (resizeState.isScaled) {
// Ensure that the width is an integer if the table has been scaled
width = Math.floor(width);
}
var mapIndex = rowIndex * map.width + columnIndex;
var cellPos = map.map[mapIndex];
var attrs = updatedCellsAttrs[cellPos] || _objectSpread({}, table.nodeAt(cellPos).attrs);
var colspan = attrs.colspan || 1;
if (attrs.colwidth && attrs.colwidth.length > colspan) {
attrs.colwidth = attrs.colwidth.slice(0, colspan);
}
// Rowspanning cell that has already been handled
if (rowIndex && map.map[mapIndex] === map.map[mapIndex - map.width]) {
continue;
}
var colspanIndex = colspan === 1 ? 0 : columnIndex - map.colCount(cellPos);
if (attrs.colwidth && attrs.colwidth[colspanIndex] === width) {
continue;
}
var colwidths = attrs.colwidth ? attrs.colwidth.slice() : Array.from({
length: colspan
}, function (_) {
return 0;
});
colwidths[colspanIndex] = width;
if (colwidths.length > colspan) {
colwidths = colwidths.slice(0, colspan);
}
updatedCellsAttrs[cellPos] = _objectSpread(_objectSpread({}, attrs), {}, {
colwidth: colwidths.includes(0) ? undefined : colwidths
});
}
}
// updating all cells with new attributes
var seen = {};
for (var _rowIndex = 0; _rowIndex < map.height; _rowIndex++) {
for (var _columnIndex = 0; _columnIndex < map.width; _columnIndex++) {
var _mapIndex = _rowIndex * map.width + _columnIndex;
var pos = map.map[_mapIndex];
var cell = table.nodeAt(pos);
if (!seen[pos] && cell) {
if (updatedCellsAttrs[pos]) {
steps.push(new _transform.AttrStep(pos + start, 'colwidth', updatedCellsAttrs[pos].colwidth === undefined ? null : updatedCellsAttrs[pos].colwidth));
}
seen[pos] = true;
}
}
}
if (api !== null && api !== void 0 && api.batchAttributeUpdates) {
var batchStep = api.batchAttributeUpdates.actions.batchSteps({
steps: steps,
doc: tr.doc
});
tr.step(batchStep);
} else {
steps.forEach(function (s) {
tr.step(s);
});
}
return tr;
};
};
/**
* This function is called when user inserts/deletes a column in a table to;
* - rescale all columns (if the table did not overflow before the insertion)
* - and update column widths.
*
* This is done manually to avoid a multi-dispatch in TableComponent. See [ED-8288].
* @param table
* @param view
* @returns Updated transaction with rescaled columns for a given table
*/
var rescaleColumns = exports.rescaleColumns = function rescaleColumns() {
var isTableScalingEnabled = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
var isTableFixedColumnWidthsOptionEnabled = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
var shouldUseIncreasedScalingPercent = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
var api = arguments.length > 3 ? arguments[3] : undefined;
var isCommentEditor = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : false;
return function (table, view) {
return function (tr) {
if (!view) {
return tr;
}
var newTable = tr.doc.nodeAt(table.pos);
var domAtPos = view.domAtPos.bind(view);
var maybeTable = domAtPos(table.start).node;
var maybeTableElement = maybeTable instanceof HTMLElement ? maybeTable : null;
var tableRef = maybeTableElement === null || maybeTableElement === void 0 ? void 0 : maybeTableElement.closest('table');
if (!tableRef || !newTable) {
return tr;
}
var isResized = (0, _colgroup.hasTableBeenResized)(table.node);
var previousTableInfo = {
width: 0,
possibleMaxWidth: 0,
isResized: isResized
};
var tableDepth = view.state.doc.resolve(table.pos).depth;
var shouldScale = isTableScalingEnabled && tableDepth === 0;
if (shouldScale && isTableFixedColumnWidthsOptionEnabled) {
shouldScale = newTable.attrs.displayMode !== 'fixed';
}
if (shouldScale) {
previousTableInfo = {
width: (0, _misc.getTableElementWidth)(table.node),
possibleMaxWidth: (0, _misc.getTableContainerElementWidth)(table.node),
isResized: isResized
};
} else {
var _tableRef$parentEleme;
previousTableInfo = {
// when table is resized the tableRef client width will be 1px larger than colGroup, which is used in calculations
width: isResized ? tableRef.clientWidth - 1 : tableRef.clientWidth,
/** the is the width the table can reach before overflowing */
possibleMaxWidth: (tableRef === null || tableRef === void 0 || (_tableRef$parentEleme = tableRef.parentElement) === null || _tableRef$parentEleme === void 0 ? void 0 : _tableRef$parentEleme.clientWidth) || 0,
isResized: isResized
};
}
// determine the new table, based on new width
var newTableInfo = {
noOfColumns: _tableMap.TableMap.get(newTable).width
};
if (!newTableInfo.noOfColumns || newTableInfo.noOfColumns <= 0) {
return tr;
}
var averageColumnWidth = previousTableInfo.width / newTableInfo.noOfColumns;
// If the table has not been resized (i.e. all columns will have the same width) and every column width is bigger than the minimum column width
// we skip updating the size of columns here.
if (!previousTableInfo.isResized && averageColumnWidth > _styles.tableCellMinWidth) {
return tr;
}
var wasTableInOverflow = previousTableInfo.width > previousTableInfo.possibleMaxWidth;
// If the table has not been resized, and each column width is smaller than the minimum column width
// Or if the table has been resized, but each column width is either 48px or null
// we update the table to have 48px for each column
if (!previousTableInfo.isResized && averageColumnWidth <= _styles.tableCellMinWidth || previousTableInfo.isResized && (0, _colgroup.isMinCellWidthTable)(table.node)) {
var widths = new Array(newTableInfo.noOfColumns).fill(_styles.tableCellMinWidth);
var cols = widths.map(function (_, index) {
return {
width: _styles.tableCellMinWidth,
minWidth: _styles.tableCellMinWidth,
index: index
};
});
var minWidthResizeState = {
cols: cols,
widths: widths,
maxSize: previousTableInfo.possibleMaxWidth,
tableWidth: previousTableInfo.width,
overflow: wasTableInOverflow
};
return updateColumnWidths(minWidthResizeState, table.node, table.start, api)(tr);
}
var resizeState = (0, _resizeState.getResizeState)({
minWidth: _styles.tableCellMinWidth,
table: table.node,
start: table.start,
tableRef: tableRef,
domAtPos: domAtPos,
maxSize: previousTableInfo.possibleMaxWidth,
isTableScalingEnabled: shouldScale,
shouldUseIncreasedScalingPercent: shouldUseIncreasedScalingPercent,
isCommentEditor: isCommentEditor
});
// Two scenarios that require scaling:
// 1. If the new table width will result in the table going into overflow
// we resize the cells to avoid it (e.g. adding a column)
// 2. If the new table width will be shorter than the parent width, scale columns to fit parent
if (!wasTableInOverflow && resizeState.overflow || resizeState.tableWidth < resizeState.maxSize) {
resizeState = (0, _scaleTable.scaleTableTo)(resizeState, previousTableInfo.possibleMaxWidth);
}
return updateColumnWidths(resizeState, table.node, table.start, api)(tr);
};
};
};