From 2d15ce8d051d1cc2078ab56e37eaaa1622d111bf Mon Sep 17 00:00:00 2001 From: Mathias Jakobsen Date: Thu, 17 Aug 2023 09:09:54 +0100 Subject: [PATCH] Merge pull request #14317 from overleaf/mj-table-gen-update [visual] in-place table generator updates GitOrigin-RevId: 410411fd9158e6c8c6fe6a5300556800732a252a --- .../components/table-generator/cell.tsx | 2 +- .../contexts/selection-context.tsx | 10 ++++++ .../contexts/table-context.tsx | 4 +-- .../table-generator/toolbar/commands.ts | 30 +++++++++++++++- .../toolbar/toolbar-button.tsx | 1 - .../toolbar/toolbar-dropdown.tsx | 35 ++++++++++++------- .../table-generator/toolbar/toolbar.tsx | 14 ++++---- .../visual/visual-widgets/tabular.tsx | 13 +++++++ 8 files changed, 85 insertions(+), 24 deletions(-) diff --git a/services/web/frontend/js/features/source-editor/components/table-generator/cell.tsx b/services/web/frontend/js/features/source-editor/components/table-generator/cell.tsx index 23b6d29b80..9e0040ede7 100644 --- a/services/web/frontend/js/features/source-editor/components/table-generator/cell.tsx +++ b/services/web/frontend/js/features/source-editor/components/table-generator/cell.tsx @@ -118,7 +118,7 @@ export const Cell: FC<{ if (renderDiv.current && !editing) { const tree = parser.parse(toDisplay) const node = tree.topNode - + renderDiv.current.innerText = '' typesetNodeIntoElement( node, renderDiv.current, diff --git a/services/web/frontend/js/features/source-editor/components/table-generator/contexts/selection-context.tsx b/services/web/frontend/js/features/source-editor/components/table-generator/contexts/selection-context.tsx index 4f3b0afe92..9fe11d0423 100644 --- a/services/web/frontend/js/features/source-editor/components/table-generator/contexts/selection-context.tsx +++ b/services/web/frontend/js/features/source-editor/components/table-generator/contexts/selection-context.tsx @@ -166,6 +166,16 @@ export class TableSelection { maxY === totalRows - 1 ) } + + width() { + const { minX, maxX } = this.normalized() + return maxX - minX + 1 + } + + height() { + const { minY, maxY } = this.normalized() + return maxY - minY + 1 + } } const SelectionContext = createContext< diff --git a/services/web/frontend/js/features/source-editor/components/table-generator/contexts/table-context.tsx b/services/web/frontend/js/features/source-editor/components/table-generator/contexts/table-context.tsx index e074b82827..2560b004ee 100644 --- a/services/web/frontend/js/features/source-editor/components/table-generator/contexts/table-context.tsx +++ b/services/web/frontend/js/features/source-editor/components/table-generator/contexts/table-context.tsx @@ -1,5 +1,5 @@ import { FC, createContext, useContext } from 'react' -import { Positions, TableData } from '../tabular' +import { Positions, TableData, TableRenderingError } from '../tabular' import { CellPosition, CellSeparator, @@ -41,7 +41,7 @@ export const TableProvider: FC<{ // TODO: Validate better that the table matches the column definition for (const row of tableData.table.rows) { if (row.cells.length !== tableData.table.columns.length) { - throw new Error("Table doesn't match column definition") + return } } diff --git a/services/web/frontend/js/features/source-editor/components/table-generator/toolbar/commands.ts b/services/web/frontend/js/features/source-editor/components/table-generator/toolbar/commands.ts index 6e4b19ce66..c72704958f 100644 --- a/services/web/frontend/js/features/source-editor/components/table-generator/toolbar/commands.ts +++ b/services/web/frontend/js/features/source-editor/components/table-generator/toolbar/commands.ts @@ -173,8 +173,15 @@ export const removeRowOrColumns = ( const numberOfRows = positions.rowPositions.length if (selection.spansEntireTable(numberOfColumns, numberOfRows)) { - return emptyTable(view, columnSpecification, positions) + emptyTable(view, columnSpecification, positions) + return new TableSelection({ cell: 0, row: 0 }) } + const removedRows = + Number(selection.isRowSelected(startRow, numberOfColumns)) * + selection.height() + const removedColumns = + Number(selection.isColumnSelected(startCell, numberOfRows)) * + selection.width() for (let row = startRow; row <= endRow; row++) { if (selection.isRowSelected(row, numberOfColumns)) { @@ -221,6 +228,13 @@ export const removeRowOrColumns = ( insert: newSpecification, }) view.dispatch({ changes }) + const updatedNumberOfRows = numberOfRows - removedRows + const updatedNumberOfColumns = numberOfColumns - removedColumns + // Clamp selection to new table size + return new TableSelection({ + cell: Math.max(0, Math.min(updatedNumberOfColumns - 1, startCell)), + row: Math.max(0, Math.min(updatedNumberOfRows - 1, startRow)), + }) } const emptyTable = ( @@ -262,6 +276,13 @@ export const insertRow = ( const numberOfColumns = positions.cells[maxY].length const insert = `\n${' &'.repeat(numberOfColumns - 1)}\\\\` view.dispatch({ changes: { from, to: from, insert } }) + if (!below) { + return selection + } + return new TableSelection( + { cell: 0, row: maxY + 1 }, + { cell: numberOfColumns - 1, row: maxY + 1 } + ) } export const insertColumn = ( @@ -300,6 +321,13 @@ export const insertColumn = ( insert: generateColumnSpecification(columnSpecification), }) view.dispatch({ changes }) + if (!after) { + return selection + } + return new TableSelection( + { cell: maxX + 1, row: 0 }, + { cell: maxX + 1, row: positions.rowPositions.length - 1 } + ) } export const removeNodes = ( diff --git a/services/web/frontend/js/features/source-editor/components/table-generator/toolbar/toolbar-button.tsx b/services/web/frontend/js/features/source-editor/components/table-generator/toolbar/toolbar-button.tsx index b3dbc89f1a..c5d2ee2bfa 100644 --- a/services/web/frontend/js/features/source-editor/components/table-generator/toolbar/toolbar-button.tsx +++ b/services/web/frontend/js/features/source-editor/components/table-generator/toolbar/toolbar-button.tsx @@ -36,7 +36,6 @@ export const ToolbarButton = memo<{ if (command) { event.preventDefault() command(view) - view.focus() } }, [command, view] diff --git a/services/web/frontend/js/features/source-editor/components/table-generator/toolbar/toolbar-dropdown.tsx b/services/web/frontend/js/features/source-editor/components/table-generator/toolbar/toolbar-dropdown.tsx index c31c96518b..7219016cbd 100644 --- a/services/web/frontend/js/features/source-editor/components/table-generator/toolbar/toolbar-dropdown.tsx +++ b/services/web/frontend/js/features/source-editor/components/table-generator/toolbar/toolbar-dropdown.tsx @@ -23,10 +23,9 @@ export const ToolbarDropdown: FC<{ disabled, disabledTooltip, }) => { - const { open, onToggle } = useDropdown() + const { open, onToggle, ref } = useDropdown() const toggleButtonRef = useRef(null) const { ref: tabularRef } = useTabularContext() - const button = ( ) - const overlay = open && tabularRef.current && ( + const overlay = tabularRef.current && ( onToggle(false)} - animation={false} - container={tabularRef.current} - containerPadding={0} - placement="bottom" - rootClose + show={open} target={toggleButtonRef.current ?? undefined} + placement="bottom" + container={tabularRef.current} + animation + containerPadding={0} + onHide={() => onToggle(false)} > + {/* eslint-disable-next-line jsx-a11y/no-static-element-interactions, + jsx-a11y/click-events-have-key-events */} @@ -83,6 +91,7 @@ export const ToolbarDropdown: FC<{ return ( <>