|
| 1 | +diff --git a/node_modules/@shopify/flash-list/dist/FlashListProps.d.ts b/node_modules/@shopify/flash-list/dist/FlashListProps.d.ts |
| 2 | +index fa786bf..586014c 100644 |
| 3 | +--- a/node_modules/@shopify/flash-list/dist/FlashListProps.d.ts |
| 4 | ++++ b/node_modules/@shopify/flash-list/dist/FlashListProps.d.ts |
| 5 | +@@ -127,10 +127,12 @@ export interface FlashListProps<TItem> extends Omit<ScrollViewProps, "maintainVi |
| 6 | + /** |
| 7 | + * Additional configuration for initialScrollIndex. |
| 8 | + * Use viewOffset to apply an offset to the initial scroll position as defined by initialScrollIndex. |
| 9 | ++ * Use viewPosition to position the item within the viewport (0 = start, 0.5 = center, 1 = end), mirroring scrollToIndex. |
| 10 | + * Ignored if initialScrollIndex is not set. |
| 11 | + */ |
| 12 | + initialScrollIndexParams?: { |
| 13 | + viewOffset?: number; |
| 14 | ++ viewPosition?: number; |
| 15 | + } | null | undefined; |
| 16 | + /** |
| 17 | + * Used to extract a unique key for a given item at the specified index. |
| 18 | +diff --git a/node_modules/@shopify/flash-list/dist/recyclerview/RecyclerViewManager.js b/node_modules/@shopify/flash-list/dist/recyclerview/RecyclerViewManager.js |
| 19 | +index 3b69234..41bfb84 100644 |
| 20 | +--- a/node_modules/@shopify/flash-list/dist/recyclerview/RecyclerViewManager.js |
| 21 | ++++ b/node_modules/@shopify/flash-list/dist/recyclerview/RecyclerViewManager.js |
| 22 | +@@ -294,11 +294,26 @@ export class RecyclerViewManager { |
| 23 | + // re-estimate unmeasured items with an updated average height, changing |
| 24 | + // the target item's position. Reading before recompute would capture a |
| 25 | + // stale offset, causing the wrong items to be rendered. |
| 26 | +- this.layoutManager.recomputeLayouts(0, initialScrollIndex); |
| 27 | ++ this.layoutManager.recomputeLayouts(0, this.getDataLength() - 1); |
| 28 | + const initialItemLayout = this.layoutManager.getLayout(initialScrollIndex); |
| 29 | +- const initialItemOffset = this.propsRef.horizontal |
| 30 | ++ let initialItemOffset = this.propsRef.horizontal |
| 31 | + ? initialItemLayout.x |
| 32 | + : initialItemLayout.y; |
| 33 | ++ // Anchor the initial render window according to initialScrollIndexParams.viewPosition so the |
| 34 | ++ // first painted frame already shows the target item at the requested position in the viewport. |
| 35 | ++ const initialScrollIndexParams = this.propsRef.initialScrollIndexParams; |
| 36 | ++ const viewPosition = initialScrollIndexParams === null || initialScrollIndexParams === void 0 ? void 0 : initialScrollIndexParams.viewPosition; |
| 37 | ++ if (viewPosition !== undefined) { |
| 38 | ++ const windowSize = this.propsRef.horizontal |
| 39 | ++ ? this.getWindowSize().width |
| 40 | ++ : this.getWindowSize().height; |
| 41 | ++ const itemSize = this.propsRef.horizontal |
| 42 | ++ ? initialItemLayout.width |
| 43 | ++ : initialItemLayout.height; |
| 44 | ++ if (windowSize > 0) { |
| 45 | ++ initialItemOffset = Math.max(0, initialItemOffset - (windowSize - itemSize) * viewPosition); |
| 46 | ++ } |
| 47 | ++ } |
| 48 | + this.engagedIndicesTracker.scrollOffset = initialItemOffset; |
| 49 | + } |
| 50 | + else { |
| 51 | +diff --git a/node_modules/@shopify/flash-list/dist/recyclerview/hooks/useRecyclerViewController.js b/node_modules/@shopify/flash-list/dist/recyclerview/hooks/useRecyclerViewController.js |
| 52 | +index 18e59ce..17c8063 100644 |
| 53 | +--- a/node_modules/@shopify/flash-list/dist/recyclerview/hooks/useRecyclerViewController.js |
| 54 | ++++ b/node_modules/@shopify/flash-list/dist/recyclerview/hooks/useRecyclerViewController.js |
| 55 | +@@ -566,10 +566,45 @@ export function useRecyclerViewController(recyclerViewManager, ref, scrollViewRe |
| 56 | + }, 500); |
| 57 | + pauseOffsetCorrection.current = true; |
| 58 | + const additionalOffset = (_c = initialScrollIndexParams === null || initialScrollIndexParams === void 0 ? void 0 : initialScrollIndexParams.viewOffset) !== null && _c !== void 0 ? _c : 0; |
| 59 | +- const offset = horizontal |
| 60 | +- ? recyclerViewManager.getLayout(initialScrollIndex).x + additionalOffset |
| 61 | +- : recyclerViewManager.getLayout(initialScrollIndex).y + |
| 62 | +- additionalOffset; |
| 63 | ++ const initialItemLayout = recyclerViewManager.getLayout(initialScrollIndex); |
| 64 | ++ let offset = (horizontal ? initialItemLayout.x : initialItemLayout.y) + |
| 65 | ++ additionalOffset; |
| 66 | ++ // Position the target item within the viewport (0 = start, 0.5 = center, 1 = end), mirroring scrollToIndex. |
| 67 | ++ const viewPosition = initialScrollIndexParams === null || initialScrollIndexParams === void 0 ? void 0 : initialScrollIndexParams.viewPosition; |
| 68 | ++ if (viewPosition !== undefined) { |
| 69 | ++ const containerSize = horizontal |
| 70 | ++ ? recyclerViewManager.getWindowSize().width |
| 71 | ++ : recyclerViewManager.getWindowSize().height; |
| 72 | ++ const itemSize = horizontal |
| 73 | ++ ? initialItemLayout.width |
| 74 | ++ : initialItemLayout.height; |
| 75 | ++ if (containerSize > 0) { |
| 76 | ++ offset = Math.max(0, offset - (containerSize - itemSize) * viewPosition); |
| 77 | ++ } |
| 78 | ++ } |
| 79 | ++ // Make it clear there are more items to scroll to underneath the bottom edge. |
| 80 | ++ // If the bottom item is (essentially) fully visible against the bottom edge AND there |
| 81 | ++ // is an item underneath it, nudge the bottom edge up so CROP_OFFSET px of the current |
| 82 | ++ // bottom item gets cropped, signalling that more content can be scrolled into view. |
| 83 | ++ if (viewPosition !== undefined && !horizontal && recyclerViewManager.props.inverted && offset > 0) { |
| 84 | ++ const CROP_OFFSET = 10; |
| 85 | ++ let bottomIndex = -1; |
| 86 | ++ for (let i = initialScrollIndex; i >= 0; i--) { |
| 87 | ++ if (recyclerViewManager.getLayout(i).y <= offset) { |
| 88 | ++ bottomIndex = i; |
| 89 | ++ break; |
| 90 | ++ } |
| 91 | ++ } |
| 92 | ++ if (bottomIndex > 0) { |
| 93 | ++ const bottomItemLayout = recyclerViewManager.getLayout(bottomIndex); |
| 94 | ++ const hiddenPortion = offset - bottomItemLayout.y; |
| 95 | ++ // 8px is bottom padding of every item |
| 96 | ++ if (hiddenPortion <= 8) { |
| 97 | ++ // Crop the current bottom item rather than letting it sit flush against the edge. |
| 98 | ++ offset = bottomItemLayout.y + CROP_OFFSET; |
| 99 | ++ } |
| 100 | ++ } |
| 101 | ++ } |
| 102 | + handlerMethods.scrollToOffset({ |
| 103 | + offset, |
| 104 | + animated: false, |
0 commit comments