Appearance
useGalleryPreviewNavigation Composable ​
File Information ​
- Path:
app/composables/core/components/dialogs/useGalleryPreviewNavigation.ts - Purpose: Current index, previous/next rules, position counter, prefetch and arrow keys for the gallery
- Type: Core Composable
- Added: PR #137 (RIV-1266), 2026-10-28
Overview ​
useGalleryPreviewNavigation(options: GalleryNavigationOptions) works on the merged list from useGalleryPreviewPager. When the next asset is not loaded yet it records a pending move ('forward', 'backward' or 'last'), asks the pager to load, and completes the move once the items arrive. The current asset is followed by id, so the index stays on the same asset when pages are inserted before it.
Features ​
Position ​
| Value | Rule |
|---|---|
inTail | there is a gap and currentIndex >= headLength |
position | in the tail: total - (count - 1 - currentIndex); else currentIndex + 1 |
indexForPosition(p) | -1 outside 1..total; head positions map directly; tail positions map from total - tailLength + 1; positions in the gap return -1 |
total | max(paging.total(), count) |
Moves ​
| Function | Rule (in order) |
|---|---|
goNext() | ignore if empty or a move is pending -> last head item with a gap: load forward -> not last item: index + 1 -> no tail and can load forward: load forward -> loop: index 0 |
goPrev() | ignore if empty or pending -> first tail item: load backward -> index > 0: index - 1 -> no loop: stay -> tail loaded or nothing to load: last index -> else load last |
goTo(i) | clamps to 0..count-1, clears a pending move |
hasPrev | index > 0, or loop with more than one item or more data |
hasNext | not the last item, or (no tail and can load forward), or loop with more than one item or more data |
When loading stops and the pending move still cannot complete, it is retried only if loading is allowed and the user is still at the edge for that move; otherwise the move is dropped.
Prefetch ​
DEFAULT_PREFETCH_RATIO = 0.6 (or paging.ratio()). Skipped while closed, loading, a move is pending, or canPrefetch() is false. In the head it calls loadForward() once currentIndex + 1 >= ceil(headLength * ratio); in the tail it calls loadBackward() once the distance from the tail end reaches ceil(tailLength * ratio).
Keyboard ​
ArrowLeft / ArrowRight on window while open; preventDefault(); ignored when the event target is INPUT, TEXTAREA, SELECT, VIDEO, AUDIO or contentEditable.
Open / close ​
Opening resets to the index of startAssetId (0 if not found); closing drops any pending move.
Return Type ​
items, currentIndex (readonly), current, total, position, hasPrev, hasNext, hasGap, hasTail, headLength, loopEnabled, indexForPosition, pendingMove (readonly), goTo, goPrev, goNext.
Parameters ​
GalleryNavigationOptions: assets, startAssetId, open, keyboardEnabled?, loop?, paging? (GalleryPaging). Without paging it navigates the given list only.
Usage Example ​
typescript
const { current, position, total, goNext, goPrev } =
useGalleryPreviewNavigation({
assets: () => pager.items.value,
startAssetId: () => props.startAssetId,
open: () => modalDialog.value,
loop: () => props.loop !== false,
});