UNPKG

@atlaskit/editor-plugin-table

Version:

Table plugin for the @atlaskit/editor

215 lines (207 loc) 10.2 kB
"use strict"; 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); }; }; };