UNPKG

@atlaskit/editor-plugin-table

Version:

Table plugin for the @atlaskit/editor

107 lines (106 loc) 4.17 kB
import { mapChildren } from '@atlaskit/editor-common/utils'; import { TableMap } from '@atlaskit/editor-tables/table-map'; import { findTable } from '@atlaskit/editor-tables/utils'; export const isIsolating = node => { return !!node.type.spec.isolating; }; export const containsHeaderColumn = table => { const map = TableMap.get(table); // Get cell positions for first column. const cellPositions = map.cellsInRect({ left: 0, top: 0, right: 1, bottom: map.height }); for (let i = 0; i < cellPositions.length; i++) { try { const cell = table.nodeAt(cellPositions[i]); if (cell && cell.type !== table.type.schema.nodes.tableHeader) { return false; } } catch (e) { return false; } } return true; }; export const containsHeaderRow = table => { const map = TableMap.get(table); for (let i = 0; i < map.width; i++) { const cell = table.nodeAt(map.map[i]); if (cell && cell.type !== table.type.schema.nodes.tableHeader) { return false; } } return true; }; export const checkIfHeaderColumnEnabled = selection => filterNearSelection(selection, findTable, containsHeaderColumn, false); export const checkIfHeaderRowEnabled = selection => filterNearSelection(selection, findTable, containsHeaderRow, false); export const checkIfNumberColumnEnabled = selection => filterNearSelection(selection, findTable, table => !!table.attrs.isNumberColumnEnabled, false); export const getTableWidth = node => { return getTableWidths(node).reduce((acc, current) => acc + current, 0); }; export const tablesHaveDifferentColumnWidths = (currentTable, previousTable) => { const currentTableWidths = getTableWidths(currentTable); const previousTableWidths = getTableWidths(previousTable); if (currentTableWidths.length !== previousTableWidths.length) { return true; } const sameWidths = currentTableWidths.every((value, index) => { return value === previousTableWidths[index]; }); return sameWidths === false; }; export const tablesHaveDifferentNoOfColumns = (currentTable, previousTable) => { const prevMap = TableMap.get(previousTable); const currentMap = TableMap.get(currentTable); return prevMap.width !== currentMap.width; }; export const tablesHaveDifferentNoOfRows = (currentTable, previousTable) => { const prevMap = TableMap.get(previousTable); const currentMap = TableMap.get(currentTable); return prevMap.height !== currentMap.height; }; function filterNearSelection(selection, findNode, predicate, defaultValue) { const found = findNode(selection); if (!found) { return defaultValue; } return predicate(found.node, found.pos); } function getTableWidths(node) { if (!node.content.firstChild) { return []; } const tableWidths = []; node.content.firstChild.content.forEach(cell => { if (Array.isArray(cell.attrs.colwidth)) { const colspan = cell.attrs.colspan || 1; tableWidths.push(...cell.attrs.colwidth.slice(0, colspan)); } }); return tableWidths; } export const isTableNested = (state, tablePos = 0) => { const parent = state.doc.resolve(tablePos).parent; const nodeTypes = state.schema.nodes; return parent.type === nodeTypes.layoutColumn || parent.type === nodeTypes.expand || parent.type === nodeTypes.bodiedExtension || parent.type === nodeTypes.extensionFrame || parent.type === nodeTypes.tableHeader || parent.type === nodeTypes.tableCell; }; export const isTableNestedInMoreThanOneNode = (state, tablePos = 0) => { return state.doc.resolve(tablePos).depth > 2; }; const anyChildCellMergedAcrossRow = node => mapChildren(node, child => child.attrs.rowspan || 0).some(rowspan => rowspan > 1); /** * Check if a given node is a header row with this definition: * - all children are tableHeader cells * - no table cells have been have merged with other table row cells * * @param node ProseMirror node * @return boolean if it meets definition */ export const supportedHeaderRow = node => { const allHeaders = mapChildren(node, child => child.type.name === 'tableHeader').every(Boolean); const someMerged = anyChildCellMergedAcrossRow(node); return allHeaders && !someMerged; };