@shopify/flash-list 1.6.4 → 1.7.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (73) hide show
  1. package/RNFlashList.podspec +13 -2
  2. package/android/build.gradle +18 -0
  3. package/android/src/main/kotlin/com/shopify/reactnative/flash_list/AutoLayoutShadow.kt +1 -1
  4. package/android/src/main/kotlin/com/shopify/reactnative/flash_list/AutoLayoutView.kt +16 -8
  5. package/android/src/main/kotlin/com/shopify/reactnative/flash_list/AutoLayoutViewManager.kt +19 -18
  6. package/android/src/main/kotlin/com/shopify/reactnative/flash_list/BlankAreaEvent.kt +29 -0
  7. package/android/src/main/kotlin/com/shopify/reactnative/flash_list/CellContainerManager.kt +12 -5
  8. package/android/src/paper/java/com/facebook/react/viewmanagers/AutoLayoutViewManagerDelegate.java +46 -0
  9. package/android/src/paper/java/com/facebook/react/viewmanagers/AutoLayoutViewManagerInterface.java +21 -0
  10. package/android/src/paper/java/com/facebook/react/viewmanagers/CellContainerManagerDelegate.java +31 -0
  11. package/android/src/paper/java/com/facebook/react/viewmanagers/CellContainerManagerInterface.java +16 -0
  12. package/android/src/test/java/com/shopify/reactnative/flash_list/AutoLayoutShadowTest.kt +3 -3
  13. package/dist/FlashList.d.ts +5 -1
  14. package/dist/FlashList.d.ts.map +1 -1
  15. package/dist/FlashList.js +6 -0
  16. package/dist/FlashList.js.map +1 -1
  17. package/dist/MasonryFlashList.d.ts.map +1 -1
  18. package/dist/MasonryFlashList.js +6 -4
  19. package/dist/MasonryFlashList.js.map +1 -1
  20. package/dist/__tests__/FlashList.test.js +110 -0
  21. package/dist/__tests__/FlashList.test.js.map +1 -1
  22. package/dist/__tests__/helpers/mountFlashList.d.ts +1 -1
  23. package/dist/__tests__/helpers/mountFlashList.d.ts.map +1 -1
  24. package/dist/__tests__/helpers/mountFlashList.js +1 -1
  25. package/dist/__tests__/helpers/mountFlashList.js.map +1 -1
  26. package/dist/__tests__/helpers/mountMasonryFlashList.d.ts +1 -1
  27. package/dist/__tests__/helpers/mountMasonryFlashList.d.ts.map +1 -1
  28. package/dist/__tests__/helpers/mountMasonryFlashList.js +1 -1
  29. package/dist/__tests__/helpers/mountMasonryFlashList.js.map +1 -1
  30. package/dist/__tests__/useBlankAreaTracker.test.js +1 -1
  31. package/dist/__tests__/useBlankAreaTracker.test.js.map +1 -1
  32. package/dist/native/auto-layout/AutoLayoutView.d.ts +1 -1
  33. package/dist/native/cell-container/CellContainer.web.d.ts +1 -1
  34. package/dist/native/cell-container/CellContainer.web.d.ts.map +1 -1
  35. package/dist/specs/AutoLayoutNativeComponent.d.ts +19 -0
  36. package/dist/specs/AutoLayoutNativeComponent.d.ts.map +1 -0
  37. package/dist/specs/AutoLayoutNativeComponent.js +6 -0
  38. package/dist/specs/AutoLayoutNativeComponent.js.map +1 -0
  39. package/dist/specs/CellContainerNativeComponent.d.ts +9 -0
  40. package/dist/specs/CellContainerNativeComponent.d.ts.map +1 -0
  41. package/dist/specs/CellContainerNativeComponent.js +6 -0
  42. package/dist/specs/CellContainerNativeComponent.js.map +1 -0
  43. package/dist/tsconfig.tsbuildinfo +1 -1
  44. package/dist/viewability/ViewabilityHelper.d.ts +1 -0
  45. package/dist/viewability/ViewabilityHelper.d.ts.map +1 -1
  46. package/dist/viewability/ViewabilityHelper.js +3 -0
  47. package/dist/viewability/ViewabilityHelper.js.map +1 -1
  48. package/dist/viewability/ViewabilityManager.d.ts +1 -0
  49. package/dist/viewability/ViewabilityManager.d.ts.map +1 -1
  50. package/dist/viewability/ViewabilityManager.js +6 -0
  51. package/dist/viewability/ViewabilityManager.js.map +1 -1
  52. package/ios/Sources/AutoLayoutView.swift +47 -29
  53. package/ios/Sources/AutoLayoutViewComponentView.h +16 -0
  54. package/ios/Sources/AutoLayoutViewComponentView.mm +90 -0
  55. package/ios/Sources/CellContainerComponentView.h +18 -0
  56. package/ios/Sources/CellContainerComponentView.mm +62 -0
  57. package/ios/Sources/CellContainerManager.swift +1 -1
  58. package/ios/Sources/FlatListPro-Bridging-Header.h +3 -0
  59. package/package.json +26 -21
  60. package/src/FlashList.tsx +7 -0
  61. package/src/MasonryFlashList.tsx +5 -2
  62. package/src/__tests__/FlashList.test.tsx +115 -0
  63. package/src/__tests__/helpers/mountFlashList.tsx +2 -2
  64. package/src/__tests__/helpers/mountMasonryFlashList.tsx +2 -2
  65. package/src/__tests__/useBlankAreaTracker.test.tsx +2 -2
  66. package/src/specs/AutoLayoutNativeComponent.ts +24 -0
  67. package/src/specs/CellContainerNativeComponent.ts +9 -0
  68. package/src/viewability/ViewabilityHelper.ts +4 -0
  69. package/src/viewability/ViewabilityManager.ts +8 -0
  70. package/CHANGELOG.md +0 -284
  71. package/ios/Sources/CellContainer.swift +0 -9
  72. /package/ios/Sources/{AutoLayoutViewManager.m → AutoLayoutViewManager.mm} +0 -0
  73. /package/ios/Sources/{CellContainerManager.m → CellContainerManager.mm} +0 -0
@@ -0,0 +1,90 @@
1
+ #ifdef RCT_NEW_ARCH_ENABLED
2
+ #import "AutoLayoutViewComponentView.h"
3
+ #import <React/RCTConversions.h>
4
+ #import <React/RCTViewManager.h>
5
+
6
+ #import <react/renderer/components/rnflashlist/ComponentDescriptors.h>
7
+ #import <react/renderer/components/rnflashlist/EventEmitters.h>
8
+ #import <react/renderer/components/rnflashlist/Props.h>
9
+ #import <react/renderer/components/rnflashlist/RCTComponentViewHelpers.h>
10
+
11
+ #import "RCTFabricComponentsPlugins.h"
12
+
13
+ #if __has_include(<RNFlashList/RNFlashList-Swift.h>)
14
+ #import <RNFlashList/RNFlashList-Swift.h>
15
+ #else
16
+ #import "RNFlashList-Swift.h"
17
+ #endif
18
+
19
+ using namespace facebook::react;
20
+
21
+ @interface AutoLayoutViewComponentView () <RCTAutoLayoutViewViewProtocol>
22
+ @end
23
+
24
+ @implementation AutoLayoutViewComponentView
25
+ {
26
+ AutoLayoutView *_autoLayoutView;
27
+ }
28
+
29
+ - (instancetype)initWithFrame:(CGRect)frame
30
+ {
31
+ if (self = [super initWithFrame:frame]) {
32
+ static const auto defaultProps = std::make_shared<const AutoLayoutViewProps>();
33
+ _props = defaultProps;
34
+ _autoLayoutView = [[AutoLayoutView alloc] initWithFrame:self.bounds];
35
+ self.contentView = _autoLayoutView;
36
+
37
+ __weak AutoLayoutViewComponentView* weakSelf = self;
38
+ _autoLayoutView.onBlankAreaEventHandler = ^(CGFloat start, CGFloat end) {
39
+ AutoLayoutViewComponentView *strongSelf = weakSelf;
40
+ if (strongSelf != nullptr && strongSelf->_eventEmitter != nullptr) {
41
+ std::dynamic_pointer_cast<const facebook::react::AutoLayoutViewEventEmitter>(strongSelf->_eventEmitter)
42
+ ->onBlankAreaEvent(facebook::react::AutoLayoutViewEventEmitter::OnBlankAreaEvent{
43
+ .offsetStart = (int) floor(start),
44
+ .offsetEnd = (int) floor(end),
45
+ });
46
+ }
47
+ };
48
+ }
49
+
50
+ return self;
51
+ }
52
+
53
+ - (void)mountChildComponentView:(UIView<RCTComponentViewProtocol> *)childComponentView index:(NSInteger)index
54
+ {
55
+ [_autoLayoutView mountChildComponentView:childComponentView index:index];
56
+ }
57
+
58
+ - (void)unmountChildComponentView:(UIView<RCTComponentViewProtocol> *)childComponentView index:(NSInteger)index
59
+ {
60
+ [_autoLayoutView unmountChildComponentView:childComponentView index:index];
61
+ }
62
+
63
+ #pragma mark - RCTComponentViewProtocol
64
+
65
+ + (ComponentDescriptorProvider)componentDescriptorProvider
66
+ {
67
+ return concreteComponentDescriptorProvider<AutoLayoutViewComponentDescriptor>();
68
+ }
69
+
70
+ - (void)updateProps:(const Props::Shared &)props oldProps:(const Props::Shared &)oldProps
71
+ {
72
+ const auto &newProps = *std::static_pointer_cast<const AutoLayoutViewProps>(props);
73
+
74
+ [_autoLayoutView setHorizontal:newProps.horizontal];
75
+ [_autoLayoutView setScrollOffset:newProps.scrollOffset];
76
+ [_autoLayoutView setWindowSize:newProps.windowSize];
77
+ [_autoLayoutView setRenderAheadOffset:newProps.renderAheadOffset];
78
+ [_autoLayoutView setEnableInstrumentation:newProps.enableInstrumentation];
79
+ [_autoLayoutView setDisableAutoLayout:newProps.disableAutoLayout];
80
+
81
+ [super updateProps:props oldProps:oldProps];
82
+ }
83
+ @end
84
+
85
+ Class<RCTComponentViewProtocol> AutoLayoutViewCls(void)
86
+ {
87
+ return AutoLayoutViewComponentView.class;
88
+ }
89
+
90
+ #endif /* RCT_NEW_ARCH_ENABLED */
@@ -0,0 +1,18 @@
1
+ #ifndef CellContainer_h
2
+ #define CellContainer_h
3
+
4
+ #import <UIKit/UIKit.h>
5
+
6
+ #ifdef RCT_NEW_ARCH_ENABLED
7
+ #import <React/RCTViewComponentView.h>
8
+
9
+ @interface CellContainerComponentView : RCTViewComponentView
10
+ #else
11
+ @interface CellContainerComponentView : UIView
12
+ #endif // RCT_NEW_ARCH_ENABLED
13
+
14
+ @property int64_t index;
15
+
16
+ @end
17
+
18
+ #endif /* CellContainer_h */
@@ -0,0 +1,62 @@
1
+ #import "CellContainerComponentView.h"
2
+
3
+ #ifdef RCT_NEW_ARCH_ENABLED
4
+ #import <React/RCTConversions.h>
5
+
6
+ #import <react/renderer/components/rnflashlist/ComponentDescriptors.h>
7
+ #import <react/renderer/components/rnflashlist/EventEmitters.h>
8
+ #import <react/renderer/components/rnflashlist/Props.h>
9
+ #import <react/renderer/components/rnflashlist/RCTComponentViewHelpers.h>
10
+
11
+ #import "RCTFabricComponentsPlugins.h"
12
+
13
+ #if __has_include(<RNFlashList/RNFlashList-Swift.h>)
14
+ #import <RNFlashList/RNFlashList-Swift.h>
15
+ #else
16
+ #import "RNFlashList-Swift.h"
17
+ #endif
18
+
19
+ using namespace facebook::react;
20
+
21
+ @interface CellContainerComponentView () <RCTCellContainerViewProtocol>
22
+ @end
23
+
24
+ @implementation CellContainerComponentView
25
+
26
+ - (instancetype)initWithFrame:(CGRect)frame
27
+ {
28
+ if (self = [super initWithFrame:frame]) {
29
+ static const auto defaultProps = std::make_shared<const CellContainerProps>();
30
+ _props = defaultProps;
31
+
32
+ self.userInteractionEnabled = true;
33
+ }
34
+
35
+ return self;
36
+ }
37
+
38
+ #pragma mark - RCTComponentViewProtocol
39
+
40
+ + (ComponentDescriptorProvider)componentDescriptorProvider
41
+ {
42
+ return concreteComponentDescriptorProvider<CellContainerComponentDescriptor>();
43
+ }
44
+
45
+ - (void)updateProps:(const Props::Shared &)props oldProps:(const Props::Shared &)oldProps
46
+ {
47
+ const auto &newProps = *std::static_pointer_cast<const CellContainerProps>(props);
48
+
49
+ self.index = newProps.index;
50
+
51
+ [super updateProps:props oldProps:oldProps];
52
+ }
53
+ @end
54
+
55
+ Class<RCTComponentViewProtocol> CellContainerCls(void)
56
+ {
57
+ return CellContainerComponentView.class;
58
+ }
59
+ #else
60
+ @implementation CellContainerComponentView
61
+ @end
62
+ #endif /* RCT_NEW_ARCH_ENABLED */
@@ -3,7 +3,7 @@ import Foundation
3
3
  @objc(CellContainerManager)
4
4
  class CellContainerManager: RCTViewManager {
5
5
  override func view() -> UIView! {
6
- return CellContainer()
6
+ return CellContainerComponentView()
7
7
  }
8
8
 
9
9
  override static func requiresMainQueueSetup() -> Bool {
@@ -4,5 +4,8 @@
4
4
  #import <React/RCTBridgeModule.h>
5
5
  #import <React/RCTEventEmitter.h>
6
6
  #import <React/RCTViewManager.h>
7
+ #import <React/RCTComponent.h>
8
+
9
+ #import "CellContainerComponentView.h"
7
10
 
8
11
  #endif /* FlatListPro_Bridging_Header_h */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@shopify/flash-list",
3
- "version": "1.6.4",
3
+ "version": "1.7.1",
4
4
  "keywords": [
5
5
  "react-native",
6
6
  "recyclerview",
@@ -28,27 +28,26 @@
28
28
  "main": "dist/index.js",
29
29
  "types": "dist/index.d.ts",
30
30
  "scripts": {
31
- "up": "bundle install && yarn fixture-up && yarn e2e-up && yarn build",
32
- "fixture-web-up": "cd fixture/web-app && yarn && cd ../../",
33
- "fixture-up": "cd fixture && yarn && cd ios && bundle exec pod install && cd ../../",
34
- "e2e-up": "cd fixture/ios && brew tap wix/brew && brew install applesimutils && cd ../../",
35
- "start": "cd fixture && react-native start",
31
+ "up": "bundle install && yarn fixture:rn:up && yarn e2e:up && yarn build",
32
+ "start": "cd fixture/react-native && react-native start",
36
33
  "test": "jest",
37
34
  "lint": "yarn eslint . --ext .ts,.tsx",
38
35
  "lint:fix": "yarn eslint . --ext .ts,.tsx --fix",
39
36
  "type-check": "yarn tsc --pretty --noEmit",
40
37
  "build": "tsc -b",
41
- "e2e:build:android": "detox build -c android.emu.release",
42
- "run-ios": "cd fixture && yarn react-native run-ios && yarn build --watch",
43
- "ri": "yarn run-ios",
44
- "run-android": "cd fixture && yarn react-native run-android && yarn build --watch",
45
- "ra": "yarn run-android",
46
- "run-e2e-ios": "cd fixture && yarn e2e:build:ios && yarn e2e:test:ios",
38
+ "fixture:rn:up": "cd fixture/react-native && yarn && cd ios && bundle exec pod install && cd ../../../",
39
+ "fixture:expo:up": "cd fixture/expo && yarn && cd ../../",
40
+ "fixture:rn:android": "cd fixture/react-native && yarn react-native run-android && yarn build --watch",
41
+ "fixture:rn:ios": "cd fixture/react-native && yarn react-native run-ios && yarn build --watch",
42
+ "ra": "yarn fixture:rn:android",
43
+ "ri": "yarn fixture:rn:ios",
44
+ "fixture:expo:start": "cd fixture/expo && yarn start",
45
+ "rw": "yarn fixture:expo:start",
46
+ "e2e:up": "cd fixture/react-native/ios && brew tap wix/brew && brew install applesimutils && cd ../../../",
47
+ "e2e:ios": "cd fixture/react-native && yarn e2e:build:ios && yarn e2e:test:ios",
47
48
  "rei": "yarn run-e2e-ios",
48
- "run-e2e-android": "cd fixture && yarn e2e:build:android && yarn e2e:test:android",
49
+ "e2e:android": "cd fixture/react-native && yarn e2e:build:android && yarn e2e:test:android",
49
50
  "rea": "yarn run-e2e-android",
50
- "run-web": "cd fixture/web-app && yarn web",
51
- "rw": "yarn run-web",
52
51
  "predeploy:website": "sh ./build_website.sh",
53
52
  "deploy:website": "gh-pages -d website/_site"
54
53
  },
@@ -60,11 +59,11 @@
60
59
  "devDependencies": {
61
60
  "@babel/core": "^7.18.5",
62
61
  "@babel/runtime": "^7.18.3",
63
- "@quilted/react-testing": "^0.5.14",
62
+ "@quilted/react-testing": "0.5.27",
64
63
  "@react-native-community/eslint-config": "^3.0.3",
65
64
  "@shopify/eslint-plugin": "^41.3.1",
66
65
  "@types/jest": "^29.5.10",
67
- "@types/react-native": "0.72.2",
66
+ "@types/react": "^18.0.24",
68
67
  "babel-jest": "^28.1.1",
69
68
  "enhanced-resolve": "^5.9.3",
70
69
  "eslint": "8.18.0",
@@ -72,8 +71,9 @@
72
71
  "jest": "^29.7.0",
73
72
  "metro-react-native-babel-preset": "^0.71.1",
74
73
  "prettier": "^2.7.1",
75
- "react": "17.0.2",
76
- "react-native": "0.68.5",
74
+ "react": "18.2.0",
75
+ "react-native": "0.74.3",
76
+ "react-test-renderer": "18.2.0",
77
77
  "typescript": "^4.7.4"
78
78
  },
79
79
  "files": [
@@ -85,7 +85,12 @@
85
85
  "jestSetup.js"
86
86
  ],
87
87
  "dependencies": {
88
- "recyclerlistview": "4.2.0",
89
- "tslib": "2.4.0"
88
+ "recyclerlistview": "4.2.1",
89
+ "tslib": "2.6.3"
90
+ },
91
+ "codegenConfig": {
92
+ "name": "rnflashlist",
93
+ "type": "components",
94
+ "jsSrcsDir": "./src/specs"
90
95
  }
91
96
  }
package/src/FlashList.tsx CHANGED
@@ -870,6 +870,13 @@ class FlashList<T> extends React.PureComponent<
870
870
  public recordInteraction = () => {
871
871
  this.viewabilityManager.recordInteraction();
872
872
  };
873
+
874
+ /**
875
+ * Retriggers viewability calculations. Useful to imperatively trigger viewability calculations.
876
+ */
877
+ public recomputeViewableItems = () => {
878
+ this.viewabilityManager.recomputeViewableItems();
879
+ };
873
880
  }
874
881
 
875
882
  export default FlashList;
@@ -114,6 +114,9 @@ const MasonryFlashListComponent = React.forwardRef(
114
114
 
115
115
  const totalColumnFlex = useTotalColumnFlex(dataSet, props);
116
116
 
117
+ const propsRef = useRef(props);
118
+ propsRef.current = props;
119
+
117
120
  const onScrollRef = useRef<OnScrollCallback[]>([]);
118
121
  const emptyScrollEvent = useRef(getEmptyScrollEvent())
119
122
  .current as NativeSyntheticEvent<MasonryFlashListScrollEvent>;
@@ -135,7 +138,7 @@ const MasonryFlashListComponent = React.forwardRef(
135
138
  onScrollCallback?.(emptyScrollEvent);
136
139
  });
137
140
  if (!scrollEvent.nativeEvent.doNotPropagate) {
138
- props.onScroll?.(scrollEvent);
141
+ propsRef.current.onScroll?.(scrollEvent);
139
142
  }
140
143
  }
141
144
  ).current;
@@ -151,7 +154,7 @@ const MasonryFlashListComponent = React.forwardRef(
151
154
  onScrollProxy?.(emptyScrollEvent);
152
155
  emptyScrollEvent.nativeEvent.doNotPropagate = false;
153
156
  }, 32);
154
- props.onLoad?.(args);
157
+ propsRef.current.onLoad?.(args);
155
158
  }).current;
156
159
 
157
160
  const [parentFlashList, getFlashList] =
@@ -551,6 +551,121 @@ describe("FlashList", () => {
551
551
  });
552
552
  });
553
553
 
554
+ it("retrigers viewability events when recomputeViewableItems is called", () => {
555
+ const onViewableItemsChanged = jest.fn();
556
+ const flashList = mountFlashList({
557
+ estimatedItemSize: 300,
558
+ onViewableItemsChanged,
559
+ viewabilityConfig: {
560
+ itemVisiblePercentThreshold: 50,
561
+ minimumViewTime: 0,
562
+ },
563
+ });
564
+
565
+ // Initial viewable items
566
+ expect(onViewableItemsChanged).toHaveBeenCalledWith({
567
+ changed: [
568
+ {
569
+ index: 0,
570
+ isViewable: true,
571
+ item: "One",
572
+ key: "0",
573
+ timestamp: expect.any(Number),
574
+ },
575
+ {
576
+ index: 1,
577
+ isViewable: true,
578
+ item: "Two",
579
+ key: "1",
580
+ timestamp: expect.any(Number),
581
+ },
582
+ {
583
+ index: 2,
584
+ isViewable: true,
585
+ item: "Three",
586
+ key: "2",
587
+ timestamp: expect.any(Number),
588
+ },
589
+ ],
590
+ viewableItems: [
591
+ {
592
+ index: 0,
593
+ isViewable: true,
594
+ item: "One",
595
+ key: "0",
596
+ timestamp: expect.any(Number),
597
+ },
598
+ {
599
+ index: 1,
600
+ isViewable: true,
601
+ item: "Two",
602
+ key: "1",
603
+ timestamp: expect.any(Number),
604
+ },
605
+ {
606
+ index: 2,
607
+ isViewable: true,
608
+ item: "Three",
609
+ key: "2",
610
+ timestamp: expect.any(Number),
611
+ },
612
+ ],
613
+ });
614
+
615
+ onViewableItemsChanged.mockClear();
616
+
617
+ flashList.instance.recomputeViewableItems();
618
+
619
+ expect(onViewableItemsChanged).toHaveBeenCalledWith({
620
+ changed: [
621
+ {
622
+ index: 0,
623
+ isViewable: true,
624
+ item: "One",
625
+ key: "0",
626
+ timestamp: expect.any(Number),
627
+ },
628
+ {
629
+ index: 1,
630
+ isViewable: true,
631
+ item: "Two",
632
+ key: "1",
633
+ timestamp: expect.any(Number),
634
+ },
635
+ {
636
+ index: 2,
637
+ isViewable: true,
638
+ item: "Three",
639
+ key: "2",
640
+ timestamp: expect.any(Number),
641
+ },
642
+ ],
643
+ viewableItems: [
644
+ {
645
+ index: 0,
646
+ isViewable: true,
647
+ item: "One",
648
+ key: "0",
649
+ timestamp: expect.any(Number),
650
+ },
651
+ {
652
+ index: 1,
653
+ isViewable: true,
654
+ item: "Two",
655
+ key: "1",
656
+ timestamp: expect.any(Number),
657
+ },
658
+ {
659
+ index: 2,
660
+ isViewable: true,
661
+ item: "Three",
662
+ key: "2",
663
+ timestamp: expect.any(Number),
664
+ },
665
+ ],
666
+ });
667
+ });
668
+
554
669
  it("should not overlap header with sitcky index 0", () => {
555
670
  const HeaderComponent = () => {
556
671
  return <Text>Empty</Text>;
@@ -1,7 +1,7 @@
1
1
  import React from "react";
2
2
  import { Text } from "react-native";
3
3
  import "@quilted/react-testing/matchers";
4
- import { mount, Root } from "@quilted/react-testing";
4
+ import { render, Root } from "@quilted/react-testing";
5
5
 
6
6
  import FlashList from "../../FlashList";
7
7
  import { FlashListProps, ListRenderItem } from "../../FlashListProps";
@@ -34,7 +34,7 @@ export const mountFlashList = (
34
34
  props?: MockFlashListProps,
35
35
  ref?: React.RefObject<FlashList<string>>
36
36
  ) => {
37
- const flashList = mount(renderFlashList(props, ref)) as Omit<
37
+ const flashList = render(renderFlashList(props, ref)) as Omit<
38
38
  Root<FlashListProps<string>>,
39
39
  "instance"
40
40
  > & {
@@ -1,7 +1,7 @@
1
1
  import React from "react";
2
2
  import { Text } from "react-native";
3
3
  import "@quilted/react-testing/matchers";
4
- import { mount, Root } from "@quilted/react-testing";
4
+ import { render, Root } from "@quilted/react-testing";
5
5
 
6
6
  import { ListRenderItem } from "../../FlashListProps";
7
7
  import {
@@ -44,7 +44,7 @@ export const mountMasonryFlashList = (
44
44
  props?: MockMasonryFlashListProps,
45
45
  ref?: React.RefObject<MasonryFlashListRef<string>>
46
46
  ) => {
47
- const flashList = mount(renderMasonryFlashList(props, ref)) as Omit<
47
+ const flashList = render(renderMasonryFlashList(props, ref)) as Omit<
48
48
  Root<MasonryFlashListProps<string>>,
49
49
  "instance"
50
50
  > & {
@@ -1,5 +1,5 @@
1
1
  import React, { useEffect } from "react";
2
- import { mount } from "@quilted/react-testing";
2
+ import { render } from "@quilted/react-testing";
3
3
 
4
4
  import {
5
5
  BlankAreaTrackerConfig,
@@ -44,7 +44,7 @@ const mountBlankTrackingFlashList = (props?: BlankTrackingFlashListProps) => {
44
44
  const flashListRef: React.RefObject<FlashList<any>> = {
45
45
  current: null,
46
46
  };
47
- const blankTrackingFlashList = mount(
47
+ const blankTrackingFlashList = render(
48
48
  <BlankTrackingFlashList {...props} instance={flashListRef} />
49
49
  );
50
50
  return {
@@ -0,0 +1,24 @@
1
+ import codegenNativeComponent from "react-native/Libraries/Utilities/codegenNativeComponent";
2
+ import type { ViewProps } from "react-native";
3
+ import type {
4
+ Int32,
5
+ Double,
6
+ DirectEventHandler,
7
+ } from "react-native/Libraries/Types/CodegenTypes";
8
+
9
+ type BlankAreaEvent = Readonly<{
10
+ offsetStart: Int32;
11
+ offsetEnd: Int32;
12
+ }>;
13
+
14
+ interface NativeProps extends ViewProps {
15
+ horizontal?: boolean;
16
+ scrollOffset?: Double;
17
+ windowSize?: Double;
18
+ renderAheadOffset?: Double;
19
+ enableInstrumentation?: boolean;
20
+ disableAutoLayout?: boolean;
21
+ onBlankAreaEvent?: DirectEventHandler<BlankAreaEvent>;
22
+ }
23
+
24
+ export default codegenNativeComponent<NativeProps>("AutoLayoutView");
@@ -0,0 +1,9 @@
1
+ import codegenNativeComponent from "react-native/Libraries/Utilities/codegenNativeComponent";
2
+ import type { Int32 } from "react-native/Libraries/Types/CodegenTypes";
3
+ import type { ViewProps } from "react-native";
4
+
5
+ interface NativeProps extends ViewProps {
6
+ index?: Int32;
7
+ }
8
+
9
+ export default codegenNativeComponent<NativeProps>("CellContainer");
@@ -118,6 +118,10 @@ class ViewabilityHelper {
118
118
  }
119
119
  }
120
120
 
121
+ public clearLastReportedViewableIndices() {
122
+ this.lastReportedViewableIndices = [];
123
+ }
124
+
121
125
  private isItemViewable(
122
126
  index: number,
123
127
  horizontal: boolean,
@@ -88,6 +88,14 @@ export default class ViewabilityManager<T> {
88
88
  });
89
89
  };
90
90
 
91
+ public recomputeViewableItems = () => {
92
+ this.viewabilityHelpers.forEach((viewabilityHelper) =>
93
+ viewabilityHelper.clearLastReportedViewableIndices()
94
+ );
95
+
96
+ this.updateViewableItems();
97
+ };
98
+
91
99
  /**
92
100
  * Creates a new `ViewabilityHelper` instance with `onViewableItemsChanged` callback and `ViewabilityConfig`
93
101
  * @returns `ViewabilityHelper` instance