Skip to content

Commit

Permalink
handle invalid cases and write jsdocs
Browse files Browse the repository at this point in the history
  • Loading branch information
onx2 committed Aug 22, 2024
1 parent f63cdfb commit a3823b9
Showing 1 changed file with 51 additions and 13 deletions.
64 changes: 51 additions & 13 deletions src/core/cache.ts
Original file line number Diff line number Diff line change
Expand Up @@ -94,20 +94,32 @@ export const computeTotalSize = (cache: Cache): number => {

/**
* @internal
* Finds the index of an item in the cache whose computed offset is closest to the specified offset.
*
* The search starts from the given initial index `i` and adjusts the search range based on whether
* the offset at `i` is less than or equal to the target offset. If a match is found, the index of
* the item is returned; otherwise, the function returns -1 if the item is not found.
*
* @param {Cache} cache - The cache object containing the data.
* @param {number} offset - The target offset to search for within the cache.
* @param {number} i - The initial index to start searching from.
* @returns {number} - The index of the item closest to the offset, or -1 if not found.
*/
export const findIndex = (cache: Cache, offset: number, i: number): number => {
let low = 0;
let high = cache._length - 1;
if (!isValidIndex(i, cache)) return -1;

let [low, high] = [0, cache._length - 1];
let mid, itemOffset;


if (computeOffset(cache, i) <= offset) {
low = i; // Start searching from initialIndex -> up
low = i; // Start searching from the initial index -> up
} else {
high = i; // Start searching from initialIndex -> down
high = i; // Start searching from the initial index -> down
}

while (low <= high) {
mid = Math.floor((low + high) / 2);
mid = (low + high) >> 1;
itemOffset = computeOffset(cache, mid);

if (itemOffset <= offset) {
Expand All @@ -119,25 +131,51 @@ export const findIndex = (cache: Cache, offset: number, i: number): number => {
high = mid - 1;
}
}
return clamp(low, 0, cache._length - 1);

return -1;
};

const isValidIndex = (index: number, cache: Cache): boolean => {
if (cache._length <= 0) return false;
if (index < 0) return false;
if (index > cache._length - 1) return false;

return true;
}
/**
* Computes the range of item indices that should be rendered based on the current scroll position
* and the viewport size.
*
* The function determines the index of the first item that should be visible (`start`) and the
* index of the last item that should be visible (`end`). It ensures that the computed range is
* valid and within the bounds of the available items, adjusting for invalid cases.
*
* @internal
* @param {Cache} cache - The cache object containing information about the items.
* @param {number} scrollOffset - The current scroll position of the viewport in pixels.
* @param {number} prevStartIndex - The starting index from the previously computed range.
* @param {number} viewportSize - The size of the viewport (height or width) in pixels.
* @returns {ItemsRange} An array with two indices: the starting and ending indices of the visible items.
*/
export const computeRange = (
cache: Cache,
scrollOffset: number,
prevStartIndex: number,
viewportSize: number
): ItemsRange => {
const start = findIndex(
cache,
scrollOffset,
// Clamp because prevStartIndex may exceed the limit when children decreased a lot after scrolling
min(prevStartIndex, cache._length - 1)
);
return [start, findIndex(cache, scrollOffset + viewportSize, start)];
if (cache._length <= 0) return [0, 0];
const lastIndex = cache._length - 1;

// Clamp because prevStartIndex may exceed the limit when children decreased a lot after scrolling
const start = findIndex(cache, scrollOffset, min(prevStartIndex, lastIndex));
if (!isValidIndex(start, cache)) return [0, 0];

const end = findIndex(cache, scrollOffset + viewportSize, start);
if (!isValidIndex(end, cache)) return [start, lastIndex];

if (start > end) return [end, start];

return [start, end];
};

/**
Expand Down

0 comments on commit a3823b9

Please sign in to comment.