Skip to content

Commit

Permalink
[TablePlugin] implement column / row adding / removal functions with …
Browse files Browse the repository at this point in the history
…merged cells
  • Loading branch information
dimaanj committed Sep 15, 2023
1 parent 5a79d1b commit d777438
Show file tree
Hide file tree
Showing 16 changed files with 542 additions and 244 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,8 @@ const TableCellElement = React.forwardRef<

const { rightProps, bottomProps, leftProps, hiddenLeft } =
useTableCellElementResizable(resizableState);



const Cell = isHeader ? 'th' : 'td';

return (
Expand Down
12 changes: 0 additions & 12 deletions apps/www/src/registry/default/plate-ui/table-element.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -131,18 +131,6 @@ const TableFloatingToolbar = React.forwardRef<
((cellEntries[0][0] as any)?.colSpan > 1 ||
(cellEntries[0][0] as any)?.rowSpan > 1);

console.log(
'canUnmerge',
canUnmerge,
'hasEntries',
hasEntries,
isCollapsed(editor.selection),
cellEntries,
cellEntries?.length === 1,
(cellEntries?.[0]?.[0] as any)?.colSpan,
(cellEntries?.[0]?.[0] as any)?.rowSpan
);

const mergeToolbarActive =
isSelected &&
!readOnly &&
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,16 +17,14 @@ import {
} from '../../types';
import { getCellTypes, getEmptyCellNode } from '../../utils/index';

const getRowSpanInCol = (table: TTableCellElement, colIndex: number) => {
const getRowSpanInFirstCol = (table: TTableCellElement, colIndex: number) => {
return table.children.reduce((acc, cur) => {
const rowEl = cur as TTableRowElement;
const cellEl = rowEl.children.find((cell) => {
const cellElem = cell as TTableCellElement;
return cellElem?.colIndex === colIndex;
}) as TTableCellElement;

// console.log('cellEl', cellEl);

if (colIndex === cellEl?.colIndex) {
const curRowSpan = cellEl?.rowSpan || 1;
return acc + curRowSpan;
Expand Down Expand Up @@ -56,14 +54,14 @@ export const useTableCellsMerge = () => {
// define rowSpan
const firstCell = firstRow.children?.[0] as TTableCellElement;
const firstColIndex = firstCell.colIndex!;
const rowSpan = getRowSpanInCol(table, firstColIndex);
const rowSpan = getRowSpanInFirstCol(table, firstColIndex);

const [, startCellPath] = selectedCellEntries[0];

const contents = [];
for (const cellEntry of selectedCellEntries) {
const [el] = cellEntry;
contents.push(...el.children); // TODO: make deep clone here
contents.push(...el.children); // TODO: consider using deep clone
}

const cols: any = {};
Expand All @@ -79,8 +77,6 @@ export const useTableCellsMerge = () => {
}
});

// console.log('colSpan', colSpan, 'rowSpan', rowSpan, 'cols', cols);

// removes multiple cells with on same path.
// once cell removed, next cell in the row will settle down on that path
Object.values(cols).forEach((paths: any) => {
Expand All @@ -98,7 +94,7 @@ export const useTableCellsMerge = () => {
rowSpan,
};

insertElements(editor, mergedCell, { at: startCellPath });
insertElements(editor, mergedCell, { at: startCellPath, select: true });
};

const onUnmerge = () => {
Expand All @@ -124,22 +120,14 @@ export const useTableCellsMerge = () => {
const colSpan = cellElem.colSpan;
const rowSpan = cellElem.rowSpan;

// console.log('cellPath', cellPath, 'rowSpan', rowSpan, 'colSpan', colSpan);

const colPaths = Array.from(
{ length: colSpan } as ArrayLike<number>,
(_, index) => {
return index;
}
).map((current) => {
return colPath + current;
});
(_, index) => index
).map((current) => colPath + current);

let paths = Array.from(
{ length: rowSpan } as ArrayLike<number>,
(_, index) => {
return index;
}
(_, index) => index
).map((current) => {
const currentRowPath = rowPath + current;
return colPaths.map((currentColPath) => [
Expand All @@ -154,12 +142,10 @@ export const useTableCellsMerge = () => {
match: { type: getPluginType(editor, ELEMENT_TABLE) },
});
const table = tableEntry?.[0] as TTableElement;
// console.log('found table', table);

paths = paths.map((cellsPaths) => {
const currentPath = cellsPaths[0]; // pick starting cell in the row
const [rowIndex, colIndex] = currentPath.slice(-2);
// console.log('cellsPaths', cellsPaths);

let newCellPaths = cellsPaths;
if (colIndex > 0) {
Expand All @@ -168,12 +154,6 @@ export const useTableCellsMerge = () => {
at: prevCellInRowPath,
match: { type: getCellTypes(editor) },
});
// console.log(
// 'prevCellInRowPath',
// prevCellInRowPath,
// 'foundEntry',
// foundEntry
// );

/**
* Search for the last cell path in the row.
Expand All @@ -182,35 +162,27 @@ export const useTableCellsMerge = () => {
*/
if (!foundEntry) {
const currentRow = table.children[rowIndex] as TTableRowElement;
console.log('table', table, rowIndex, currentRow);
const endingCell = currentRow.children.at(-1)!;
const endingCellPath = findNodePath(editor, endingCell)!;
console.log(
'endingCell',
endingCell,
'endingCellPath',
endingCellPath
);

const [, startingColIndex] = endingCellPath.slice(-2);
const startWith =
startingColIndex === 0 ? startingColIndex : startingColIndex + 1;

newCellPaths = cellsPaths.map((currentCellPath, i) => {
const currentRowPath = currentCellPath.slice(0, -1);
const newPath = [...currentRowPath, startWith + i];
const newPath = [...currentRowPath, startWith + i]; // adjust column path
return newPath;
});
}
}
return newCellPaths;
});

// console.log('-----------------');

// remove merged cell
removeNodes(editor, { at: path });

// console.log('paths', paths);
// insert new cells
paths
.flat()
.forEach((p, index) =>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,9 @@ export const isTableRectangular = (table?: TTableElement) => {
rowEl.children?.forEach((cell) => {
const cellElem = cell as TTableCellElement;

// console.log('current cell', cellElem);
Array.from({
length: cellElem?.rowSpan || 1,
} as ArrayLike<number>).forEach((_, i) => {
// console.log(
// 'pushing into arr, index',
// rI + i,
// 'value',
// cellElem?.colSpan || 1
// );
if (!arr[rI + i]) {
arr[rI + i] = 0;
}
Expand All @@ -32,7 +25,5 @@ export const isTableRectangular = (table?: TTableElement) => {
});
});

// console.log('arr', arr);

return allEqual(arr);
};
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@ export const useSelectedCells = () => {
if (cellEntries?.length > 1) {
const cells = cellEntries.map((entry) => entry[0]);

console.log('current cells', cells);
if (JSON.stringify(cells) !== JSON.stringify(selectedCells)) {
setSelectedCells(cells);
}
Expand Down
15 changes: 10 additions & 5 deletions packages/table/src/components/TableElement/useTableColSizes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,8 @@ export const useTableColSizes = (
const editor = usePlateEditorRef();
const colSizeOverrides = useTableStore().get.colSizeOverrides();

const { enableUnsetSingleColSize } = getPluginOptions<TablePlugin>(
editor,
ELEMENT_TABLE
);
const { enableUnsetSingleColSize, minColumnWidth } =
getPluginOptions<TablePlugin>(editor, ELEMENT_TABLE);

const colCount = getTableColumnCount(tableNode);

Expand All @@ -38,10 +36,17 @@ export const useTableColSizes = (
() =>
getTableOverriddenColSizes(
colCount,
minColumnWidth,
tableNode.colSizes ? [...tableNode.colSizes] : undefined,
disableOverrides ? undefined : colSizeOverrides
),
[colCount, colSizeOverrides, disableOverrides, tableNode.colSizes]
[
colCount,
colSizeOverrides,
disableOverrides,
minColumnWidth,
tableNode.colSizes,
]
);

const setCellsOffsets = useTableStore().set.cellsOffsets();
Expand Down
3 changes: 2 additions & 1 deletion packages/table/src/createTablePlugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ export const ELEMENT_TABLE = 'table';
export const ELEMENT_TH = 'th';
export const ELEMENT_TR = 'tr';
export const ELEMENT_TD = 'td';
export const DEFAULT_MIN_COL_WIDTH = 48;

/**
* Enables support for tables.
Expand All @@ -35,7 +36,7 @@ export const createTablePlugin = createPluginFactory<TablePlugin>({
disableSelect: true,
});
},
minColumnWidth: 48,
minColumnWidth: DEFAULT_MIN_COL_WIDTH,
},
withOverrides: withTable,
plugins: [
Expand Down
2 changes: 0 additions & 2 deletions packages/table/src/queries/getTableGridAbove.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,8 +72,6 @@ export const getTableGridAbove = <
return [start] as GetTableGridReturnType<T>;
}

console.log('return all', start, table);

return {
tableEntries: [[table, start[1].slice(0, -2)]],
cellEntries: [start],
Expand Down
41 changes: 2 additions & 39 deletions packages/table/src/queries/getTableGridByRange.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import { Range } from 'slate';

import { ELEMENT_TABLE } from '../createTablePlugin';
import { TTableCellElement, TTableElement, TTableRowElement } from '../types';
import { getCellTypes } from '../utils';
import { findCellByIndexes, getCellTypes } from '../utils';
import { getEmptyTableNode } from '../utils/getEmptyTableNode';

export type FormatType = 'table' | 'cell' | 'all';
Expand Down Expand Up @@ -90,7 +90,7 @@ export const getTableGridByRange = <T extends FormatType, V extends Value>(
let rowIndex = startRowIndex;
let colIndex = startColIndex;
while (true) {
const cell = findCellByIndexes(editor, realTable, rowIndex, colIndex);
const cell = findCellByIndexes(realTable, rowIndex, colIndex);
if (!cell) {
break;
}
Expand Down Expand Up @@ -139,45 +139,8 @@ export const getTableGridByRange = <T extends FormatType, V extends Value>(
return [[table, tablePath]] as GetTableGridReturnType<T>;
}

console.log('return entries', [[table, tablePath]], cellEntries);

return {
tableEntries: [[table, tablePath]],
cellEntries,
} as GetTableGridReturnType<T>;
};

const findCellByIndexes = <V extends Value>(
editor: PlateEditor<V>,
table: TTableElement,
searchRowIndex: number,
searchColIndex: number
) => {
const allCells = table.children.flatMap(
(current) => current.children
) as TTableCellElement[];

console.log('searching for', searchRowIndex, searchColIndex);
const foundCell = allCells.find((cell) => {
const cellElement = cell as TTableCellElement;

const colIndex = cellElement.colIndex!;
const endColIndex = cellElement.colIndex! + cellElement.colSpan! - 1;
const rowIndex = cellElement.rowIndex!;
const endRowIndex = cellElement.rowIndex! + cellElement.rowSpan! - 1;

console.log('current', colIndex, endColIndex, rowIndex, endRowIndex);
if (
searchColIndex >= colIndex &&
searchColIndex <= endColIndex &&
searchRowIndex >= rowIndex &&
searchRowIndex <= endRowIndex
) {
return true;
}

return false;
});

return foundCell;
};
6 changes: 3 additions & 3 deletions packages/table/src/queries/getTableOverriddenColSizes.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import { DEFAULT_MIN_COL_WIDTH } from '../createTablePlugin';
import { TableStoreSizeOverrides } from '../stores/index';

const DEFAULT_COL_WIDTH = 200;

/**
* Returns node.colSizes if it exists, applying overrides, otherwise returns a
* colSizes with default widths. Since colSizes should always return valid widths
* of the columns for table cells merging feature.
*/
export const getTableOverriddenColSizes = (
colCount: number,
minColumnWidth?: number,
colSizes?: number[],
colSizeOverrides?: TableStoreSizeOverrides
): number[] => {
Expand All @@ -19,7 +19,7 @@ export const getTableOverriddenColSizes = (
if (overridden) return overridden;
if (size > 0) return size;

return DEFAULT_COL_WIDTH;
return minColumnWidth || DEFAULT_MIN_COL_WIDTH;
});

return newColSizes;
Expand Down
Loading

0 comments on commit d777438

Please sign in to comment.