@react-native-macos/virtualized-lists 0.76.11 → 0.77.6

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.
package/CHANGELOG.json CHANGED
@@ -1,36 +1,6 @@
1
1
  {
2
2
  "name": "@react-native-mac/virtualized-lists",
3
3
  "entries": [
4
- {
5
- "date": "Tue, 03 Dec 2024 23:38:40 GMT",
6
- "version": "0.76.3",
7
- "tag": "@react-native-mac/virtualized-lists_v0.76.3",
8
- "comments": {
9
- "patch": [
10
- {
11
- "author": "sanajmi@microsoft.com",
12
- "package": "@react-native-mac/virtualized-lists",
13
- "commit": "acc82e5591a2cb8a0d0531379c999cd03f1748f7",
14
- "comment": "Applying package update to 0.76.2 ***NO_CI***"
15
- }
16
- ]
17
- }
18
- },
19
- {
20
- "date": "Tue, 29 Oct 2024 22:18:55 GMT",
21
- "version": "0.76.0",
22
- "tag": "@react-native-mac/virtualized-lists_v0.76.0",
23
- "comments": {
24
- "minor": [
25
- {
26
- "author": "sanajmi@microsoft.com",
27
- "package": "@react-native-mac/virtualized-lists",
28
- "commit": "74eacf73237c296712e8886a23e42fed58021c71",
29
- "comment": "chore(0.76): Merge up to 0.76.0 (#2232)"
30
- }
31
- ]
32
- }
33
- },
34
4
  {
35
5
  "date": "Wed, 06 Sep 2023 19:59:04 GMT",
36
6
  "tag": "@react-native-mac/virtualized-lists_v0.72.1",
package/CHANGELOG.md CHANGED
@@ -1,25 +1,9 @@
1
1
  # Change Log - @react-native-macos/virtualized-lists
2
2
 
3
- This log was last generated on Tue, 03 Dec 2024 23:38:40 GMT and should not be manually modified.
3
+ This log was last generated on Wed, 06 Sep 2023 19:59:04 GMT and should not be manually modified.
4
4
 
5
5
  <!-- Start content -->
6
6
 
7
- ## 0.76.3
8
-
9
- Tue, 03 Dec 2024 23:38:40 GMT
10
-
11
- ### Patches
12
-
13
- - Applying package update to 0.76.2 ***NO_CI*** (sanajmi@microsoft.com)
14
-
15
- ## 0.76.0
16
-
17
- Tue, 29 Oct 2024 22:18:55 GMT
18
-
19
- ### Minor changes
20
-
21
- - chore(0.76): Merge up to 0.76.0 (#2232) (sanajmi@microsoft.com)
22
-
23
7
  ## 0.72.1
24
8
 
25
9
  Wed, 06 Sep 2023 19:59:04 GMT
@@ -4,13 +4,12 @@
4
4
  * This source code is licensed under the MIT license found in the
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  *
7
- * @format
8
7
  * @flow strict-local
8
+ * @format
9
9
  */
10
10
 
11
- 'use strict';
12
-
13
- const {InteractionManager} = require('react-native');
11
+ import {InteractionManager} from 'react-native';
12
+ import * as ReactNativeFeatureFlags from 'react-native/src/private/featureflags/ReactNativeFeatureFlags';
14
13
 
15
14
  /**
16
15
  * A simple class for batching up invocations of a low-pri callback. A timeout is set to run the
@@ -38,37 +37,47 @@ class Batchinator {
38
37
  _callback: () => void;
39
38
  _delay: number;
40
39
  _taskHandle: ?{cancel: () => void, ...};
41
- constructor(callback: () => void, delayMS: number) {
42
- this._delay = delayMS;
40
+
41
+ constructor(callback: () => void, delay: number) {
42
+ this._delay = delay;
43
43
  this._callback = callback;
44
44
  }
45
+
45
46
  /*
46
47
  * Cleanup any pending tasks.
47
48
  *
48
49
  * By default, if there is a pending task the callback is run immediately. Set the option abort to
49
50
  * true to not call the callback if it was pending.
50
51
  */
51
- dispose(options: {abort: boolean, ...} = {abort: false}) {
52
+ dispose(): void {
52
53
  if (this._taskHandle) {
53
54
  this._taskHandle.cancel();
54
- if (!options.abort) {
55
- this._callback();
56
- }
57
55
  this._taskHandle = null;
58
56
  }
59
57
  }
60
- schedule() {
58
+
59
+ schedule(): void {
61
60
  if (this._taskHandle) {
62
61
  return;
63
62
  }
64
- const timeoutHandle = setTimeout(() => {
65
- this._taskHandle = InteractionManager.runAfterInteractions(() => {
66
- // Note that we clear the handle before invoking the callback so that if the callback calls
67
- // schedule again, it will actually schedule another task.
68
- this._taskHandle = null;
69
- this._callback();
70
- });
71
- }, this._delay);
63
+ const invokeCallback = () => {
64
+ // Note that we clear the handle before invoking the callback so that if the callback calls
65
+ // schedule again, it will actually schedule another task.
66
+ this._taskHandle = null;
67
+ this._callback();
68
+ };
69
+
70
+ const timeoutHandle = setTimeout(
71
+ // NOTE: When shipping this, delete `Batchinator` instead of only these
72
+ // lines of code. Without `InteractionManager`, it's just a `setTimeout`.
73
+ ReactNativeFeatureFlags.disableInteractionManagerInBatchinator()
74
+ ? invokeCallback
75
+ : () => {
76
+ this._taskHandle =
77
+ InteractionManager.runAfterInteractions(invokeCallback);
78
+ },
79
+ this._delay,
80
+ );
72
81
  this._taskHandle = {cancel: () => clearTimeout(timeoutHandle)};
73
82
  }
74
83
  }
@@ -167,6 +167,30 @@ export default class ListMetricsAggregator {
167
167
  // check for invalid frames due to row re-ordering
168
168
  return frame;
169
169
  } else {
170
+ let offset;
171
+
172
+ const highestMeasuredCellIndex = this.getHighestMeasuredCellIndex();
173
+ if (highestMeasuredCellIndex < index) {
174
+ // If any of the cells before this one have been laid out already, we
175
+ // should use that information in the estimations.
176
+ // This is important because if the list has a header, the initial cell
177
+ // will have a larger offset that we should take into account here.
178
+ const highestMeasuredCellFrame = this.getCellMetrics(
179
+ highestMeasuredCellIndex,
180
+ props,
181
+ );
182
+ if (highestMeasuredCellFrame) {
183
+ offset =
184
+ highestMeasuredCellFrame.offset +
185
+ highestMeasuredCellFrame.length +
186
+ this._averageCellLength * (index - highestMeasuredCellIndex - 1);
187
+ }
188
+ }
189
+
190
+ if (offset == null) {
191
+ offset = this._averageCellLength * index;
192
+ }
193
+
170
194
  const {data, getItemCount} = props;
171
195
  invariant(
172
196
  index >= 0 && index < getItemCount(data),
@@ -174,7 +198,7 @@ export default class ListMetricsAggregator {
174
198
  );
175
199
  return {
176
200
  length: this._averageCellLength,
177
- offset: this._averageCellLength * index,
201
+ offset,
178
202
  index,
179
203
  isMounted: false,
180
204
  };
@@ -35,7 +35,7 @@ export type ViewabilityConfigCallbackPair = {
35
35
  ...
36
36
  };
37
37
 
38
- export type ViewabilityConfig = {|
38
+ export type ViewabilityConfig = $ReadOnly<{|
39
39
  /**
40
40
  * Minimum amount of time (in milliseconds) that an item must be physically viewable before the
41
41
  * viewability callback will be fired. A high number means that scrolling through content without
@@ -62,7 +62,7 @@ export type ViewabilityConfig = {|
62
62
  * render.
63
63
  */
64
64
  waitForInteraction?: boolean,
65
- |};
65
+ |}>;
66
66
 
67
67
  /**
68
68
  * A Utility class for calculating viewable items based on current metrics like scroll position and
@@ -381,7 +381,7 @@ class VirtualizedList extends StateSafePureComponent<Props, State> {
381
381
 
382
382
  _registerAsNestedChild = (childList: {
383
383
  cellKey: string,
384
- ref: React.ElementRef<typeof VirtualizedList>,
384
+ ref: VirtualizedList,
385
385
  }): void => {
386
386
  this._nestedChildLists.add(childList.ref, childList.cellKey);
387
387
  if (this._hasInteracted) {
@@ -389,9 +389,7 @@ class VirtualizedList extends StateSafePureComponent<Props, State> {
389
389
  }
390
390
  };
391
391
 
392
- _unregisterAsNestedChild = (childList: {
393
- ref: React.ElementRef<typeof VirtualizedList>,
394
- }): void => {
392
+ _unregisterAsNestedChild = (childList: {ref: VirtualizedList}): void => {
395
393
  this._nestedChildLists.remove(childList.ref);
396
394
  };
397
395
 
@@ -715,7 +713,7 @@ class VirtualizedList extends StateSafePureComponent<Props, State> {
715
713
  if (this._isNestedWithSameOrientation()) {
716
714
  this.context.unregisterAsNestedChild({ref: this});
717
715
  }
718
- this._updateCellsToRenderBatcher.dispose({abort: true});
716
+ this._updateCellsToRenderBatcher.dispose();
719
717
  this._viewabilityTuples.forEach(tuple => {
720
718
  tuple.viewabilityHelper.dispose();
721
719
  });
@@ -989,8 +987,10 @@ class VirtualizedList extends StateSafePureComponent<Props, State> {
989
987
  <ListEmptyComponent />
990
988
  )): any);
991
989
  cells.push(
990
+ // $FlowFixMe[prop-missing] React.Element internal inspection
992
991
  <VirtualizedListCellContextProvider
993
992
  cellKey={this._getCellKey() + '-empty'}
993
+ collapsable={Platform.OS !== 'macos'} // [macOS]
994
994
  key="$empty">
995
995
  {React.cloneElement(element, {
996
996
  onLayout: (event: LayoutEvent) => {
@@ -1050,6 +1050,7 @@ class VirtualizedList extends StateSafePureComponent<Props, State> {
1050
1050
  lastMetrics.offset + lastMetrics.length - firstMetrics.offset;
1051
1051
  cells.push(
1052
1052
  <View
1053
+ collapsable={Platform.OS !== 'macos'} // [macOS]
1053
1054
  key={`$spacer-${section.first}`}
1054
1055
  style={{[spacerKey]: spacerSize}}
1055
1056
  />,
@@ -1090,6 +1091,7 @@ class VirtualizedList extends StateSafePureComponent<Props, State> {
1090
1091
  cellKey={this._getFooterCellKey()}
1091
1092
  key="$footer">
1092
1093
  <View
1094
+ collapsable={Platform.OS !== 'macos'} // [macOS]
1093
1095
  onLayout={this._onLayoutFooter}
1094
1096
  style={StyleSheet.compose(
1095
1097
  inversionStyle,
@@ -1200,7 +1202,7 @@ class VirtualizedList extends StateSafePureComponent<Props, State> {
1200
1202
  }
1201
1203
 
1202
1204
  componentDidUpdate(prevProps: Props) {
1203
- const {data, extraData} = this.props;
1205
+ const {data, extraData, getItemLayout} = this.props;
1204
1206
  if (data !== prevProps.data || extraData !== prevProps.extraData) {
1205
1207
  // clear the viewableIndices cache to also trigger
1206
1208
  // the onViewableItemsChanged callback with the new data
@@ -1221,6 +1223,14 @@ class VirtualizedList extends StateSafePureComponent<Props, State> {
1221
1223
  if (hiPriInProgress) {
1222
1224
  this._hiPriInProgress = false;
1223
1225
  }
1226
+
1227
+ // We only call `onEndReached` after we render the last cell, but when
1228
+ // getItemLayout is present, we can scroll past the last rendered cell, and
1229
+ // never trigger a new layout or bounds change, so we need to check again
1230
+ // after rendering more cells.
1231
+ if (getItemLayout != null) {
1232
+ this._maybeCallOnEdgeReached();
1233
+ }
1224
1234
  }
1225
1235
 
1226
1236
  _cellRefs: {[string]: null | CellRenderer<any>} = {};
@@ -1647,6 +1657,14 @@ class VirtualizedList extends StateSafePureComponent<Props, State> {
1647
1657
  onEndReached,
1648
1658
  onEndReachedThreshold,
1649
1659
  } = this.props;
1660
+ // Wait until we have real metrics
1661
+ if (
1662
+ !this._listMetrics.hasContentLength() ||
1663
+ this._scrollMetrics.visibleLength === 0
1664
+ ) {
1665
+ return;
1666
+ }
1667
+
1650
1668
  // If we have any pending scroll updates it means that the scroll metrics
1651
1669
  // are out of date and we should not call any of the edge reached callbacks.
1652
1670
  if (this.state.pendingScrollUpdateCount > 0) {
@@ -1790,6 +1808,10 @@ class VirtualizedList extends StateSafePureComponent<Props, State> {
1790
1808
  };
1791
1809
  };
1792
1810
 
1811
+ unstable_onScroll(e: Object) {
1812
+ this._onScroll(e);
1813
+ }
1814
+
1793
1815
  _onScroll = (e: Object) => {
1794
1816
  this._nestedChildLists.forEach(childList => {
1795
1817
  childList._onScroll(e);
@@ -1895,7 +1917,7 @@ class VirtualizedList extends StateSafePureComponent<Props, State> {
1895
1917
  this._hiPriInProgress = true;
1896
1918
  // Don't worry about interactions when scrolling quickly; focus on filling content as fast
1897
1919
  // as possible.
1898
- this._updateCellsToRenderBatcher.dispose({abort: true});
1920
+ this._updateCellsToRenderBatcher.dispose();
1899
1921
  this._updateCellsToRender();
1900
1922
  return;
1901
1923
  } else {
@@ -1942,6 +1964,10 @@ class VirtualizedList extends StateSafePureComponent<Props, State> {
1942
1964
  return hiPri;
1943
1965
  }
1944
1966
 
1967
+ unstable_onScrollBeginDrag(e: ScrollEvent) {
1968
+ this._onScrollBeginDrag(e);
1969
+ }
1970
+
1945
1971
  _onScrollBeginDrag = (e: ScrollEvent): void => {
1946
1972
  this._nestedChildLists.forEach(childList => {
1947
1973
  childList._onScrollBeginDrag(e);
@@ -1953,6 +1979,10 @@ class VirtualizedList extends StateSafePureComponent<Props, State> {
1953
1979
  this.props.onScrollBeginDrag && this.props.onScrollBeginDrag(e);
1954
1980
  };
1955
1981
 
1982
+ unstable_onScrollEndDrag(e: ScrollEvent) {
1983
+ this._onScrollEndDrag(e);
1984
+ }
1985
+
1956
1986
  _onScrollEndDrag = (e: ScrollEvent): void => {
1957
1987
  this._nestedChildLists.forEach(childList => {
1958
1988
  childList._onScrollEndDrag(e);
@@ -1965,6 +1995,10 @@ class VirtualizedList extends StateSafePureComponent<Props, State> {
1965
1995
  this.props.onScrollEndDrag && this.props.onScrollEndDrag(e);
1966
1996
  };
1967
1997
 
1998
+ unstable_onMomentumScrollBegin(e: ScrollEvent) {
1999
+ this._onMomentumScrollBegin(e);
2000
+ }
2001
+
1968
2002
  _onMomentumScrollBegin = (e: ScrollEvent): void => {
1969
2003
  this._nestedChildLists.forEach(childList => {
1970
2004
  childList._onMomentumScrollBegin(e);
@@ -1972,6 +2006,10 @@ class VirtualizedList extends StateSafePureComponent<Props, State> {
1972
2006
  this.props.onMomentumScrollBegin && this.props.onMomentumScrollBegin(e);
1973
2007
  };
1974
2008
 
2009
+ unstable_onMomentumScrollEnd(e: ScrollEvent) {
2010
+ this._onMomentumScrollEnd(e);
2011
+ }
2012
+
1975
2013
  _onMomentumScrollEnd = (e: ScrollEvent): void => {
1976
2014
  this._nestedChildLists.forEach(childList => {
1977
2015
  childList._onMomentumScrollEnd(e);
@@ -8,7 +8,6 @@
8
8
  * @format
9
9
  */
10
10
 
11
- import * as ReactNativeFeatureFlags from 'react-native/src/private/featureflags/ReactNativeFeatureFlags';
12
11
  import type {CellRendererProps, RenderItemType} from './VirtualizedListProps';
13
12
  import type {ViewStyleProp} from 'react-native/Libraries/StyleSheet/StyleSheet';
14
13
  import type {
@@ -19,7 +18,7 @@ import type {
19
18
  import {VirtualizedListCellContextProvider} from './VirtualizedListContext.js';
20
19
  import invariant from 'invariant';
21
20
  import * as React from 'react';
22
- import {StyleSheet, View} from 'react-native';
21
+ import {Platform, StyleSheet, View} from 'react-native'; // [macOS]
23
22
 
24
23
  export type Props<ItemT> = {
25
24
  CellRendererComponent?: ?React.ComponentType<CellRendererProps<ItemT>>,
@@ -70,17 +69,7 @@ export default class CellRenderer<ItemT> extends React.PureComponent<
70
69
  props: Props<ItemT>,
71
70
  prevState: State<ItemT>,
72
71
  ): ?State<ItemT> {
73
- if (ReactNativeFeatureFlags.enableOptimisedVirtualizedCells()) {
74
- if (props.item !== prevState.separatorProps.leadingItem) {
75
- return {
76
- separatorProps: {
77
- ...prevState.separatorProps,
78
- leadingItem: props.item,
79
- },
80
- };
81
- }
82
- return null;
83
- } else {
72
+ if (props.item !== prevState.separatorProps.leadingItem) {
84
73
  return {
85
74
  separatorProps: {
86
75
  ...prevState.separatorProps,
@@ -88,6 +77,7 @@ export default class CellRenderer<ItemT> extends React.PureComponent<
88
77
  },
89
78
  };
90
79
  }
80
+ return null;
91
81
  }
92
82
 
93
83
  // TODO: consider factoring separator stuff out of VirtualizedList into FlatList since it's not
@@ -219,7 +209,7 @@ export default class CellRenderer<ItemT> extends React.PureComponent<
219
209
  : horizontal
220
210
  ? [styles.row, inversionStyle]
221
211
  : inversionStyle;
222
- const result = !CellRendererComponent ? (
212
+ let result = !CellRendererComponent ? ( // [macOS]
223
213
  <View
224
214
  style={cellStyle}
225
215
  onFocusCapture={this._onCellFocusCapture}
@@ -240,6 +230,11 @@ export default class CellRenderer<ItemT> extends React.PureComponent<
240
230
  </CellRendererComponent>
241
231
  );
242
232
 
233
+ if (Platform.OS === 'macos') {
234
+ // [macOS
235
+ result = React.cloneElement(result, {collapsable: false});
236
+ } // macOS]
237
+
243
238
  return (
244
239
  <VirtualizedListCellContextProvider cellKey={this.props.cellKey}>
245
240
  {result}
@@ -146,7 +146,7 @@ class VirtualizedSectionList<
146
146
  this._listRef.scrollToIndex(toIndexParams);
147
147
  }
148
148
 
149
- getListRef(): ?React.ElementRef<typeof VirtualizedList> {
149
+ getListRef(): ?VirtualizedList {
150
150
  return this._listRef;
151
151
  }
152
152
 
@@ -598,14 +598,12 @@ function ItemWithSeparator(props: ItemWithSeparatorProps): React.Node {
598
598
  );
599
599
  }
600
600
 
601
- /* $FlowFixMe[class-object-subtyping] added when improving typing for this
602
- * parameters */
603
- // $FlowFixMe[method-unbinding]
604
- module.exports = (VirtualizedSectionList: React.AbstractComponent<
605
- React.ElementConfig<typeof VirtualizedSectionList>,
606
- $ReadOnly<{
607
- getListRef: () => ?React.ElementRef<typeof VirtualizedList>,
608
- scrollToLocation: (params: ScrollToLocationParamsType) => void,
609
- ...
610
- }>,
611
- >);
601
+ module.exports = VirtualizedSectionList as component(
602
+ ref: React.RefSetter<
603
+ interface {
604
+ getListRef(): ?VirtualizedList,
605
+ scrollToLocation(params: ScrollToLocationParamsType): void,
606
+ },
607
+ >,
608
+ ...Props<SectionBase<any>>
609
+ );
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@react-native-macos/virtualized-lists",
3
- "version": "0.76.11",
3
+ "version": "0.77.6",
4
4
  "description": "Virtualized lists for React Native macOS.",
5
5
  "license": "MIT",
6
6
  "repository": {