Review follow-up (Sara): j/k wrap-around and fresh-entry had no direct coverage — the logic lived inline in the page where the action spec only mocks the callbacks. Extracted to a pure stepRegion() with 9 unit tests (empty list, forward/back, both wraps, fresh-entry null + unknown id, length-1). Also replaces the inline nested ternary Felix flagged. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
34 lines
1.1 KiB
TypeScript
34 lines
1.1 KiB
TypeScript
/**
|
|
* Region navigation for the transcribe keyboard shortcuts (j/k) — issue #327.
|
|
*
|
|
* Pure and side-effect free so the wrap-around / fresh-entry branches are
|
|
* unit-testable without mounting the page.
|
|
*/
|
|
|
|
/**
|
|
* Pick the annotation id one step from the active region, wrapping around the
|
|
* ends. Entering fresh (no active region, or an unknown id) lands on the first
|
|
* region going forward and the last going backward.
|
|
*
|
|
* @param orderedAnnotationIds region annotation ids in display order
|
|
* @param activeId the currently active region, or null
|
|
* @param delta +1 for next (j), -1 for previous (k)
|
|
* @returns the next annotation id, or null when there are no regions
|
|
*/
|
|
export function stepRegion(
|
|
orderedAnnotationIds: string[],
|
|
activeId: string | null,
|
|
delta: 1 | -1
|
|
): string | null {
|
|
const count = orderedAnnotationIds.length;
|
|
if (count === 0) return null;
|
|
|
|
const current = activeId === null ? -1 : orderedAnnotationIds.indexOf(activeId);
|
|
if (current === -1) {
|
|
return delta > 0 ? orderedAnnotationIds[0] : orderedAnnotationIds[count - 1];
|
|
}
|
|
|
|
const next = (current + delta + count) % count;
|
|
return orderedAnnotationIds[next];
|
|
}
|