From 36ccbd5af100c30a88325e7d315ab4a8ab2498fb Mon Sep 17 00:00:00 2001 From: huanhuanwa <2323666215@qq.com> Date: Fri, 28 Jun 2024 18:40:51 +0800 Subject: [PATCH 1/4] feat(core): adjust table resize --- .changeset/forty-dogs-admire.md | 5 + packages/draw/src/interfaces/index.ts | 9 +- .../draw/src/plugins/with-table-resize.ts | 129 +++++++++++++++--- 3 files changed, 120 insertions(+), 23 deletions(-) create mode 100644 .changeset/forty-dogs-admire.md diff --git a/.changeset/forty-dogs-admire.md b/.changeset/forty-dogs-admire.md new file mode 100644 index 000000000..8a70446f2 --- /dev/null +++ b/.changeset/forty-dogs-admire.md @@ -0,0 +1,5 @@ +--- +'@plait/draw': patch +--- + +adjust table resize diff --git a/packages/draw/src/interfaces/index.ts b/packages/draw/src/interfaces/index.ts index ee12bea58..213e653cb 100644 --- a/packages/draw/src/interfaces/index.ts +++ b/packages/draw/src/interfaces/index.ts @@ -49,7 +49,12 @@ export const PlaitDrawElement = { } }, isShapeElement: (value: any): value is PlaitShapeElement => { - return PlaitDrawElement.isImage(value) || PlaitDrawElement.isGeometry(value) || PlaitDrawElement.isTable(value) || PlaitDrawElement.isSwimlane(value); + return ( + PlaitDrawElement.isImage(value) || + PlaitDrawElement.isGeometry(value) || + PlaitDrawElement.isTable(value) || + PlaitDrawElement.isSwimlane(value) + ); }, isBasicShape: (value: any) => { return Object.keys(BasicShapes).includes(value.shape); @@ -77,5 +82,5 @@ export const PlaitDrawElement = { }, isElementByTable: (value: any): value is PlaitBaseTable => { return PlaitDrawElement.isTable(value) || PlaitDrawElement.isSwimlane(value) || PlaitDrawElement.isGeometryByTable(value); - }, + } }; diff --git a/packages/draw/src/plugins/with-table-resize.ts b/packages/draw/src/plugins/with-table-resize.ts index 506a258c1..55fe78c4d 100644 --- a/packages/draw/src/plugins/with-table-resize.ts +++ b/packages/draw/src/plugins/with-table-resize.ts @@ -1,5 +1,5 @@ import { getHitElementByPoint, PlaitBoard, Point, RectangleClient, Transforms, isSelectedElement } from '@plait/core'; -import { PlaitBaseTable, PlaitTableBoard, PlaitTableCellWithPoints } from '../interfaces/table'; +import { PlaitBaseTable, PlaitTable, PlaitTableBoard, PlaitTableCellWithPoints, PlaitTableElement } from '../interfaces/table'; import { getIndexByResizeHandle, isCornerHandle, @@ -22,7 +22,7 @@ interface TableResizeOptions extends ResizeOptions { cell: PlaitTableCellWithPoints; } -const MIN_CELL_SIZE = 20; +const MIN_CELL_SIZE = 32; export function withTableResize(board: PlaitTableBoard) { let snapG: SVGGElement | null; @@ -95,7 +95,7 @@ export function withTableResize(board: PlaitTableBoard) { } } else { const isFromCorner = isCornerHandle(board, resizeRef.handle); - const isAspectRatio = resizeState.isShift; + const isAspectRatio = isFromCorner ? true : resizeState.isShift; const handleIndex = getIndexByResizeHandle(resizeRef.handle); const { originPoint, handlePoint } = getResizeOriginPointAndHandlePoint(board, handleIndex, resizeRef.rectangle!); const resizeSnapRefOptions = getSnapResizingRefOptions( @@ -120,29 +120,51 @@ export function withTableResize(board: PlaitTableBoard) { const offsetHeight = targetRect.height - originRect.height; let columns = [...resizeRef.element.columns]; let rows = [...resizeRef.element.rows]; - if (offsetWidth !== 0) { - columns = columns.map(item => { - if (item.width) { - return { - ...item, - width: item.width + offsetWidth * (item.width / originRect.width) + let update = false; + if (!isFromCorner) { + const { + columnWidth, + rowHeight, + columnIndex, + rowIndex, + minCellWidthInColumn, + minCellHeightInRow + } = getUpdateTableContent(board, resizeRef.element, handleIndex); + if (!columnWidth || !rowHeight) { + if (!columnWidth) { + columns[columnIndex] = { + ...columns[columnIndex], + width: minCellWidthInColumn }; } - return item; - }); - } - if (offsetHeight !== 0) { - rows = rows.map(item => { - if (item.height) { - return { - ...item, - height: item.height + offsetHeight * (item.height / originRect.height) + if (!rowHeight) { + rows[rowIndex] = { + ...rows[rowIndex], + height: minCellHeightInRow }; } - return item; - }); + } + if (offsetWidth !== 0 && offsetWidth + columns[columnIndex].width! > MIN_CELL_SIZE) { + columns = calculateRowsOrColumns(columns, offsetWidth, originRect.width, false, false, columnIndex); + update = true; + } + if (offsetHeight !== 0 && offsetHeight + rows[rowIndex].height! > MIN_CELL_SIZE) { + rows = calculateRowsOrColumns(rows, offsetHeight, originRect.height, false, true, rowIndex); + update = true; + } + } else { + if (offsetWidth !== 0) { + columns = calculateRowsOrColumns(columns, offsetWidth, originRect.width, true, false); + } + if (offsetHeight !== 0) { + rows = calculateRowsOrColumns(rows, offsetHeight, originRect.height, true, true); + } + update = true; + } + + if (update) { + Transforms.setNode(board, { points: normalizeShapePoints(points), rows, columns }, path); } - Transforms.setNode(board, { points: normalizeShapePoints(points), columns, rows }, path); } }, afterResize: (resizeRef: ResizeRef) => { @@ -155,3 +177,68 @@ export function withTableResize(board: PlaitTableBoard) { return board; } + +function calculateRowsOrColumns( + data: { id: string; width?: number; height?: number }[], + offset: number, + originSize: number, + isFromCorner: boolean, + isRow: boolean, + updateIndex?: number +) { + return data.map((item, index) => { + const isUpdateIndex = index === updateIndex; + if (isFromCorner || (isUpdateIndex && !isFromCorner)) { + const dimension = isRow ? 'height' : 'width'; + if (item[dimension]) { + const adjustedValue = isFromCorner + ? item[dimension]! + offset * (item[dimension]! / originSize) + : item[dimension]! + offset; + return { + ...item, + [dimension]: adjustedValue + }; + } + } + return item; + }); +} + +function getUpdateTableContent(board: PlaitBoard, element: PlaitBaseTable, handleIndex: number) { + let columnIndex = 0; + let rowIndex = 0; + const { columns, rows } = element; + const cellsWithPoints = getCellsWithPoints(board, element); + if ([Number(ResizeHandle.s), Number(ResizeHandle.e)].includes(handleIndex)) { + columnIndex = columns.length - 1; + rowIndex = rows.length - 1; + } + const rowId = rows[rowIndex].id; + const columnId = columns[columnIndex].id; + const { minCellWidthInColumn, minCellHeightInRow } = cellsWithPoints.reduce( + (acc, item) => { + if (item.rowId === rowId) { + const { height } = RectangleClient.getRectangleByPoints(item.points); + if (acc.minCellHeightInRow === -1 || height < acc.minCellHeightInRow) { + acc.minCellHeightInRow = height; + } + } + if (item.columnId === columnId) { + const { width } = RectangleClient.getRectangleByPoints(item.points); + if (acc.minCellWidthInColumn === -1 || width < acc.minCellWidthInColumn) { + acc.minCellWidthInColumn = width; + } + } + return acc; + }, + { minCellWidthInColumn: -1, minCellHeightInRow: -1 } + ); + return { + rowIndex, + columnIndex, + rowHeight: rows[rowIndex].height || 0, + columnWidth: columns[columnIndex].width || 0, + minCellWidthInColumn, + minCellHeightInRow + }; +} From 860fc62ac28f9238aca3646296e9459f5f05b4ce Mon Sep 17 00:00:00 2001 From: huanhuanwa <2323666215@qq.com> Date: Mon, 1 Jul 2024 11:15:49 +0800 Subject: [PATCH 2/4] fix: optimize code --- .../draw/src/plugins/with-table-resize.ts | 92 +++++++++---------- 1 file changed, 44 insertions(+), 48 deletions(-) diff --git a/packages/draw/src/plugins/with-table-resize.ts b/packages/draw/src/plugins/with-table-resize.ts index 55fe78c4d..4c85234a2 100644 --- a/packages/draw/src/plugins/with-table-resize.ts +++ b/packages/draw/src/plugins/with-table-resize.ts @@ -1,5 +1,5 @@ import { getHitElementByPoint, PlaitBoard, Point, RectangleClient, Transforms, isSelectedElement } from '@plait/core'; -import { PlaitBaseTable, PlaitTable, PlaitTableBoard, PlaitTableCellWithPoints, PlaitTableElement } from '../interfaces/table'; +import { PlaitBaseTable, PlaitTableBoard, PlaitTableCellWithPoints } from '../interfaces/table'; import { getIndexByResizeHandle, isCornerHandle, @@ -122,35 +122,57 @@ export function withTableResize(board: PlaitTableBoard) { let rows = [...resizeRef.element.rows]; let update = false; if (!isFromCorner) { - const { - columnWidth, - rowHeight, - columnIndex, - rowIndex, - minCellWidthInColumn, - minCellHeightInRow - } = getUpdateTableContent(board, resizeRef.element, handleIndex); - if (!columnWidth || !rowHeight) { - if (!columnWidth) { + const { columnIndex, rowIndex } = getResizeRowAndColumnIndex(resizeRef.element, handleIndex); + if (offsetWidth !== 0) { + if (!columns[columnIndex].width) { + const cellsWithPoints = getCellsWithPoints(board, resizeRef.element); + const { minCellWidthInColumn } = cellsWithPoints.reduce( + (acc, item) => { + if (item.columnId === columns[columnIndex].id) { + const { width } = RectangleClient.getRectangleByPoints(item.points); + if (!acc.minCellWidthInColumn || width < acc.minCellWidthInColumn) { + acc.minCellWidthInColumn = width; + } + } + return acc; + }, + { minCellWidthInColumn: 0 } + ); columns[columnIndex] = { ...columns[columnIndex], width: minCellWidthInColumn }; } - if (!rowHeight) { + if (offsetWidth + columns[columnIndex].width! > MIN_CELL_SIZE) { + columns = calculateRowsOrColumns(columns, offsetWidth, originRect.width, false, false, columnIndex); + update = true; + } + } + + if (offsetHeight !== 0) { + if (!rows[rowIndex].height) { + const cellsWithPoints = getCellsWithPoints(board, resizeRef.element); + const { minCellHeightInRow } = cellsWithPoints.reduce( + (acc, item) => { + if (item.rowId === rows[rowIndex].id) { + const { height } = RectangleClient.getRectangleByPoints(item.points); + if (!acc.minCellHeightInRow || height < acc.minCellHeightInRow) { + acc.minCellHeightInRow = height; + } + } + return acc; + }, + { minCellHeightInRow: 0 } + ); rows[rowIndex] = { ...rows[rowIndex], height: minCellHeightInRow }; } - } - if (offsetWidth !== 0 && offsetWidth + columns[columnIndex].width! > MIN_CELL_SIZE) { - columns = calculateRowsOrColumns(columns, offsetWidth, originRect.width, false, false, columnIndex); - update = true; - } - if (offsetHeight !== 0 && offsetHeight + rows[rowIndex].height! > MIN_CELL_SIZE) { - rows = calculateRowsOrColumns(rows, offsetHeight, originRect.height, false, true, rowIndex); - update = true; + if (offsetHeight + rows[rowIndex].height! > MIN_CELL_SIZE) { + rows = calculateRowsOrColumns(rows, offsetHeight, originRect.height, false, true, rowIndex); + update = true; + } } } else { if (offsetWidth !== 0) { @@ -161,7 +183,6 @@ export function withTableResize(board: PlaitTableBoard) { } update = true; } - if (update) { Transforms.setNode(board, { points: normalizeShapePoints(points), rows, columns }, path); } @@ -204,41 +225,16 @@ function calculateRowsOrColumns( }); } -function getUpdateTableContent(board: PlaitBoard, element: PlaitBaseTable, handleIndex: number) { +function getResizeRowAndColumnIndex(element: PlaitBaseTable, handleIndex: number) { let columnIndex = 0; let rowIndex = 0; const { columns, rows } = element; - const cellsWithPoints = getCellsWithPoints(board, element); if ([Number(ResizeHandle.s), Number(ResizeHandle.e)].includes(handleIndex)) { columnIndex = columns.length - 1; rowIndex = rows.length - 1; } - const rowId = rows[rowIndex].id; - const columnId = columns[columnIndex].id; - const { minCellWidthInColumn, minCellHeightInRow } = cellsWithPoints.reduce( - (acc, item) => { - if (item.rowId === rowId) { - const { height } = RectangleClient.getRectangleByPoints(item.points); - if (acc.minCellHeightInRow === -1 || height < acc.minCellHeightInRow) { - acc.minCellHeightInRow = height; - } - } - if (item.columnId === columnId) { - const { width } = RectangleClient.getRectangleByPoints(item.points); - if (acc.minCellWidthInColumn === -1 || width < acc.minCellWidthInColumn) { - acc.minCellWidthInColumn = width; - } - } - return acc; - }, - { minCellWidthInColumn: -1, minCellHeightInRow: -1 } - ); return { rowIndex, - columnIndex, - rowHeight: rows[rowIndex].height || 0, - columnWidth: columns[columnIndex].width || 0, - minCellWidthInColumn, - minCellHeightInRow + columnIndex }; } From 73832bee08e6bb06db419bb05377a7535f867043 Mon Sep 17 00:00:00 2001 From: huanhuanwa <2323666215@qq.com> Date: Mon, 1 Jul 2024 16:41:24 +0800 Subject: [PATCH 3/4] fix: optimzie code --- packages/draw/src/plugins/with-table-resize.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/draw/src/plugins/with-table-resize.ts b/packages/draw/src/plugins/with-table-resize.ts index 4c85234a2..b1fd52eca 100644 --- a/packages/draw/src/plugins/with-table-resize.ts +++ b/packages/draw/src/plugins/with-table-resize.ts @@ -95,7 +95,7 @@ export function withTableResize(board: PlaitTableBoard) { } } else { const isFromCorner = isCornerHandle(board, resizeRef.handle); - const isAspectRatio = isFromCorner ? true : resizeState.isShift; + const isAspectRatio = isFromCorner ? true : false; const handleIndex = getIndexByResizeHandle(resizeRef.handle); const { originPoint, handlePoint } = getResizeOriginPointAndHandlePoint(board, handleIndex, resizeRef.rectangle!); const resizeSnapRefOptions = getSnapResizingRefOptions( From 573bc126bb12305c4d25c293d196681708a168b2 Mon Sep 17 00:00:00 2001 From: huanhuanwa <2323666215@qq.com> Date: Tue, 2 Jul 2024 11:12:33 +0800 Subject: [PATCH 4/4] fix(draw): adjust table cell resize --- .../draw/src/plugins/with-table-resize.ts | 273 +++++++++--------- packages/draw/src/utils/table.ts | 20 +- 2 files changed, 151 insertions(+), 142 deletions(-) diff --git a/packages/draw/src/plugins/with-table-resize.ts b/packages/draw/src/plugins/with-table-resize.ts index b1fd52eca..0b477f492 100644 --- a/packages/draw/src/plugins/with-table-resize.ts +++ b/packages/draw/src/plugins/with-table-resize.ts @@ -1,5 +1,5 @@ import { getHitElementByPoint, PlaitBoard, Point, RectangleClient, Transforms, isSelectedElement } from '@plait/core'; -import { PlaitBaseTable, PlaitTableBoard, PlaitTableCellWithPoints } from '../interfaces/table'; +import { PlaitBaseTable, PlaitTableBoard, PlaitTableCell, PlaitTableCellWithPoints } from '../interfaces/table'; import { getIndexByResizeHandle, isCornerHandle, @@ -35,26 +35,10 @@ export function withTableResize(board: PlaitTableBoard) { hitTest: (point: Point) => { const hitElement = getHitElementByPoint(board, point); if (hitElement && PlaitDrawElement.isElementByTable(hitElement)) { - let rectangle = board.getRectangle(hitElement) as RectangleClient; - let handleRef = getHitRectangleResizeHandleRef(board, rectangle, point, hitElement.angle); - if (handleRef) { - const selectElement = isSelectedElement(board, hitElement); - if ( - (selectElement && isSingleSelectElementByTable(board)) || - (!selectElement && !isCornerHandle(board, handleRef.handle)) - ) { - return { - element: hitElement, - handle: handleRef.handle, - cursorClass: handleRef.cursorClass, - rectangle - }; - } - } const cells = getCellsWithPoints(board, hitElement); for (let i = 0; i < cells.length; i++) { - rectangle = RectangleClient.getRectangleByPoints(cells[i].points); - handleRef = getHitRectangleResizeHandleRef(board, rectangle, point, 0); + const rectangle = RectangleClient.getRectangleByPoints(cells[i].points); + const handleRef = getHitRectangleResizeHandleRef(board, rectangle, point, 0); if (handleRef && !isCornerHandle(board, handleRef.handle)) { return { element: hitElement, @@ -67,12 +51,29 @@ export function withTableResize(board: PlaitTableBoard) { }; } } + const rectangle = board.getRectangle(hitElement) as RectangleClient; + const handleRef = getHitRectangleResizeHandleRef(board, rectangle, point, hitElement.angle); + if (handleRef) { + const selectElement = isSelectedElement(board, hitElement); + if ( + (selectElement && isSingleSelectElementByTable(board)) || + (!selectElement && !isCornerHandle(board, handleRef.handle)) + ) { + return { + element: hitElement, + handle: handleRef.handle, + cursorClass: handleRef.cursorClass, + rectangle + }; + } + } } return null; }, onResize: (resizeRef: ResizeRef, resizeState: ResizeState) => { snapG?.remove(); const path = PlaitBoard.findPath(board, resizeRef.element); + if (resizeRef.options?.cell && resizeRef.rectangle) { const handleIndex = getIndexByResizeHandle(resizeRef.handle); const { originPoint, handlePoint } = getResizeOriginPointAndHandlePoint(board, handleIndex, resizeRef.rectangle!); @@ -82,108 +83,81 @@ export function withTableResize(board: PlaitTableBoard) { const targetPoints = originPoints.map(p => { return movePointByZoomAndOriginPoint(p, originPoint, xZoom, yZoom); }) as [Point, Point]; - const offsetX = targetPoints[1][0] - originPoints[1][0]; - const offsetY = targetPoints[1][1] - originPoints[1][1]; - const width = targetPoints[1][0] - targetPoints[0][0]; - const height = targetPoints[1][1] - targetPoints[0][1]; - if (offsetX !== 0 && width >= MIN_CELL_SIZE) { - const { columns, points } = updateColumns(resizeRef.element, resizeRef.options?.cell.columnId, width, offsetX); - Transforms.setNode(board, { columns, points }, path); - } else if (offsetY !== 0 && height >= MIN_CELL_SIZE) { - const { rows, points } = updateRows(resizeRef.element, resizeRef.options?.cell.rowId, height, offsetY); - Transforms.setNode(board, { rows, points }, path); - } - } else { - const isFromCorner = isCornerHandle(board, resizeRef.handle); - const isAspectRatio = isFromCorner ? true : false; - const handleIndex = getIndexByResizeHandle(resizeRef.handle); - const { originPoint, handlePoint } = getResizeOriginPointAndHandlePoint(board, handleIndex, resizeRef.rectangle!); - const resizeSnapRefOptions = getSnapResizingRefOptions( - board, - resizeRef, - resizeState, - { - originPoint, - handlePoint - }, - isAspectRatio, - isFromCorner - ); - const resizeSnapRef = getSnapResizingRef(board, [resizeRef.element], resizeSnapRefOptions); - snapG = resizeSnapRef.snapG; - PlaitBoard.getElementActiveHost(board).append(snapG); - const points = resizeSnapRef.activePoints as [Point, Point]; - const originPoints = resizeRef.element.points; + const originRect = RectangleClient.getRectangleByPoints(originPoints); - const targetRect = RectangleClient.getRectangleByPoints(points); + const targetRect = RectangleClient.getRectangleByPoints(targetPoints); const offsetWidth = targetRect.width - originRect.width; const offsetHeight = targetRect.height - originRect.height; - let columns = [...resizeRef.element.columns]; - let rows = [...resizeRef.element.rows]; - let update = false; - if (!isFromCorner) { - const { columnIndex, rowIndex } = getResizeRowAndColumnIndex(resizeRef.element, handleIndex); - if (offsetWidth !== 0) { - if (!columns[columnIndex].width) { - const cellsWithPoints = getCellsWithPoints(board, resizeRef.element); - const { minCellWidthInColumn } = cellsWithPoints.reduce( - (acc, item) => { - if (item.columnId === columns[columnIndex].id) { - const { width } = RectangleClient.getRectangleByPoints(item.points); - if (!acc.minCellWidthInColumn || width < acc.minCellWidthInColumn) { - acc.minCellWidthInColumn = width; - } - } - return acc; - }, - { minCellWidthInColumn: 0 } - ); - columns[columnIndex] = { - ...columns[columnIndex], - width: minCellWidthInColumn - }; - } - if (offsetWidth + columns[columnIndex].width! > MIN_CELL_SIZE) { - columns = calculateRowsOrColumns(columns, offsetWidth, originRect.width, false, false, columnIndex); - update = true; - } + const direction = getResizeCellDirection(handleIndex); + if (offsetWidth !== 0 && direction) { + const columnIndex = getResizeColumnOrRowIndex(resizeRef.element, resizeRef.options?.cell, direction, false); + let width = targetPoints[1][0] - targetPoints[0][0]; + if (resizeRef.options?.cell.colspan && resizeRef.options?.cell.colspan !== 1) { + const columnWidth = getResizeColumnOrRowSize(board, resizeRef.element, columnIndex, false); + width = columnWidth + offsetWidth; } - - if (offsetHeight !== 0) { - if (!rows[rowIndex].height) { - const cellsWithPoints = getCellsWithPoints(board, resizeRef.element); - const { minCellHeightInRow } = cellsWithPoints.reduce( - (acc, item) => { - if (item.rowId === rows[rowIndex].id) { - const { height } = RectangleClient.getRectangleByPoints(item.points); - if (!acc.minCellHeightInRow || height < acc.minCellHeightInRow) { - acc.minCellHeightInRow = height; - } - } - return acc; - }, - { minCellHeightInRow: 0 } - ); - rows[rowIndex] = { - ...rows[rowIndex], - height: minCellHeightInRow - }; - } - if (offsetHeight + rows[rowIndex].height! > MIN_CELL_SIZE) { - rows = calculateRowsOrColumns(rows, offsetHeight, originRect.height, false, true, rowIndex); - update = true; - } + if (width >= MIN_CELL_SIZE) { + const { columns, points } = updateColumns( + resizeRef.element, + resizeRef.element.columns[columnIndex].id, + width, + offsetWidth, + direction + ); + Transforms.setNode(board, { columns, points }, path); + } + } + if (offsetHeight !== 0 && direction) { + const rowIndex = getResizeColumnOrRowIndex(resizeRef.element, resizeRef.options?.cell, direction, true); + let height = targetPoints[1][1] - targetPoints[0][1]; + if (resizeRef.options?.cell.rowspan && resizeRef.options?.cell.rowspan !== 1) { + const rowHeight = getResizeColumnOrRowSize(board, resizeRef.element, rowIndex, true); + height = rowHeight + offsetHeight; } - } else { + if (height >= MIN_CELL_SIZE) { + const { rows, points } = updateRows( + resizeRef.element, + resizeRef.element.rows[rowIndex].id, + height, + offsetHeight, + direction + ); + Transforms.setNode(board, { rows, points }, path); + } + } + } else { + const isFromCorner = isCornerHandle(board, resizeRef.handle); + if (isFromCorner) { + const handleIndex = getIndexByResizeHandle(resizeRef.handle); + const { originPoint, handlePoint } = getResizeOriginPointAndHandlePoint(board, handleIndex, resizeRef.rectangle!); + const resizeSnapRefOptions = getSnapResizingRefOptions( + board, + resizeRef, + resizeState, + { + originPoint, + handlePoint + }, + true, + true + ); + const resizeSnapRef = getSnapResizingRef(board, [resizeRef.element], resizeSnapRefOptions); + snapG = resizeSnapRef.snapG; + PlaitBoard.getElementActiveHost(board).append(snapG); + const points = resizeSnapRef.activePoints as [Point, Point]; + const originPoints = resizeRef.element.points; + const originRect = RectangleClient.getRectangleByPoints(originPoints); + const targetRect = RectangleClient.getRectangleByPoints(points); + const offsetWidth = targetRect.width - originRect.width; + const offsetHeight = targetRect.height - originRect.height; + let columns = [...resizeRef.element.columns]; + let rows = [...resizeRef.element.rows]; if (offsetWidth !== 0) { - columns = calculateRowsOrColumns(columns, offsetWidth, originRect.width, true, false); + columns = calculateRowsOrColumns(columns, offsetWidth, originRect.width, false); } if (offsetHeight !== 0) { - rows = calculateRowsOrColumns(rows, offsetHeight, originRect.height, true, true); + rows = calculateRowsOrColumns(rows, offsetHeight, originRect.height, true); } - update = true; - } - if (update) { Transforms.setNode(board, { points: normalizeShapePoints(points), rows, columns }, path); } } @@ -203,38 +177,61 @@ function calculateRowsOrColumns( data: { id: string; width?: number; height?: number }[], offset: number, originSize: number, - isFromCorner: boolean, - isRow: boolean, - updateIndex?: number + isRow: boolean ) { - return data.map((item, index) => { - const isUpdateIndex = index === updateIndex; - if (isFromCorner || (isUpdateIndex && !isFromCorner)) { - const dimension = isRow ? 'height' : 'width'; - if (item[dimension]) { - const adjustedValue = isFromCorner - ? item[dimension]! + offset * (item[dimension]! / originSize) - : item[dimension]! + offset; - return { - ...item, - [dimension]: adjustedValue - }; - } + const dimension = isRow ? 'height' : 'width'; + return data.map(item => { + if (item[dimension]) { + const value = item[dimension]! + offset * (item[dimension]! / originSize); + return { + ...item, + [dimension]: value + }; } return item; }); } -function getResizeRowAndColumnIndex(element: PlaitBaseTable, handleIndex: number) { - let columnIndex = 0; - let rowIndex = 0; - const { columns, rows } = element; +function getResizeCellDirection(handleIndex: number) { if ([Number(ResizeHandle.s), Number(ResizeHandle.e)].includes(handleIndex)) { - columnIndex = columns.length - 1; - rowIndex = rows.length - 1; + return 'end'; } - return { - rowIndex, - columnIndex - }; + if ([Number(ResizeHandle.n), Number(ResizeHandle.w)].includes(handleIndex)) { + return 'start'; + } + return undefined; +} + +function getResizeColumnOrRowIndex(element: PlaitBaseTable, resizeCell: PlaitTableCell, direction: 'start' | 'end', isRow: boolean) { + const data = isRow ? element.rows : element.columns; + const id = isRow ? resizeCell.rowId : resizeCell.columnId; + const span = isRow ? resizeCell.rowspan : resizeCell.colspan; + let index = data.findIndex(item => item.id === id); + if (direction === 'end' && span && span !== 1) { + index += span - 1; + } + return index; +} + +function getResizeColumnOrRowSize(board: PlaitBoard, element: PlaitBaseTable, index: number, isRow: boolean) { + const size = isRow ? element.rows[index]['height'] : element.columns[index]['width']; + if (size) { + return size; + } + const id = isRow ? element.rows[index].id : element.columns[index].id; + const dimension = isRow ? 'height' : 'width'; + const cellsWithPoints = getCellsWithPoints(board, element); + const minDimension = cellsWithPoints.reduce((acc, item) => { + const itemId = isRow ? item.rowId : item.columnId; + if (itemId === id) { + const rectangle = RectangleClient.getRectangleByPoints(item.points); + const itemSize = rectangle[dimension]; + if (!acc || itemSize < acc) { + acc = itemSize; + } + } + return acc; + }, 0); + + return minDimension; } diff --git a/packages/draw/src/utils/table.ts b/packages/draw/src/utils/table.ts index 008a0dfd2..d0c1470fc 100644 --- a/packages/draw/src/utils/table.ts +++ b/packages/draw/src/utils/table.ts @@ -107,15 +107,27 @@ export function getTextManageByCell(cell: PlaitTableCell) { return getTextManage(cell.id); } -export const updateColumns = (table: PlaitBaseTable, columnId: string, width: number, offset: number) => { +export const updateColumns = ( + table: PlaitBaseTable, + columnId: string, + width: number, + offset: number, + direction: 'start' | 'end' = 'end' +) => { const columns = table.columns.map(item => (item.id === columnId ? { ...item, width } : item)); - const points = [table.points[0], [table.points[1][0] + offset, table.points[1][1]]] as Point[]; + let points = [table.points[0], [table.points[1][0] + offset, table.points[1][1]]] as Point[]; + if (direction === 'start') { + points = [[table.points[0][0] - offset, table.points[0][1]], table.points[1]] as Point[]; + } return { columns, points }; }; -export const updateRows = (table: PlaitBaseTable, rowId: string, height: number, offset: number) => { +export const updateRows = (table: PlaitBaseTable, rowId: string, height: number, offset: number, direction: 'start' | 'end' = 'end') => { const rows = table.rows.map(item => (item.id === rowId ? { ...item, height } : item)); - const points = [table.points[0], [table.points[1][0], table.points[1][1] + offset]] as Point[]; + let points = [table.points[0], [table.points[1][0], table.points[1][1] + offset]] as Point[]; + if (direction === 'start') { + points = [[table.points[0][0], table.points[0][1] - offset], table.points[1]] as Point[]; + } return { rows, points }; };