1/** 2 * Prev/next navigation flags for the record modal (#421). 3 * 4 * The modal's prev/next buttons derive from the record's position in the 5 * filtered list. A deep link (?record=ID) opens the modal by looking the id up 6 * in the full records set, so a filtered-out record can still be open -- and 7 * then its index in `filteredRecords` is -1. The old inline derivation computed 8 * `hasNext = index < filteredRecords.length - 1`, which is true for index === -1 9 * whenever the list is non-empty: the Next button rendered enabled but 10 * handleModalNav no-ops on index === -1, so it looked clickable and did nothing. 11 * 12 * A record outside the filtered list has no neighbours in that list, so both 13 * flags are false. Guarding hasNext with `index >= 0` makes the button state 14 * honest (disabled) instead of inert. 15 */ 16 17/** 18 * Derive the modal's position and prev/next availability. 19 * @param {Array} filteredRecords - the currently filtered record list 20 * @param {string|null} selectedRecordId - the open record's id 21 * @returns {{index: number, total: number, hasPrev: boolean, hasNext: boolean}} 22 */ 23export function deriveNavFlags(filteredRecords, selectedRecordId) { 24 const list = Array.isArray(filteredRecords) ? filteredRecords : []; 25 const index = list.findIndex(r => r.id === selectedRecordId); 26 return { 27 index, 28 total: list.length, 29 hasPrev: index > 0, 30 hasNext: index >= 0 && index < list.length - 1, 31 }; 32} 33 34export default { deriveNavFlags };
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.