UNPKG

@atlaskit/editor-plugin-table

Version:

Table plugin for the @atlaskit/editor

237 lines (227 loc) 8.98 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports.getColumnsWidths = exports.getColumnIndexMappedToColumnIndexInFirstRow = exports.getColumnDeleteButtonParams = exports.convertHTMLCellIndexToColumnIndex = exports.colWidthsForRow = void 0; var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray")); var _utils = require("@atlaskit/editor-common/utils"); var _utils2 = require("@atlaskit/editor-prosemirror/utils"); var _tableMap = require("@atlaskit/editor-tables/table-map"); var _utils3 = require("@atlaskit/editor-tables/utils"); var _consts = require("../../ui/consts"); var getColumnsWidths = exports.getColumnsWidths = function getColumnsWidths(view) { var selection = view.state.selection; var widths = []; var table = (0, _utils3.findTable)(selection); if (table) { var map = _tableMap.TableMap.get(table.node); var domAtPos = view.domAtPos.bind(view); // When there is no cell we need to fill it with undefined widths = Array.from({ length: map.width }); for (var i = 0; i < map.width; i++) { if (!map.isCellMergedTopLeft(0, i)) { // Ignored via go/ees005 // eslint-disable-next-line @typescript-eslint/no-non-null-assertion var node = table.node.nodeAt(map.map[i]); var pos = map.map[i] + table.start; // Ignored via go/ees005 // eslint-disable-next-line @atlaskit/editor/no-as-casting var cellRef = (0, _utils2.findDomRefAtPos)(pos, domAtPos); var rect = cellRef.getBoundingClientRect(); widths[i] = (rect ? rect.width : cellRef.offsetWidth) + 1; i += node.attrs.colspan - 1; } } } return widths; }; var getColumnDeleteButtonParams = exports.getColumnDeleteButtonParams = function getColumnDeleteButtonParams(columnsWidths, selection) { var rect = (0, _utils3.getSelectionRect)(selection); if (!rect) { return null; } var width = 0; var offset = 0; // find the columns before the selection for (var i = 0; i < rect.left; i++) { var colWidth = columnsWidths[i]; if (colWidth) { offset += colWidth - 1; } } // these are the selected columns widths var indexes = []; for (var _i = rect.left; _i < rect.right; _i++) { var _colWidth = columnsWidths[_i]; if (_colWidth) { width += _colWidth; indexes.push(_i); } } var left = offset + width / 2 - _consts.tableDeleteButtonSize / 2; return { left: left, indexes: indexes }; }; // give a row colspan and a colwidths // and map to a row's colwidths var mapTableColwidthsToRow = function mapTableColwidthsToRow(rowColSpans, tableColWidths) { var curColIdx = 0; var colWidths = []; rowColSpans.forEach(function (cellColSpan) { var colWidth = tableColWidths.slice(curColIdx, curColIdx + cellColSpan).reduce(function (acc, val) { return acc + val; }, 0); curColIdx += cellColSpan; colWidths.push(colWidth); }); return colWidths; }; var getRelativeDomCellWidths = function getRelativeDomCellWidths(_ref) { var width = _ref.width, colspan = _ref.colspan, colwidth = _ref.colwidth; // For cells with colSpan 1 // or // for cells in a table with unchanged column widths, // these are identified by the lack of colwidth data attribute, // return equally partitioned total cell width in DOM for each cell. if (colspan === 1 || !colwidth) { return new Array(colspan).fill(width / colspan); } // For cells that have colSpan > 1 and // are part of a table with resized columns // return the current total DOM width of the cell multiplied // by the percentage of the each individual cell's size. // The cell size percentage is calculated using individual colwidth of the cell, // from data-colwidth attribute on the cell, // divided by the total width of the cells from colwidths for merged cells. // Ex: // colwidth = ‘201,102’ // Total colWidth = 303 // returned cellWidths = [303 * (201/303), 303 * (102/303)] // For merged cells we get back colwidth as `201,102` var cellColWidths = colwidth.split(',').map(function (colwidth) { return Number(colwidth); }); var totalCalculatedCellWidth = cellColWidths.reduce(function (acc, cellColWidth) { return acc + cellColWidth; }, 0); return cellColWidths.map(function (cellColWidth) { return width * (cellColWidth / totalCalculatedCellWidth); }); }; var colWidthsForRow = exports.colWidthsForRow = function colWidthsForRow(tr) { // get the colspans var rowColSpans = (0, _utils.maphElem)(tr, function (cell) { return Number(cell.getAttribute('colspan') || 1 /* default to span of 1 */); }); // Chrome has trouble aligning borders with auto tables // and the rest of the page grid. tables with defined // column widths align fine. // // eg a 4x25% table might end up as 189px 190px 190px 190px // // prefer copying the widths via the DOM // or inferring from the next row if one exists var copyTarget = tr.nextElementSibling || tr; if (copyTarget) { // either from the first row while it's still in the table var cellInfos = (0, _utils.maphElem)(copyTarget, function (cell) { return { width: cell.getBoundingClientRect().width, colspan: Number(cell.getAttribute('colspan') || 1), colwidth: cell.dataset.colwidth }; }); // reverse engineer cell widths from table widths var domBasedCellWidths = []; cellInfos.map(function (cell) { domBasedCellWidths.push.apply(domBasedCellWidths, (0, _toConsumableArray2.default)(getRelativeDomCellWidths(cell))); }); if (cellInfos.reduce(function (acc, cell) { return acc + cell.width; }, 0) !== 0) { var newWidths = mapTableColwidthsToRow(rowColSpans, domBasedCellWidths); return newWidths.map(function (px) { return "".concat(px, "px"); }).join(' '); } } // as a fallback, just calculate a %, and hope that // it aligns perfectly in the user's browser var visualColCount = rowColSpans.reduce(function (acc, val) { return acc + val; }, 0); var pctWidths = rowColSpans.map(function (cellColSpan) { return cellColSpan / visualColCount * 100; }); return pctWidths.map(function (pct) { return "".concat(pct, "%"); }).join(' '); }; var convertHTMLCellIndexToColumnIndex = exports.convertHTMLCellIndexToColumnIndex = function convertHTMLCellIndexToColumnIndex(htmlColIndex, htmlRowIndex, tableMap) { // Same numbers (positions) in tableMap.map array mean that there are merged cells. // Cells can be merged across columns. So we need to check if the cell on the left and current cell have the same value. // Cells can be merged acroll rows. So we need to check if the cell above has the same value as current cell. // When cell has the same value as the cell above it or the cell to the left of it, html cellIndex won't count it a separete column. var width = tableMap.width; var map = tableMap.map; var htmlColCount = 0; if (htmlRowIndex === 0) { for (var colIndex = 0; colIndex < width; colIndex++) { if (colIndex === 0 || map[colIndex] !== map[colIndex - 1]) { htmlColCount++; } if (htmlColCount - 1 === htmlColIndex) { return colIndex; } } } else { for (var _colIndex = 0; _colIndex < width; _colIndex++) { var currentCellMapIndex = htmlRowIndex * width + _colIndex; var cellAboveMapIndex = (htmlRowIndex - 1) * width + _colIndex; if (_colIndex > 0) { if (map[currentCellMapIndex] !== map[currentCellMapIndex - 1] && map[currentCellMapIndex] !== map[cellAboveMapIndex]) { htmlColCount++; } } else { if (map[currentCellMapIndex] !== map[cellAboveMapIndex]) { htmlColCount++; } } if (htmlColCount - 1 === htmlColIndex) { return _colIndex; } } } return 0; }; // When first row has merged cells, our converted column index needs to be mapped. var getColumnIndexMappedToColumnIndexInFirstRow = exports.getColumnIndexMappedToColumnIndexInFirstRow = function getColumnIndexMappedToColumnIndexInFirstRow(convertedColIndex, htmlRowIndex, tableMap) { var width = tableMap.width; var map = tableMap.map; var mapColIndexToFistRowColIndex = []; var htmlColCounFirstRow = 0; var colSpan = 0; if (htmlRowIndex === 0) { return convertedColIndex; } for (var colIndex = 0; colIndex < width; colIndex++) { if (colIndex === 0 || map[colIndex] !== map[colIndex - 1]) { if (colSpan > 0) { htmlColCounFirstRow += colSpan; colSpan = 0; } htmlColCounFirstRow++; } else if (map[colIndex] === map[colIndex - 1]) { colSpan++; } mapColIndexToFistRowColIndex[colIndex] = htmlColCounFirstRow - 1; } return mapColIndexToFistRowColIndex[convertedColIndex]; };