UNPKG

@atlaskit/editor-plugin-table

Version:

Table plugin for the @atlaskit/editor

206 lines (201 loc) 11 kB
import _toConsumableArray from "@babel/runtime/helpers/toConsumableArray"; import { tableCellMinWidth } from '@atlaskit/editor-common/styles'; import { calcTableColumnWidths, getFragmentBackingArray } from '@atlaskit/editor-common/utils'; import { DOMSerializer } from '@atlaskit/editor-prosemirror/model'; import { akEditorTableNumberColumnWidth } from '@atlaskit/editor-shared-styles'; import { TableMap } from '@atlaskit/editor-tables/table-map'; import { COLUMN_MIN_WIDTH, MAX_SCALING_PERCENT, MAX_SCALING_PERCENT_TABLES_WITH_FIXED_COLUMN_WIDTHS_OPTION } from './consts'; import { getScalingPercentForTableWithoutWidth, getTableContainerElementWidth, getTableScalingPercent } from './misc'; /** * This ensures the combined width of the columns (and tbody) of table is always smaller or equal * than the table and table wrapper elements. This is necessary as there is no longer * padding on the .pm-table-wrapper, so all elements need to be the same width to avoid * overflow. */ export var getColWidthFix = function getColWidthFix(colwidth, tableColumnCount) { return colwidth - 1 / tableColumnCount; }; var generateColStyle = function generateColStyle(fixedColWidth, tableWidth, isCommentEditor, isChromelessEditor, isNested, shouldUseIncreasedScalingPercent, isNumberColumnEnabled, isTableHasWidth, hasTableBeenResized) { var maxScalingPercent = shouldUseIncreasedScalingPercent ? MAX_SCALING_PERCENT_TABLES_WITH_FIXED_COLUMN_WIDTHS_OPTION : MAX_SCALING_PERCENT; var maxScaledRatio = 1 - maxScalingPercent; var isFullPageEditor = !isChromelessEditor && !isCommentEditor; // for nested tables, or chromeless editor, which used non resizable table container if (isNested || isChromelessEditor) { if (hasTableBeenResized) { return "width: max(".concat(fixedColWidth, "px, ").concat(tableCellMinWidth, "px)"); } return "width: ".concat(tableCellMinWidth, "px)"); } if (isFullPageEditor || !isFullPageEditor && isTableHasWidth) { var scaledPercent = isNumberColumnEnabled ? "calc(calc(var(--ak-editor-table-width) - ".concat(akEditorTableNumberColumnWidth, "px - 1px)/").concat(tableWidth, ")") : "calc(calc(var(--ak-editor-table-width) - 1px)/".concat(tableWidth, ")"); return "width: max(calc(".concat(fixedColWidth, "px * ").concat(maxScaledRatio, "), calc(").concat(fixedColWidth, " * ").concat(scaledPercent, "), ").concat(tableCellMinWidth, "px)"); } // table resized to full-width in comment editor // it doesn't have a width attribute, and cols has been resized if (hasTableBeenResized) { var _scaledPercent = isNumberColumnEnabled ? "calc(calc(var(--ak-editor-table-width) - ".concat(akEditorTableNumberColumnWidth, "px - 1px)/").concat(tableWidth, ")") : "calc(calc(var(--ak-editor-table-width) - 1px)/".concat(tableWidth, ")"); return "width: max(calc(".concat(fixedColWidth, " * ").concat(_scaledPercent, "), ").concat(tableCellMinWidth, "px)"); } return "width: ".concat(tableCellMinWidth, "px"); }; export var generateColgroupFromNode = function generateColgroupFromNode(table, isCommentEditor, isChromelessEditor, isNested, isTableScalingEnabled, shouldUseIncreasedScalingPercent) { var cols = []; var map = TableMap.get(table); var isTableHasWidth = !!table.attrs.width; var isNumberColumnEnabled = table.attrs.isNumberColumnEnabled || false; var isFullPageEditor = !isChromelessEditor && !isCommentEditor; // Ignored via go/ees005 // eslint-disable-next-line @typescript-eslint/no-non-null-assertion table.content.firstChild.content.forEach(function (cell) { var colspan = cell.attrs.colspan || 1; // if the table has been resized if (Array.isArray(cell.attrs.colwidth)) { cell.attrs.colwidth.slice(0, colspan).forEach(function (width) { // existing logic for calculating the width of the column var fixedColWidth = getColWidthFix(width, map.width); var tableWidth = isFullPageEditor || !isFullPageEditor && isTableHasWidth ? getTableContainerElementWidth(table) : calcTableColumnWidths(table).reduce(function (sum, width) { return sum + width; }, 0); if (isTableScalingEnabled) { cols.push(['col', { style: generateColStyle(fixedColWidth, tableWidth, isCommentEditor, isChromelessEditor, isNested, shouldUseIncreasedScalingPercent, isNumberColumnEnabled, isTableHasWidth, true) }]); } else { cols.push(['col', { style: "width: max(".concat(fixedColWidth, "px, ").concat(tableCellMinWidth, "px)") }]); } }); } else { if (!isTableScalingEnabled) { cols.push.apply(cols, _toConsumableArray(Array.from({ length: colspan }, function (_) { return ['col', { style: "width: ".concat(tableCellMinWidth, "px;") }]; }))); } else { // columns has not been resized, so distribute the width evenly cols.push.apply(cols, _toConsumableArray(Array.from({ length: colspan }, function (_) { var tableWidth = getTableContainerElementWidth(table); var columnWidth = tableWidth / map.width || 0; var fixedColWidth = getColWidthFix(columnWidth, map.width || 0); return ['col', { style: generateColStyle(fixedColWidth, tableWidth, isCommentEditor, isChromelessEditor, isNested, shouldUseIncreasedScalingPercent, isNumberColumnEnabled, isTableHasWidth) }]; }))); } } }); return cols; }; export var generateColgroup = function generateColgroup(table, tableRef, shouldUseIncreasedScalingPercent, isCommentEditor) { var cols = []; var map = TableMap.get(table); // Ignored via go/ees005 // eslint-disable-next-line @typescript-eslint/no-non-null-assertion table.content.firstChild.content.forEach(function (cell) { var colspan = cell.attrs.colspan || 1; if (Array.isArray(cell.attrs.colwidth)) { // We slice here to guard against our colwidth array having more entries // Than the we actually span. We'll patch the document at a later point. if (tableRef) { var _table$attrs; // if we have tableRef here, isTableScalingEnabled is true var scalePercent = 1; if (isCommentEditor && !((_table$attrs = table.attrs) !== null && _table$attrs !== void 0 && _table$attrs.width)) { scalePercent = getScalingPercentForTableWithoutWidth(table, tableRef); } else { scalePercent = getTableScalingPercent(table, tableRef, shouldUseIncreasedScalingPercent); } cell.attrs.colwidth.slice(0, colspan).forEach(function (width) { // existing logic for calculating the width of the column var fixedColWidth = getColWidthFix(width, map.width); var scaledWidth = fixedColWidth * scalePercent; var finalWidth = Math.max(scaledWidth, tableCellMinWidth); cols.push(['col', { style: "width: ".concat(finalWidth, "px;") }]); }); } else { cell.attrs.colwidth.slice(0, colspan).forEach(function (width) { cols.push(['col', { style: "width: ".concat(getColWidthFix(width ? Math.max(width, tableCellMinWidth) : tableCellMinWidth, map.width), "px;") }]); }); } } else { // When we have merged cells on the first row (firstChild), // We want to ensure we're creating the appropriate amount of // cols the table still has. cols.push.apply(cols, _toConsumableArray(Array.from({ length: colspan }, function (_) { return ['col', { style: "width: ".concat(tableCellMinWidth, "px;") }]; }))); } }); return cols; }; export var insertColgroupFromNode = function insertColgroupFromNode(tableRef, table) { var isTableScalingEnabled = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false; var shouldRemove = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : true; var shouldUseIncreasedScalingPercent = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : false; var isCommentEditor = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : false; // Ignored via go/ees005 // eslint-disable-next-line @atlaskit/editor/no-as-casting var colgroup = tableRef === null || tableRef === void 0 ? void 0 : tableRef.querySelector('colgroup'); if (colgroup && shouldRemove) { tableRef === null || tableRef === void 0 || tableRef.removeChild(colgroup); } colgroup = renderColgroupFromNode(table, isTableScalingEnabled ? tableRef !== null && tableRef !== void 0 ? tableRef : undefined : undefined, shouldUseIncreasedScalingPercent, isCommentEditor); if (shouldRemove) { tableRef === null || tableRef === void 0 || tableRef.insertBefore(colgroup, tableRef === null || tableRef === void 0 ? void 0 : tableRef.firstChild); } return colgroup.children; }; export var hasTableBeenResized = function hasTableBeenResized(table) { // Ignored via go/ees005 // eslint-disable-next-line @typescript-eslint/no-non-null-assertion return !!getFragmentBackingArray(table.content.firstChild.content).find(function (cell) { return cell.attrs.colwidth; }); }; export var hasTableColumnBeenResized = hasTableBeenResized; /** * Check if a table has all the column width set to tableCellMinWidth(48px) or null * * @param table * @returns true if all column width is equal to tableCellMinWidth or null, false otherwise */ export var isMinCellWidthTable = function isMinCellWidthTable(table) { // Ignored via go/ees005 // eslint-disable-next-line @typescript-eslint/no-non-null-assertion var cellArray = getFragmentBackingArray(table.content.firstChild.content); var isTableMinCellWidth = cellArray.every(function (cell) { return cell.attrs.colwidth && cell.attrs.colwidth[0] === tableCellMinWidth || cell.attrs.colwidth === null; }); return isTableMinCellWidth; }; function renderColgroupFromNode(table, maybeTableRef, shouldUseIncreasedScalingPercent, isCommentEditor) { var rendered = DOMSerializer.renderSpec(document, ['colgroup', {}].concat(_toConsumableArray(generateColgroup(table, maybeTableRef, shouldUseIncreasedScalingPercent, isCommentEditor)))); // Ignored via go/ees005 // eslint-disable-next-line @atlaskit/editor/no-as-casting return rendered.dom; } export var getColgroupChildrenLength = function getColgroupChildrenLength(table) { var map = TableMap.get(table); return map.width; }; export var getResizerMinWidth = function getResizerMinWidth(node) { var currentColumnCount = getColgroupChildrenLength(node); var minColumnWidth = Math.min(3, currentColumnCount) * COLUMN_MIN_WIDTH; // add an extra pixel as the scale table logic will scale columns to be tableContainerWidth - 1 // the table can't scale past its min-width, so instead restrict table container min width to avoid that situation return minColumnWidth + 1; };