@legendapp/list 2.0.0-next.2 → 2.0.0-next.20

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 (260) hide show
  1. package/{dist/animated.d.mts → animated.d.mts} +7 -2
  2. package/{dist/animated.d.ts → animated.d.ts} +7 -2
  3. package/{dist/animated.js → animated.js} +2 -2
  4. package/{dist/animated.mjs → animated.mjs} +2 -2
  5. package/{dist/index.d.mts → index.d.mts} +106 -56
  6. package/{dist/index.d.ts → index.d.ts} +106 -56
  7. package/{dist/index.js → index.js} +1589 -1095
  8. package/{dist/index.mjs → index.mjs} +1591 -1097
  9. package/{dist/keyboard-controller.d.mts → keyboard-controller.d.mts} +28 -8
  10. package/{dist/keyboard-controller.d.ts → keyboard-controller.d.ts} +28 -8
  11. package/{dist/keyboard-controller.js → keyboard-controller.js} +4 -4
  12. package/{dist/keyboard-controller.mjs → keyboard-controller.mjs} +4 -4
  13. package/package.json +34 -88
  14. package/{dist/reanimated.d.mts → reanimated.d.mts} +2 -2
  15. package/{dist/reanimated.d.ts → reanimated.d.ts} +2 -2
  16. package/{dist/reanimated.js → reanimated.js} +7 -7
  17. package/{dist/reanimated.mjs → reanimated.mjs} +7 -7
  18. package/.claude/settings.local.json +0 -8
  19. package/.cursor/rules/changelog.mdc +0 -60
  20. package/.github/FUNDING.yml +0 -15
  21. package/.gitignore +0 -5
  22. package/.prettierrc.json +0 -5
  23. package/.vscode/settings.json +0 -14
  24. package/CLAUDE.md +0 -126
  25. package/biome.json +0 -46
  26. package/bun.lock +0 -1289
  27. package/bunfig.toml +0 -2
  28. package/dist/CHANGELOG.md +0 -119
  29. package/dist/LICENSE +0 -21
  30. package/dist/README.md +0 -139
  31. package/dist/package.json +0 -35
  32. package/example/README.md +0 -40
  33. package/example/api/data/genres.json +0 -23
  34. package/example/api/data/playlist/10402-10749.json +0 -1
  35. package/example/api/data/playlist/10402-10770.json +0 -1
  36. package/example/api/data/playlist/10402-37.json +0 -1
  37. package/example/api/data/playlist/10749-10752.json +0 -1
  38. package/example/api/data/playlist/10749-10770.json +0 -1
  39. package/example/api/data/playlist/10749-37.json +0 -1
  40. package/example/api/data/playlist/10749-878.json +0 -1
  41. package/example/api/data/playlist/10751-10402.json +0 -1
  42. package/example/api/data/playlist/10751-10752.json +0 -1
  43. package/example/api/data/playlist/10751-37.json +0 -1
  44. package/example/api/data/playlist/10751-53.json +0 -1
  45. package/example/api/data/playlist/10751-878.json +0 -1
  46. package/example/api/data/playlist/10751-9648.json +0 -1
  47. package/example/api/data/playlist/10752-37.json +0 -1
  48. package/example/api/data/playlist/12-10402.json +0 -1
  49. package/example/api/data/playlist/12-10749.json +0 -1
  50. package/example/api/data/playlist/12-18.json +0 -1
  51. package/example/api/data/playlist/12-27.json +0 -1
  52. package/example/api/data/playlist/12-35.json +0 -1
  53. package/example/api/data/playlist/14-36.json +0 -1
  54. package/example/api/data/playlist/14-878.json +0 -1
  55. package/example/api/data/playlist/16-10751.json +0 -1
  56. package/example/api/data/playlist/16-10770.json +0 -1
  57. package/example/api/data/playlist/16-35.json +0 -1
  58. package/example/api/data/playlist/16-36.json +0 -1
  59. package/example/api/data/playlist/16-53.json +0 -1
  60. package/example/api/data/playlist/18-10751.json +0 -1
  61. package/example/api/data/playlist/18-10752.json +0 -1
  62. package/example/api/data/playlist/18-37.json +0 -1
  63. package/example/api/data/playlist/18-53.json +0 -1
  64. package/example/api/data/playlist/18-878.json +0 -1
  65. package/example/api/data/playlist/27-10749.json +0 -1
  66. package/example/api/data/playlist/27-10770.json +0 -1
  67. package/example/api/data/playlist/28-10749.json +0 -1
  68. package/example/api/data/playlist/28-10751.json +0 -1
  69. package/example/api/data/playlist/28-10770.json +0 -1
  70. package/example/api/data/playlist/28-16.json +0 -1
  71. package/example/api/data/playlist/28-18.json +0 -1
  72. package/example/api/data/playlist/28-36.json +0 -1
  73. package/example/api/data/playlist/28-37.json +0 -1
  74. package/example/api/data/playlist/28-53.json +0 -1
  75. package/example/api/data/playlist/28-80.json +0 -1
  76. package/example/api/data/playlist/28-99.json +0 -1
  77. package/example/api/data/playlist/35-10749.json +0 -1
  78. package/example/api/data/playlist/35-10751.json +0 -1
  79. package/example/api/data/playlist/35-10752.json +0 -1
  80. package/example/api/data/playlist/35-27.json +0 -1
  81. package/example/api/data/playlist/35-36.json +0 -1
  82. package/example/api/data/playlist/35-53.json +0 -1
  83. package/example/api/data/playlist/35-80.json +0 -1
  84. package/example/api/data/playlist/36-37.json +0 -1
  85. package/example/api/data/playlist/36-878.json +0 -1
  86. package/example/api/data/playlist/36-9648.json +0 -1
  87. package/example/api/data/playlist/53-10752.json +0 -1
  88. package/example/api/data/playlist/80-10770.json +0 -1
  89. package/example/api/data/playlist/80-14.json +0 -1
  90. package/example/api/data/playlist/80-18.json +0 -1
  91. package/example/api/data/playlist/80-37.json +0 -1
  92. package/example/api/data/playlist/878-37.json +0 -1
  93. package/example/api/data/playlist/9648-10770.json +0 -1
  94. package/example/api/data/playlist/9648-37.json +0 -1
  95. package/example/api/data/playlist/9648-53.json +0 -1
  96. package/example/api/data/playlist/9648-878.json +0 -1
  97. package/example/api/data/playlist/99-10749.json +0 -1
  98. package/example/api/data/playlist/99-14.json +0 -1
  99. package/example/api/data/playlist/99-18.json +0 -1
  100. package/example/api/data/playlist/99-27.json +0 -1
  101. package/example/api/data/playlist/99-53.json +0 -1
  102. package/example/api/data/playlist/99-9648.json +0 -1
  103. package/example/api/data/playlist/index.ts +0 -73
  104. package/example/api/data/rows.json +0 -1
  105. package/example/api/index.ts +0 -36
  106. package/example/app/(tabs)/_layout.tsx +0 -60
  107. package/example/app/(tabs)/cards.tsx +0 -81
  108. package/example/app/(tabs)/index.tsx +0 -205
  109. package/example/app/(tabs)/moviesL.tsx +0 -7
  110. package/example/app/(tabs)/moviesLR.tsx +0 -7
  111. package/example/app/+not-found.tsx +0 -32
  112. package/example/app/_layout.tsx +0 -34
  113. package/example/app/accurate-scrollto/index.tsx +0 -125
  114. package/example/app/accurate-scrollto-2/index.tsx +0 -52
  115. package/example/app/accurate-scrollto-huge/index.tsx +0 -128
  116. package/example/app/add-to-end/index.tsx +0 -82
  117. package/example/app/ai-chat/index.tsx +0 -236
  118. package/example/app/bidirectional-infinite-list/index.tsx +0 -133
  119. package/example/app/cards-columns/index.tsx +0 -37
  120. package/example/app/cards-flashlist/index.tsx +0 -122
  121. package/example/app/cards-flatlist/index.tsx +0 -94
  122. package/example/app/cards-no-recycle/index.tsx +0 -110
  123. package/example/app/cards-renderItem.tsx +0 -354
  124. package/example/app/chat-example/index.tsx +0 -167
  125. package/example/app/chat-infinite/index.tsx +0 -239
  126. package/example/app/chat-keyboard/index.tsx +0 -248
  127. package/example/app/chat-resize-outer/index.tsx +0 -247
  128. package/example/app/columns/index.tsx +0 -78
  129. package/example/app/countries/index.tsx +0 -182
  130. package/example/app/countries-flashlist/index.tsx +0 -163
  131. package/example/app/countries-reorder/index.tsx +0 -187
  132. package/example/app/extra-data/index.tsx +0 -86
  133. package/example/app/filter-elements/filter-data-provider.tsx +0 -55
  134. package/example/app/filter-elements/index.tsx +0 -118
  135. package/example/app/initial-scroll-index/index.tsx +0 -106
  136. package/example/app/initial-scroll-index/renderFixedItem.tsx +0 -215
  137. package/example/app/initial-scroll-index-free-height/index.tsx +0 -70
  138. package/example/app/initial-scroll-index-keyed/index.tsx +0 -62
  139. package/example/app/lazy-list/index.tsx +0 -123
  140. package/example/app/movies-flashlist/index.tsx +0 -7
  141. package/example/app/mutable-cells/index.tsx +0 -104
  142. package/example/app/video-feed/index.tsx +0 -119
  143. package/example/app.config.js +0 -22
  144. package/example/app.json +0 -45
  145. package/example/assets/fonts/SpaceMono-Regular.ttf +0 -0
  146. package/example/assets/images/adaptive-icon.png +0 -0
  147. package/example/assets/images/favicon.png +0 -0
  148. package/example/assets/images/icon.png +0 -0
  149. package/example/assets/images/partial-react-logo.png +0 -0
  150. package/example/assets/images/react-logo.png +0 -0
  151. package/example/assets/images/react-logo@2x.png +0 -0
  152. package/example/assets/images/react-logo@3x.png +0 -0
  153. package/example/assets/images/splash-icon.png +0 -0
  154. package/example/autoscroll.sh +0 -101
  155. package/example/bun.lock +0 -2266
  156. package/example/bunfig.toml +0 -2
  157. package/example/components/Breathe.tsx +0 -54
  158. package/example/components/Circle.tsx +0 -69
  159. package/example/components/Collapsible.tsx +0 -44
  160. package/example/components/ExternalLink.tsx +0 -24
  161. package/example/components/HapticTab.tsx +0 -18
  162. package/example/components/HelloWave.tsx +0 -37
  163. package/example/components/Movies.tsx +0 -179
  164. package/example/components/ParallaxScrollView.tsx +0 -81
  165. package/example/components/ThemedText.tsx +0 -60
  166. package/example/components/ThemedView.tsx +0 -14
  167. package/example/components/__tests__/ThemedText-test.tsx +0 -10
  168. package/example/components/__tests__/__snapshots__/ThemedText-test.tsx.snap +0 -24
  169. package/example/components/ui/IconSymbol.ios.tsx +0 -32
  170. package/example/components/ui/IconSymbol.tsx +0 -43
  171. package/example/components/ui/TabBarBackground.ios.tsx +0 -22
  172. package/example/components/ui/TabBarBackground.tsx +0 -6
  173. package/example/constants/Colors.ts +0 -26
  174. package/example/constants/constants.ts +0 -5
  175. package/example/constants/useScrollTest.ts +0 -19
  176. package/example/hooks/useColorScheme.ts +0 -1
  177. package/example/hooks/useColorScheme.web.ts +0 -8
  178. package/example/hooks/useThemeColor.ts +0 -22
  179. package/example/ios/.xcode.env +0 -11
  180. package/example/ios/Podfile +0 -64
  181. package/example/ios/Podfile.lock +0 -2767
  182. package/example/ios/Podfile.properties.json +0 -5
  183. package/example/ios/listtest/AppDelegate.swift +0 -70
  184. package/example/ios/listtest/Images.xcassets/AppIcon.appiconset/App-Icon-1024x1024@1x.png +0 -0
  185. package/example/ios/listtest/Images.xcassets/AppIcon.appiconset/Contents.json +0 -14
  186. package/example/ios/listtest/Images.xcassets/Contents.json +0 -6
  187. package/example/ios/listtest/Images.xcassets/SplashScreenBackground.colorset/Contents.json +0 -20
  188. package/example/ios/listtest/Images.xcassets/SplashScreenLogo.imageset/Contents.json +0 -23
  189. package/example/ios/listtest/Images.xcassets/SplashScreenLogo.imageset/image.png +0 -0
  190. package/example/ios/listtest/Images.xcassets/SplashScreenLogo.imageset/image@2x.png +0 -0
  191. package/example/ios/listtest/Images.xcassets/SplashScreenLogo.imageset/image@3x.png +0 -0
  192. package/example/ios/listtest/Info.plist +0 -85
  193. package/example/ios/listtest/PrivacyInfo.xcprivacy +0 -48
  194. package/example/ios/listtest/SplashScreen.storyboard +0 -42
  195. package/example/ios/listtest/Supporting/Expo.plist +0 -12
  196. package/example/ios/listtest/listtest-Bridging-Header.h +0 -3
  197. package/example/ios/listtest/listtest.entitlements +0 -5
  198. package/example/ios/listtest.xcodeproj/project.pbxproj +0 -547
  199. package/example/ios/listtest.xcodeproj/xcshareddata/xcschemes/listtest.xcscheme +0 -88
  200. package/example/ios/listtest.xcworkspace/contents.xcworkspacedata +0 -10
  201. package/example/metro.config.js +0 -16
  202. package/example/package.json +0 -73
  203. package/example/scripts/reset-project.js +0 -84
  204. package/example/tsconfig.json +0 -26
  205. package/posttsup.ts +0 -24
  206. package/src/Container.tsx +0 -176
  207. package/src/Containers.tsx +0 -85
  208. package/src/ContextContainer.ts +0 -145
  209. package/src/DebugView.tsx +0 -83
  210. package/src/LazyLegendList.tsx +0 -41
  211. package/src/LeanView.tsx +0 -18
  212. package/src/LegendList.tsx +0 -558
  213. package/src/ListComponent.tsx +0 -191
  214. package/src/ScrollAdjust.tsx +0 -24
  215. package/src/ScrollAdjustHandler.ts +0 -26
  216. package/src/Separator.tsx +0 -14
  217. package/src/animated.tsx +0 -6
  218. package/src/calculateItemsInView.ts +0 -363
  219. package/src/calculateOffsetForIndex.ts +0 -23
  220. package/src/calculateOffsetWithOffsetPosition.ts +0 -26
  221. package/src/checkAllSizesKnown.ts +0 -17
  222. package/src/checkAtBottom.ts +0 -36
  223. package/src/checkAtTop.ts +0 -27
  224. package/src/checkThreshold.ts +0 -30
  225. package/src/constants.ts +0 -11
  226. package/src/createColumnWrapperStyle.ts +0 -16
  227. package/src/doInitialAllocateContainers.ts +0 -40
  228. package/src/doMaintainScrollAtEnd.ts +0 -34
  229. package/src/findAvailableContainers.ts +0 -98
  230. package/src/finishScrollTo.ts +0 -8
  231. package/src/getId.ts +0 -21
  232. package/src/getItemSize.ts +0 -52
  233. package/src/getRenderedItem.ts +0 -34
  234. package/src/getScrollVelocity.ts +0 -47
  235. package/src/handleLayout.ts +0 -70
  236. package/src/helpers.ts +0 -39
  237. package/src/index.ts +0 -11
  238. package/src/keyboard-controller.tsx +0 -63
  239. package/src/onScroll.ts +0 -66
  240. package/src/prepareMVCP.ts +0 -50
  241. package/src/reanimated.tsx +0 -63
  242. package/src/requestAdjust.ts +0 -41
  243. package/src/scrollTo.ts +0 -40
  244. package/src/scrollToIndex.ts +0 -34
  245. package/src/setDidLayout.ts +0 -25
  246. package/src/setPaddingTop.ts +0 -28
  247. package/src/state.tsx +0 -304
  248. package/src/types.ts +0 -610
  249. package/src/updateAlignItemsPaddingTop.ts +0 -18
  250. package/src/updateAllPositions.ts +0 -130
  251. package/src/updateItemSize.ts +0 -203
  252. package/src/updateTotalSize.ts +0 -44
  253. package/src/useAnimatedValue.ts +0 -6
  254. package/src/useCombinedRef.ts +0 -22
  255. package/src/useInit.ts +0 -17
  256. package/src/useSyncLayout.tsx +0 -68
  257. package/src/useValue$.ts +0 -53
  258. package/src/viewability.ts +0 -279
  259. package/tsconfig.json +0 -59
  260. package/tsup.config.ts +0 -21
@@ -1,130 +0,0 @@
1
- import { getId } from "./getId";
2
- import { getItemSize } from "./getItemSize";
3
- import { getScrollVelocity } from "./getScrollVelocity";
4
- import { roundSize } from "./helpers";
5
- import { type StateContext, peek$ } from "./state";
6
- import type { InternalState } from "./types";
7
- import { updateTotalSize } from "./updateTotalSize";
8
-
9
- export function updateAllPositions(ctx: StateContext, state: InternalState, dataChanged?: boolean) {
10
- const { averageSizes, columns, indexByKey, positions, firstFullyOnScreenIndex, idCache, sizesKnown } = state;
11
- const data = state.props.data;
12
- const numColumns = peek$(ctx, "numColumns");
13
- const indexByKeyForChecking = __DEV__ ? new Map() : undefined;
14
- const scrollVelocity = getScrollVelocity(state);
15
-
16
- if (dataChanged) {
17
- indexByKey.clear();
18
- idCache.clear();
19
- }
20
-
21
- // TODO: Hook this up to actual item types later once we have item types
22
- const itemType = "";
23
- let averageSize = averageSizes[itemType]?.avg;
24
- if (averageSize !== undefined) {
25
- averageSize = roundSize(averageSize);
26
- }
27
-
28
- // Check if we should use backwards optimization when scrolling up
29
- const shouldUseBackwards =
30
- !dataChanged && scrollVelocity < 0 && firstFullyOnScreenIndex > 5 && firstFullyOnScreenIndex < data!.length;
31
-
32
- if (shouldUseBackwards && firstFullyOnScreenIndex !== undefined) {
33
- // Get the current position of firstFullyOnScreenIndex as anchor
34
- const anchorId = getId(state, firstFullyOnScreenIndex)!;
35
- const anchorPosition = positions.get(anchorId);
36
-
37
- // If we don't have the anchor position, fall back to regular behavior
38
- if (anchorPosition !== undefined) {
39
- // Start from the anchor and go backwards
40
- let currentRowTop = anchorPosition;
41
- let maxSizeInRow = 0;
42
- let bailout = false;
43
-
44
- // Process items backwards from firstFullyOnScreenIndex - 1 to 0
45
- for (let i = firstFullyOnScreenIndex - 1; i >= 0; i--) {
46
- const id = idCache.get(i) ?? getId(state, i)!;
47
- const size = sizesKnown.get(id) ?? getItemSize(state, id, i, data[i], averageSize);
48
- const itemColumn = columns.get(id)!;
49
-
50
- maxSizeInRow = Math.max(maxSizeInRow, size);
51
-
52
- // When we reach column 1, we're at the start of a new row going backwards
53
- if (itemColumn === 1) {
54
- currentRowTop -= maxSizeInRow;
55
- maxSizeInRow = 0;
56
- }
57
-
58
- // Check if position goes too low - bail if so
59
- if (currentRowTop < -2000) {
60
- bailout = true;
61
- break;
62
- }
63
-
64
- // Update position for this item (columns and indexByKey already set)
65
- positions.set(id, currentRowTop);
66
- }
67
-
68
- if (!bailout) {
69
- // We successfully processed backwards, we're done
70
- updateTotalSize(ctx, state);
71
- return;
72
- }
73
- }
74
- }
75
-
76
- // Regular ascending behavior (either not scrolling up or bailed out)
77
- let currentRowTop = 0;
78
- let column = 1;
79
- let maxSizeInRow = 0;
80
-
81
- const hasColumns = numColumns > 1;
82
- const needsIndexByKey = dataChanged || indexByKey.size === 0;
83
-
84
- // Note that this loop is micro-optimized because it's a hot path
85
- const dataLength = data!.length;
86
- for (let i = 0; i < dataLength; i++) {
87
- // Inline the map get calls to avoid the overhead of the function call
88
- const id = idCache.get(i) ?? getId(state, i)!;
89
- const size = sizesKnown.get(id) ?? getItemSize(state, id, i, data[i], averageSize);
90
-
91
- // Set index mapping for this item
92
- if (__DEV__ && needsIndexByKey) {
93
- if (indexByKeyForChecking!.has(id)) {
94
- console.error(
95
- `[legend-list] Error: Detected overlapping key (${id}) which causes missing items and gaps and other terrrible things. Check that keyExtractor returns unique values.`,
96
- );
97
- }
98
- indexByKeyForChecking!.set(id, i);
99
- }
100
-
101
- // Set position for this item
102
- positions.set(id, currentRowTop);
103
-
104
- // Update indexByKey if needed
105
- if (needsIndexByKey) {
106
- indexByKey.set(id, i);
107
- }
108
-
109
- // Set column for this item
110
- columns.set(id, column);
111
-
112
- if (hasColumns) {
113
- if (size > maxSizeInRow) {
114
- maxSizeInRow = size;
115
- }
116
-
117
- column++;
118
- if (column > numColumns) {
119
- // Move to next row
120
- currentRowTop += maxSizeInRow;
121
- column = 1;
122
- maxSizeInRow = 0;
123
- }
124
- } else {
125
- currentRowTop += size;
126
- }
127
- }
128
-
129
- updateTotalSize(ctx, state);
130
- }
@@ -1,203 +0,0 @@
1
- import type { LayoutRectangle } from "react-native";
2
- import { calculateItemsInView } from "./calculateItemsInView";
3
- import { checkAllSizesKnown } from "./checkAllSizesKnown";
4
- import { IsNewArchitecture } from "./constants";
5
- import { doMaintainScrollAtEnd } from "./doMaintainScrollAtEnd";
6
- import { getItemSize } from "./getItemSize";
7
- import { requestAdjust } from "./requestAdjust";
8
- import { type StateContext, peek$, set$ } from "./state";
9
- import type { InternalState, MaintainScrollAtEndOptions } from "./types";
10
-
11
- export function updateItemSizes(
12
- ctx: StateContext,
13
- state: InternalState,
14
- itemUpdates: { itemKey: string; sizeObj: { width: number; height: number } }[],
15
- ) {
16
- const {
17
- props: {
18
- horizontal,
19
- maintainVisibleContentPosition,
20
- suggestEstimatedItemSize,
21
- onItemSizeChanged,
22
- data,
23
- maintainScrollAtEnd,
24
- },
25
- } = state;
26
-
27
- if (!data) return;
28
-
29
- let needsRecalculate = false;
30
- let shouldMaintainScrollAtEnd = false;
31
- let minIndexSizeChanged: number | undefined;
32
- let maxOtherAxisSize = peek$(ctx, "otherAxisSize") || 0;
33
-
34
- for (const { itemKey, sizeObj } of itemUpdates) {
35
- const index = state.indexByKey.get(itemKey)!;
36
- const prevSizeKnown = state.sizesKnown.get(itemKey);
37
-
38
- const diff = updateOneItemSize(state, itemKey, sizeObj);
39
- const size = Math.floor((horizontal ? sizeObj.width : sizeObj.height) * 8) / 8;
40
-
41
- if (diff !== 0) {
42
- minIndexSizeChanged = minIndexSizeChanged !== undefined ? Math.min(minIndexSizeChanged, index) : index;
43
-
44
- // Handle scrolling adjustments
45
- if (
46
- state.scrollingTo?.viewPosition &&
47
- maintainVisibleContentPosition &&
48
- index === state.scrollingTo.index
49
- ) {
50
- requestAdjust(ctx, state, diff * state.scrollingTo.viewPosition);
51
- }
52
-
53
- // Check if item is in view
54
- const { startBuffered, endBuffered } = state;
55
- needsRecalculate ||= index >= startBuffered && index <= endBuffered;
56
- if (!needsRecalculate) {
57
- const numContainers = ctx.values.get("numContainers") as number;
58
- for (let i = 0; i < numContainers; i++) {
59
- if (peek$(ctx, `containerItemKey${i}`) === itemKey) {
60
- needsRecalculate = true;
61
- break;
62
- }
63
- }
64
- }
65
-
66
- // Handle other axis size
67
- if (state.needsOtherAxisSize) {
68
- const otherAxisSize = horizontal ? sizeObj.height : sizeObj.width;
69
- maxOtherAxisSize = Math.max(maxOtherAxisSize, otherAxisSize);
70
- }
71
-
72
- // Check if we should maintain scroll at end
73
- if (prevSizeKnown !== undefined && Math.abs(prevSizeKnown - size) > 5) {
74
- shouldMaintainScrollAtEnd = true;
75
- }
76
-
77
- // Call onItemSizeChanged callback
78
- onItemSizeChanged?.({
79
- size,
80
- previous: size - diff,
81
- index,
82
- itemKey,
83
- itemData: state.props.data[index],
84
- });
85
- }
86
- }
87
-
88
- // Update state with minimum changed index
89
- if (minIndexSizeChanged !== undefined) {
90
- state.minIndexSizeChanged =
91
- state.minIndexSizeChanged !== undefined
92
- ? Math.min(state.minIndexSizeChanged, minIndexSizeChanged)
93
- : minIndexSizeChanged;
94
- }
95
-
96
- // Handle dev warning about estimated size
97
- if (__DEV__ && suggestEstimatedItemSize && minIndexSizeChanged !== undefined) {
98
- if (state.timeoutSizeMessage) clearTimeout(state.timeoutSizeMessage);
99
- state.timeoutSizeMessage = setTimeout(() => {
100
- state.timeoutSizeMessage = undefined;
101
- const num = state.sizesKnown.size;
102
- const avg = state.averageSizes[""]?.avg;
103
- console.warn(
104
- `[legend-list] Based on the ${num} items rendered so far, the optimal estimated size is ${avg}.`,
105
- );
106
- }, 1000);
107
- }
108
-
109
- const cur = peek$(ctx, "otherAxisSize");
110
- if (!cur || maxOtherAxisSize > cur) {
111
- set$(ctx, "otherAxisSize", maxOtherAxisSize);
112
- }
113
-
114
- const containersDidLayout = peek$(ctx, "containersDidLayout");
115
-
116
- if (containersDidLayout || checkAllSizesKnown(state)) {
117
- if (needsRecalculate) {
118
- state.scrollForNextCalculateItemsInView = undefined;
119
-
120
- calculateItemsInView(ctx, state, { doMVCP: true });
121
- }
122
- if (shouldMaintainScrollAtEnd) {
123
- if (maintainScrollAtEnd === true || (maintainScrollAtEnd as MaintainScrollAtEndOptions).onItemLayout) {
124
- doMaintainScrollAtEnd(ctx, state, false);
125
- }
126
- }
127
- }
128
- }
129
-
130
- export function updateItemSize(
131
- ctx: StateContext,
132
- state: InternalState,
133
- itemKey: string,
134
- sizeObj: { width: number; height: number },
135
- ) {
136
- if (IsNewArchitecture) {
137
- const { sizesKnown } = state;
138
- const numContainers = ctx.values.get("numContainers") as number;
139
- const changes: { itemKey: string; sizeObj: { width: number; height: number } }[] = [];
140
-
141
- // Run through all containers and if we don't already have a known size then measure the item
142
- // This is useful because when multiple items render in one frame, the first container fires a
143
- // useLayoutEffect and we can measure all containers before their useLayoutEffects fire after a delay.
144
- // This lets use fix any gaps/overlaps that might be visible before the useLayoutEffects fire for each container.
145
- for (let i = 0; i < numContainers; i++) {
146
- const containerItemKey = peek$(ctx, `containerItemKey${i}`);
147
- if (itemKey === containerItemKey) {
148
- // If it's this item just use the param
149
- changes.push({ itemKey, sizeObj });
150
- } else if (!sizesKnown.has(containerItemKey) && containerItemKey !== undefined) {
151
- const containerRef = ctx.viewRefs.get(i);
152
- if (containerRef?.current) {
153
- let measured: LayoutRectangle;
154
- containerRef.current.measure((x, y, width, height) => {
155
- measured = { x, y, width, height };
156
- });
157
-
158
- if (measured!) {
159
- changes.push({ itemKey: containerItemKey, sizeObj: measured });
160
- }
161
- }
162
- }
163
- }
164
-
165
- if (changes.length > 0) {
166
- updateItemSizes(ctx, state, changes);
167
- }
168
- } else {
169
- updateItemSizes(ctx, state, [{ itemKey, sizeObj }]);
170
- }
171
- }
172
-
173
- export function updateOneItemSize(state: InternalState, itemKey: string, sizeObj: { width: number; height: number }) {
174
- const {
175
- sizes,
176
- indexByKey,
177
- sizesKnown,
178
- averageSizes,
179
- props: { data, horizontal },
180
- } = state;
181
- if (!data) return 0;
182
-
183
- const index = indexByKey.get(itemKey)!;
184
- const prevSize = getItemSize(state, itemKey, index, data as any);
185
- const size = Math.floor((horizontal ? sizeObj.width : sizeObj.height) * 8) / 8;
186
-
187
- sizesKnown.set(itemKey, size);
188
-
189
- // Update averages
190
- const itemType = "";
191
- let averages = averageSizes[itemType];
192
- if (!averages) {
193
- averages = averageSizes[itemType] = { num: 0, avg: 0 };
194
- }
195
- averages.avg = (averages.avg * averages.num + size) / (averages.num + 1);
196
- averages.num++;
197
-
198
- if (!prevSize || Math.abs(prevSize - size) > 0.1) {
199
- sizes.set(itemKey, size);
200
- return size - prevSize;
201
- }
202
- return 0;
203
- }
@@ -1,44 +0,0 @@
1
- import { getId } from "./getId";
2
- import { getItemSize } from "./getItemSize";
3
- import { type StateContext, set$ } from "./state";
4
- import type { InternalState } from "./types";
5
- import { updateAlignItemsPaddingTop } from "./updateAlignItemsPaddingTop";
6
-
7
- export function updateTotalSize(ctx: StateContext, state: InternalState) {
8
- const {
9
- positions,
10
- props: { data },
11
- } = state;
12
-
13
- if (data.length === 0) {
14
- addTotalSize(ctx, state, null, 0);
15
- } else {
16
- const lastId = getId(state, data.length - 1);
17
- if (lastId !== undefined) {
18
- const lastPosition = positions.get(lastId);
19
- if (lastPosition !== undefined) {
20
- const lastSize = getItemSize(state, lastId, data.length - 1, data[data.length - 1]);
21
- // TODO: This is likely incorrect for columns with rows having different heights, need to get max size of the last row
22
- if (lastSize !== undefined) {
23
- const totalSize = lastPosition + lastSize;
24
- addTotalSize(ctx, state, null, totalSize);
25
- }
26
- }
27
- }
28
- }
29
- }
30
-
31
- function addTotalSize(ctx: StateContext, state: InternalState, key: string | null, add: number) {
32
- const { alignItemsAtEnd } = state.props;
33
- if (key === null) {
34
- state.totalSize = add;
35
- } else {
36
- state.totalSize += add;
37
- }
38
-
39
- set$(ctx, "totalSize", state.totalSize);
40
-
41
- if (alignItemsAtEnd) {
42
- updateAlignItemsPaddingTop(ctx, state);
43
- }
44
- }
@@ -1,6 +0,0 @@
1
- import { useRef } from "react";
2
- import { Animated } from "react-native";
3
-
4
- export const useAnimatedValue = (initialValue: number): Animated.Value => {
5
- return useRef(new Animated.Value(initialValue)).current;
6
- };
@@ -1,22 +0,0 @@
1
- import { useCallback } from "react";
2
- import { isFunction } from "./helpers";
3
-
4
- type RefItem<T> = ((element: T | null) => void) | React.MutableRefObject<T | null> | null | undefined;
5
-
6
- export const useCombinedRef = <T>(...refs: RefItem<T>[]) => {
7
- const callback = useCallback((element: T | null) => {
8
- for (const ref of refs) {
9
- if (!ref) {
10
- continue;
11
- }
12
-
13
- if (isFunction(ref)) {
14
- ref(element);
15
- } else {
16
- ref.current = element;
17
- }
18
- }
19
- }, refs);
20
-
21
- return callback;
22
- };
package/src/useInit.ts DELETED
@@ -1,17 +0,0 @@
1
- import { useRef } from "react";
2
-
3
- const symbolFirst = Symbol();
4
- // A hook that runs a callback only once during the first render.
5
- // It should happen during render, not in useEffect, so that any setState calls during the callback
6
- // will trigger a re-render immediately rather than waiting for a next render.
7
- // See https://react.dev/reference/react/useState#storing-information-from-previous-renders
8
- export function useInit<T>(cb: () => T) {
9
- const refValue = useRef<T | typeof symbolFirst>(symbolFirst);
10
-
11
- // Run inline during first render only
12
- if (refValue.current === symbolFirst) {
13
- refValue.current = cb();
14
- }
15
-
16
- return refValue.current;
17
- }
@@ -1,68 +0,0 @@
1
- import { useCallback, useLayoutEffect, useRef, useState } from "react";
2
- import type { LayoutChangeEvent, LayoutRectangle, View } from "react-native";
3
-
4
- export function useSyncLayoutState<T extends View = View>({
5
- getValue,
6
- debounce,
7
- onChange: onChangeProp,
8
- }: {
9
- getValue: (rectangle: LayoutRectangle) => number;
10
- debounce?: number | undefined;
11
- onChange: (rectangle: LayoutRectangle, fromLayoutEffect: boolean) => void;
12
- }) {
13
- const debounceTimeoutRef = useRef<any>(null);
14
- const [value, setValue] = useState(0);
15
-
16
- const onChange = useCallback(
17
- (rectangle: LayoutRectangle, fromLayoutEffect: boolean) => {
18
- const height = getValue(rectangle);
19
-
20
- if (debounce === undefined) {
21
- setValue(height);
22
- } else {
23
- // Clear previous timeout if it exists
24
- if (debounceTimeoutRef.current) {
25
- clearTimeout(debounceTimeoutRef.current);
26
- }
27
-
28
- // Debounce the setViewHeight call
29
- debounceTimeoutRef.current = setTimeout(() => {
30
- debounceTimeoutRef.current = null;
31
- setValue(height);
32
- }, debounce);
33
- }
34
-
35
- onChangeProp?.(rectangle, fromLayoutEffect);
36
- },
37
- [getValue, debounce],
38
- );
39
-
40
- const { onLayout, ref } = useSyncLayout<T>({ onChange });
41
-
42
- return { value, onLayout, ref };
43
- }
44
-
45
- export function useSyncLayout<T extends View = View>({
46
- onChange,
47
- }: {
48
- onChange: (rectangle: LayoutRectangle, fromLayoutEffect: boolean) => void;
49
- }) {
50
- const ref = useRef<T | null>(null);
51
-
52
- const onLayout = useCallback(
53
- (event: LayoutChangeEvent) => {
54
- onChange(event.nativeEvent.layout, false);
55
- },
56
- [onChange],
57
- );
58
-
59
- useLayoutEffect(() => {
60
- if (ref.current) {
61
- ref.current.measure((x, y, width, height) => {
62
- onChange({ x, y, width, height }, true);
63
- });
64
- }
65
- }, []);
66
-
67
- return { onLayout, ref };
68
- }
package/src/useValue$.ts DELETED
@@ -1,53 +0,0 @@
1
- import { useMemo } from "react";
2
- import { listen$, peek$, useStateContext } from "./state";
3
- import type { ListenerType } from "./state";
4
- import { useAnimatedValue } from "./useAnimatedValue";
5
-
6
- export function useValue$(
7
- key: ListenerType,
8
- params?: {
9
- getValue?: (value: number) => number;
10
- delay?: number | ((value: number, prevValue: number | undefined) => number);
11
- },
12
- ) {
13
- const { getValue, delay } = params || {};
14
- const ctx = useStateContext();
15
- const animValue = useAnimatedValue((getValue ? getValue(peek$(ctx, key)) : peek$(ctx, key)) ?? 0);
16
- useMemo(() => {
17
- let newValue: number | undefined = undefined;
18
- let prevValue: number | undefined = undefined;
19
- let didQueueTask = false;
20
- listen$(ctx, key, (v) => {
21
- newValue = getValue ? getValue(v) : v;
22
-
23
- if (delay !== undefined) {
24
- // Queue into a microtask because setting the value immediately was making the value
25
- // not actually set. I think it has to do with setting during useLayoutEffect, but I'm not sure.
26
- // This seems to be an optimization for setting totalSize because that can happen multiple times per frame
27
- // so we skip setting the value immediately if using the microtask version.
28
- const fn = () => {
29
- didQueueTask = false;
30
- if (newValue !== undefined) {
31
- animValue.setValue(newValue!);
32
- }
33
- };
34
- const delayValue = typeof delay === "function" ? delay(newValue!, prevValue) : delay;
35
- prevValue = newValue;
36
- if (!didQueueTask) {
37
- didQueueTask = true;
38
- if (delayValue === 0) {
39
- queueMicrotask(fn);
40
- } else {
41
- // We're not clearing the timeout because we want it to run in the timeout from the first change
42
- // but just not run multiple times.
43
- setTimeout(fn, delayValue);
44
- }
45
- }
46
- } else {
47
- animValue.setValue(newValue!);
48
- }
49
- });
50
- }, []);
51
-
52
- return animValue;
53
- }