Skip to content

Commit ab551cc

Browse files
waleedlatif1claude
andauthored
refactor(tables): decouple UI display from DB position (#4448)
* refactor(tables): phase 1 — gutter numbering from array index Delete the PositionGapRows component, the gap-fill loop, and the GAP_CHECKBOX_CLASS / GAP_ROW_LIMIT / PositionGapRowsProps surface area. The server's recompactPositions() guarantees positions are 0..N-1 contiguous in the unfiltered view, so the phantom-row machinery has been defending against a state that essentially never happens. DataRow now receives an arrayIndex prop and renders {arrayIndex + 1} in the gutter. Selection coordinates still flow through row.position; that switches in phase 2. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * refactor(tables): phase 2-5 — selection by array index, checks by row id Decouple Tables UI selection coordinates from DB position: - rowIndex semantics shift from row.position to array index across selection state, mouse handlers, keyboard nav, paste, scrollIntoView - checkedRows: Set<number> (position) → Set<string> (rowId), survives sort/filter and realtime row inserts - lastCheckboxRowRef stores rowId; shift-click range resolves to current array indices for visual-order ranges - Drop positionMap/maxPosition derived state in favor of direct rowsRef reads - ExpandedCellPopover anchors via data-row-id (row-id-stable) instead of data-row (array index) - collectRowSnapshots accepts Iterable<TableRowType> directly - Add bounds-validation effect to clamp anchor/focus when rows.length shrinks (sort change, pagination, realtime delete) - Drop redundant arrayIndex prop on DataRow (rowIndex now equals it) Server-side position math stays at API boundary only: insertRow, duplicateRow, shift-Enter append, paste create-batch, undo snapshots. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * refactor(tables): rowId-stable selection across sort, position math via reduce - Track anchor/focus by rowId so same-length sort changes remap selection to the new visual index instead of leaving it on a different row. - Replace last-row position lookups with Math.max reduce in paste's create-batch and append-row's undo snapshot — under non-position sorts, the last visual row's position is not the largest. - Trim a navigation-noise comment and tighten two over-explanatory ones. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * fix(tables): guard rowId remap effect and document paste batch position - Skip the validation effect when rows is empty (transient state during initial load of a new sort/filter before keepPreviousData populates) so selection survives uncached query changes. - Skip when isColumnSelection is true; the column-selection pinning effect owns focus.rowIndex for those, and remapping would shrink a full-column range to wherever the captured endpoints happened to land after reorder. - Comment lastRowPosition's hoist invariant so a future refactor doesn't move it inside the loop and produce colliding positions. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
1 parent e14a3a5 commit ab551cc

3 files changed

Lines changed: 200 additions & 341 deletions

File tree

apps/sim/app/workspace/[workspaceId]/tables/[tableId]/components/table/cells/expanded-cell-popover.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ export function ExpandedCellPopover({
7878
return
7979
}
8080
setDraftValue(isEditable ? formatValueForInput(target.value, target.column.type) : '')
81-
const selector = `[data-table-scroll] [data-row="${target.row.position}"][data-col="${target.colIndex}"]`
81+
const selector = `[data-table-scroll] [data-row-id="${target.row.id}"][data-col="${target.colIndex}"]`
8282
const el = document.querySelector<HTMLElement>(selector)
8383
if (!el) {
8484
setRect(null)

0 commit comments

Comments
 (0)