Skip to content

Commit b197d55

Browse files
committed
fix(tables): track the find cursor by match identity, not position
1 parent 62a2297 commit b197d55

1 file changed

Lines changed: 29 additions & 0 deletions

File tree

  • apps/sim/app/workspace/[workspaceId]/tables/[tableId]/components/table-grid

apps/sim/app/workspace/[workspaceId]/tables/[tableId]/components/table-grid/table-grid.tsx

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -495,6 +495,9 @@ export function TableGrid({
495495
const pendingMatchRef = useRef<TableFindMatch | null>(null)
496496
/** Monotonic id for the in-flight match jump; see `goToMatch`. */
497497
const goToMatchSeqRef = useRef(0)
498+
/** The match the cursor is on, by identity rather than position, so a
499+
* reordered result set can re-point at the same cell. */
500+
const activeMatchRef = useRef<TableFindMatch | null>(null)
498501
/** Term the auto-reveal has already run for, so a background refetch of the
499502
* same term doesn't re-jump the viewport. */
500503
const autoRevealedTermRef = useRef('')
@@ -1266,6 +1269,7 @@ export function TableGrid({
12661269
goToMatchSeqRef.current++
12671270
pendingMatchRef.current = null
12681271
cursorIsOnMatchRef.current = false
1272+
activeMatchRef.current = null
12691273
setIsJumping(false)
12701274
}, [trimmedFindQuery, findOpen])
12711275

@@ -1288,9 +1292,32 @@ export function TableGrid({
12881292
setRowSelection((prev) => (prev.kind === 'none' ? prev : ROW_SELECTION_NONE))
12891293
setSelectionFocus(null)
12901294
cursorIsOnMatchRef.current = true
1295+
activeMatchRef.current = match
12911296
setSelectionAnchor({ rowIndex, colIndex })
12921297
}, [rows, displayColumns, pendingMatchTick])
12931298

1299+
/**
1300+
* Re-point the cursor at the match it is actually on after the set changes.
1301+
*
1302+
* The cursor is stored as an index, but the list underneath it is mutable: a
1303+
* row insert or delete elsewhere in the table reorders matches for the SAME
1304+
* term, and index 1 can silently become a different cell. Stepping from it
1305+
* would then revisit the cell the user is on, or skip its neighbour. Matching
1306+
* on (rowId, column) — the match's identity — keeps the cursor attached to the
1307+
* cell rather than the position.
1308+
*
1309+
* When the active match is gone entirely there is nothing to re-point at;
1310+
* `stepBaseIndex` clamps the now-possibly-out-of-range index instead.
1311+
*/
1312+
useEffect(() => {
1313+
const active = activeMatchRef.current
1314+
if (!active || findMatches.length === 0) return
1315+
const index = findMatches.findIndex(
1316+
(m) => m.rowId === active.rowId && m.column === active.column
1317+
)
1318+
if (index !== -1 && index !== currentMatchIndexRef.current) setCurrentMatchIndex(index)
1319+
}, [findMatches])
1320+
12941321
/**
12951322
* A new TERM resets to its first match and reveals it.
12961323
*
@@ -1327,6 +1354,7 @@ export function TableGrid({
13271354
autoRevealedTermRef.current = submittedQuery
13281355
setCurrentMatchIndex(0)
13291356
cursorIsOnMatchRef.current = false
1357+
activeMatchRef.current = null
13301358
const first = findMatches[0]
13311359
if (!first) return
13321360
if (!rowsRef.current.some((r) => r.id === first.rowId)) return
@@ -1389,6 +1417,7 @@ export function TableGrid({
13891417
goToMatchSeqRef.current++
13901418
autoRevealedTermRef.current = ''
13911419
cursorIsOnMatchRef.current = false
1420+
activeMatchRef.current = null
13921421
setIsJumping(false)
13931422
scrollRef.current?.focus({ preventScroll: true })
13941423
}, [])

0 commit comments

Comments
 (0)