Skip to content

Commit

Permalink
improve selection, indices computation
Browse files Browse the repository at this point in the history
  • Loading branch information
dimaanj committed Nov 10, 2023
1 parent ec077ff commit c55ccf3
Show file tree
Hide file tree
Showing 15 changed files with 336 additions and 198 deletions.
1 change: 1 addition & 0 deletions apps/www/src/lib/plate/demo/values/tableValue.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,7 @@ export const tableValue: any = (
to design structured layouts.
</hp>
{createMergedCellsTable()}
{createSpanningTable()}
{/* {createTable()} */}
{/* <hp>
This table is an example of rendering a table spanning multiple columns:
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,19 @@
import { useEffect } from 'react';
import { useEditorRef, useElement } from '@udecode/plate-common';
import { useEffect, useMemo } from 'react';
import {
getPluginOptions,
useEditorRef,
useElement,
} from '@udecode/plate-common';
import { useReadOnly } from 'slate-react';

import { ELEMENT_TABLE, ELEMENT_TR } from '../../createTablePlugin';
import { getCellIndices } from '../../queries/getCellIdices';
import { getColSpan } from '../../queries/getColSpan';
import { getRowSpan } from '../../queries/getRowSpan';
import { getTableColumnIndex, getTableRowIndex } from '../../queries/index';
import { useTableStore } from '../../stores/tableStore';
import {
TablePlugin,
TTableCellElement,
TTableElement,
TTableRowElement,
Expand All @@ -29,24 +37,6 @@ export type TableCellElementState = {
colSpan: number;
};

/**
* Returns the colspan attribute of the table cell element.
* @default 1 if undefined.
*/
export const getColSpan = (cellElem: TTableCellElement) => {
const attrColSpan = Number(cellElem.attributes?.colspan);
return cellElem.colSpan || attrColSpan || 1;
};

/**
* Returns the rowspan attribute of the table cell element.
* @default 1 if undefined
*/
export const getRowSpan = (cellElem: TTableCellElement) => {
const attrRowSpan = Number(cellElem.attributes?.rowspan);
return cellElem.rowSpan || attrRowSpan || 1;
};

export const useTableCellElementState = ({
ignoreReadOnly,
}: {
Expand All @@ -61,22 +51,39 @@ export const useTableCellElementState = ({
const colSpan = getColSpan(cellElement);
const rowSpan = getRowSpan(cellElement);

const defaultColIndex = getTableColumnIndex(editor, cellElement);
const defaultRowIndex = getTableRowIndex(editor, cellElement);

const readOnly = useReadOnly();

const isCellSelected = useIsCellSelected(cellElement);
const hoveredColIndex = useTableStore().get.hoveredColIndex();
const selectedCells = useTableStore().get.selectedCells();
const cellAttributes = useTableStore().get.cellAttributes();

const tableElement = useElement<TTableElement>(ELEMENT_TABLE);
const rowElement = useElement<TTableRowElement>(ELEMENT_TR);

const x = cellAttributes.get(cellElement);
const colIndex = x?.col ?? defaultColIndex;
const rowIndex = x?.row ?? defaultRowIndex;
const { _cellIndices } = useMemo(
() => getPluginOptions<TablePlugin>(editor as any, ELEMENT_TABLE),
[editor]
);

let x: { col: number; row: number };
const fromWeakMap = _cellIndices.get(cellElement);
if (fromWeakMap) {
x = fromWeakMap;
console.log('from weak map', x, 'cellElement', cellElement);
} else {
const x1 = getCellIndices(editor, tableElement, cellElement);
if (x1) {
x = x1;
console.log('computed', x, 'cellElement', cellElement);
} else {
const defaultColIndex = getTableColumnIndex(editor, cellElement);
const defaultRowIndex = getTableRowIndex(editor, cellElement);
x = { col: defaultColIndex, row: defaultRowIndex };
console.log('get default', x, 'cellElement', cellElement);
}
}
const colIndex = x.col;
const rowIndex = x.row;

const endingRowIndex = rowIndex + rowSpan - 1;
const endingColIndex = colIndex + colSpan - 1;
Expand Down
139 changes: 2 additions & 137 deletions packages/table/src/components/TableElement/useTableElement.ts
Original file line number Diff line number Diff line change
@@ -1,27 +1,13 @@
import { useEffect } from 'react';
import {
collapseSelection,
findNodePath,
getNode,
getParentNode,
getPluginOptions,
PlateEditor,
useEditorRef,
useElement,
} from '@udecode/plate-common';
import { Path } from 'slate';

import { ELEMENT_TABLE } from '../../createTablePlugin';
import {
TableStoreCellAttributes,
useTableStore,
} from '../../stores/tableStore';
import {
TablePlugin,
TTableCellElement,
TTableElement,
TTableRowElement,
} from '../../types';
import { useTableStore } from '../../stores/tableStore';
import { TablePlugin, TTableElement } from '../../types';
import { useSelectedCells } from './useSelectedCells';
import { useTableColSizes } from './useTableColSizes';

Expand Down Expand Up @@ -50,13 +36,6 @@ export const useTableElementState = ({
const element = useElement<TTableElement>();
const selectedCells = useTableStore().get.selectedCells();
const marginLeftOverride = useTableStore().get.marginLeftOverride();
const setCellAttributes = useTableStore().set.cellAttributes();

useEffect(() => {
const newAttributes = new WeakMap() as TableStoreCellAttributes;
calculateCellIndexes(editor, element, newAttributes);
setCellAttributes(newAttributes);
}, [editor, element, setCellAttributes]);

const marginLeft = disableMarginLeft
? 0
Expand Down Expand Up @@ -102,117 +81,3 @@ export const useTableElement = () => {
},
};
};

// const cellAttributes = new WeakMap<
// TTableCellElement,
// { row: number; col: number }
// >();

function getCellIndices(
cellAttributes: TableStoreCellAttributes,
tableEl: TTableElement,
tablePath: Path,
cellPath: Path
) {
const tableNodes = tableEl.children;

let rowIndex = -1;
let colIndex = -1;

for (let r = 0; r < tableNodes.length; r++) {
const row = tableNodes[r] as TTableRowElement;

let cIndex = 0;
for (let c = 0; c < row.children.length; c++) {
const cell = row.children[c] as TTableCellElement;
const curCellPath = [r, c];
if (Path.equals(curCellPath, cellPath)) {
colIndex = cIndex;
rowIndex = r;
break;
}
cIndex += cell.colSpan || 1; // consider 0 and undefined as 1
}
}

tableNodes.slice(0, rowIndex).forEach((pR, _rowIndex) => {
const prevRow = pR as TTableRowElement;
prevRow.children.forEach((pC) => {
const prevCell = pC as TTableCellElement;
const prevIndices = cellAttributes.get(prevCell);
if (prevIndices) {
const { col: prevColIndex } = prevIndices;
if (
// colIndex affects
prevColIndex <= colIndex &&
// rowSpan affects
prevCell.rowSpan &&
prevCell.rowSpan > 1 &&
rowIndex - _rowIndex < prevCell.rowSpan
) {
colIndex += prevCell.colSpan || 1;
}
}
});
});

if (rowIndex === -1 || colIndex === -1) {
console.log('Invalid cell location.');
return null;
}

return { row: rowIndex, col: colIndex };
}

const calculateCellIndexes = (
editor: PlateEditor,
tableNode: TTableElement,
cellAttributes: TableStoreCellAttributes
) => {
// (Place the `getCellIndices()` function from the previous response here)

// Initialize an array to store the indices of each cell
const cellIndicesArray = [];

const tablePath = findNodePath(editor, tableNode)!;

// Iterate through the table rows
for (let r = 0; r < tableNode.children.length; r++) {
const row = tableNode.children[r] as TTableRowElement;
const rowIndicesArray = [];

// Iterate through the row cells
for (let c = 0; c < row.children.length; c++) {
const cell = row.children[c] as TTableCellElement;

// Get cell indices and store them in the row's array
const cellPath = [r, c];
// console.log(
// 'searching for',
// cell.children.map((m) => {
// return (m as any).children[0].text;
// }),
// tableNode,
// tablePath,
// cellPath
// );

const indices = getCellIndices(
cellAttributes,
tableNode,
tablePath,
cellPath
);
if (indices) {
cellAttributes.set(cell, indices);
}
rowIndicesArray.push(indices);
}

// Push the rowIndicesArray to the cellIndicesArray
cellIndicesArray.push(rowIndicesArray);
}

console.log('cellIndicesArray', cellIndicesArray);
return cellIndicesArray;
};
3 changes: 2 additions & 1 deletion packages/table/src/createTablePlugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { createPluginFactory } from '@udecode/plate-common';

import { onKeyDownTable } from './onKeyDownTable';
import { insertTableColumn, insertTableRow } from './transforms/index';
import { TablePlugin } from './types';
import { TablePlugin, TableStoreCellAttributes } from './types';
import { withTable } from './withTable';

export const ELEMENT_TABLE = 'table';
Expand Down Expand Up @@ -36,6 +36,7 @@ export const createTablePlugin = createPluginFactory<TablePlugin>({
});
},
minColumnWidth: 48,
_cellIndices: new WeakMap() as TableStoreCellAttributes,
},
withOverrides: withTable,
plugins: [
Expand Down
41 changes: 41 additions & 0 deletions packages/table/src/queries/findCellByIndexes.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import { Value } from '@udecode/plate-common';

import { TablePlugin, TTableCellElement, TTableElement } from '../types';
import { getIndices } from './getIndices';
import { getIndicesWithSpans } from './getIndicesWithSpans';

export const findCellByIndexes1 = (
options: TablePlugin<Value>,
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 { _startColIndex, _startRowIndex } = getIndices(options, cellElement);
const { _endRowIndex, _endColIndex } = getIndicesWithSpans(
options,
cellElement
);

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

return false;
});

return foundCell;
};
Loading

0 comments on commit c55ccf3

Please sign in to comment.