UNPKG

@atlaskit/editor-plugin-table

Version:

Table plugin for the @atlaskit/editor

170 lines (169 loc) 5.22 kB
import { parsePx } from '@atlaskit/editor-common/utils'; import { safeInsert } from '@atlaskit/editor-prosemirror/utils'; import { TableMap } from '@atlaskit/editor-tables/table-map'; import { findTable, getSelectionRect, isRowSelected } from '@atlaskit/editor-tables/utils'; import { TableCssClassName as ClassName } from '../../types'; import { tableDeleteButtonSize } from '../../ui/consts'; export const getRowHeights = tableRef => { const heights = []; const tableBody = tableRef.querySelector('tbody'); if (tableBody) { const rows = tableBody.childNodes; for (let i = 0, count = rows.length; i < count; i++) { const row = rows[i]; heights[i] = row.getBoundingClientRect().height + 1; // padding only gets applied when the container has sticky if (row.classList.contains('sticky') && i === 0) { const styles = window.getComputedStyle(row); const paddingTop = parsePx(styles.paddingTop || ''); heights[i] -= paddingTop ? paddingTop + 1 : +1; } } } return heights; }; export const getRowDeleteButtonParams = (rowsHeights, selection, offsetTop = 0) => { const rect = getSelectionRect(selection); if (!rect) { return null; } let height = 0; let offset = offsetTop; // find the rows before the selection for (let i = 0; i < rect.top; i++) { const rowHeight = rowsHeights[i]; if (rowHeight) { offset += rowHeight - 1; } } // these are the selected rows widths const indexes = []; for (let i = rect.top; i < rect.bottom; i++) { const rowHeight = rowsHeights[i]; if (rowHeight) { height += rowHeight - 1; indexes.push(i); } } const top = offset + height / 2 - tableDeleteButtonSize / 2; return { top, indexes }; }; export const getRowsParams = rowsHeights => { const rows = []; for (let i = 0, count = rowsHeights.length; i < count; i++) { const height = rowsHeights[i]; if (!height) { continue; } let endIndex = rowsHeights.length; for (let k = i + 1, count = rowsHeights.length; k < count; k++) { if (rowsHeights[k]) { endIndex = k; break; } } rows.push({ startIndex: i, endIndex, height }); } return rows; }; export const getRowClassNames = (index, selection, hoveredRows = [], isInDanger, isResizing) => { const classNames = []; if (isRowSelected(index)(selection) || hoveredRows.indexOf(index) > -1 && !isResizing) { classNames.push(ClassName.HOVERED_CELL_ACTIVE); if (isInDanger) { classNames.push(ClassName.HOVERED_CELL_IN_DANGER); } } return classNames.join(' '); }; export const copyPreviousRow = schema => insertNewRowIndex => tr => { const table = findTable(tr.selection); if (!table) { return tr; } const map = TableMap.get(table.node); const copyPreviousRowIndex = insertNewRowIndex - 1; if (insertNewRowIndex <= 0) { throw Error(`Row Index less or equal 0 isn't not allowed since there is not a previous to copy`); } if (insertNewRowIndex > map.height) { return tr; } const tableNode = table.node; const { nodes: { tableRow } } = schema; const cellsInRow = map.cellsInRect({ left: 0, right: map.width, top: copyPreviousRowIndex, bottom: copyPreviousRowIndex + 1 }); const offsetIndexPosition = copyPreviousRowIndex * map.width; const offsetNextLineIndexPosition = insertNewRowIndex * map.width; const cellsPositionsInOriginalRow = map.map.slice(offsetIndexPosition, offsetIndexPosition + map.width); const cellsPositionsInNextRow = map.map.slice(offsetNextLineIndexPosition, offsetNextLineIndexPosition + map.width); const cells = []; const fixRowspans = []; for (let i = 0; i < cellsPositionsInOriginalRow.length;) { const pos = cellsPositionsInOriginalRow[i]; const documentCellPos = pos + table.start; const node = tr.doc.nodeAt(documentCellPos); if (!node) { continue; } const attributes = { ...node.attrs, colspan: 1, rowspan: 1 }; const newCell = node.type.createAndFill(attributes); if (!newCell) { return tr; } if (cellsPositionsInNextRow.indexOf(pos) > -1) { fixRowspans.push({ pos: documentCellPos, node }); } else if (cellsInRow.indexOf(pos) > -1) { if (node.attrs.colspan > 1) { const newCellWithColspanFixed = node.type.createAndFill({ ...attributes, colspan: node.attrs.colspan }); if (!newCellWithColspanFixed) { return tr; } cells.push(newCellWithColspanFixed); i = i + node.attrs.colspan; continue; } cells.push(newCell); } else { cells.push(newCell); } i++; } fixRowspans.forEach(cell => { tr.setNodeMarkup(cell.pos, undefined, { ...cell.node.attrs, rowspan: cell.node.attrs.rowspan + 1 }); }); const cloneRow = tableNode.child(copyPreviousRowIndex); let rowPos = table.start; for (let i = 0; i < insertNewRowIndex; i++) { rowPos += tableNode.child(i).nodeSize; } return safeInsert(tableRow.createChecked(cloneRow.attrs, cells, cloneRow.marks), rowPos)(tr); };