@leonsilicon/react-native-reanimated-carousel 0.0.0

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 (328) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +652 -0
  3. package/lib/commonjs/components/Carousel.js +2 -0
  4. package/lib/commonjs/components/Carousel.js.map +1 -0
  5. package/lib/commonjs/components/CarouselLayout.js +2 -0
  6. package/lib/commonjs/components/CarouselLayout.js.map +1 -0
  7. package/lib/commonjs/components/ItemLayout.js +2 -0
  8. package/lib/commonjs/components/ItemLayout.js.map +1 -0
  9. package/lib/commonjs/components/ItemRenderer.js +2 -0
  10. package/lib/commonjs/components/ItemRenderer.js.map +1 -0
  11. package/lib/commonjs/components/LazyView.js +2 -0
  12. package/lib/commonjs/components/LazyView.js.map +1 -0
  13. package/lib/commonjs/components/Pagination/Basic/PaginationItem.js +2 -0
  14. package/lib/commonjs/components/Pagination/Basic/PaginationItem.js.map +1 -0
  15. package/lib/commonjs/components/Pagination/Basic/index.js +2 -0
  16. package/lib/commonjs/components/Pagination/Basic/index.js.map +1 -0
  17. package/lib/commonjs/components/Pagination/Custom/PaginationItem.js +2 -0
  18. package/lib/commonjs/components/Pagination/Custom/PaginationItem.js.map +1 -0
  19. package/lib/commonjs/components/Pagination/Custom/index.js +2 -0
  20. package/lib/commonjs/components/Pagination/Custom/index.js.map +1 -0
  21. package/lib/commonjs/components/Pagination/index.js +2 -0
  22. package/lib/commonjs/components/Pagination/index.js.map +1 -0
  23. package/lib/commonjs/components/ScrollViewGesture.js +2 -0
  24. package/lib/commonjs/components/ScrollViewGesture.js.map +1 -0
  25. package/lib/commonjs/constants/index.js +2 -0
  26. package/lib/commonjs/constants/index.js.map +1 -0
  27. package/lib/commonjs/hooks/useAutoPlay.js +2 -0
  28. package/lib/commonjs/hooks/useAutoPlay.js.map +1 -0
  29. package/lib/commonjs/hooks/useCarouselController.js +2 -0
  30. package/lib/commonjs/hooks/useCarouselController.js.map +1 -0
  31. package/lib/commonjs/hooks/useCheckMounted.js +2 -0
  32. package/lib/commonjs/hooks/useCheckMounted.js.map +1 -0
  33. package/lib/commonjs/hooks/useCommonVariables.js +2 -0
  34. package/lib/commonjs/hooks/useCommonVariables.js.map +1 -0
  35. package/lib/commonjs/hooks/useInitProps.js +2 -0
  36. package/lib/commonjs/hooks/useInitProps.js.map +1 -0
  37. package/lib/commonjs/hooks/useLayoutConfig.js +2 -0
  38. package/lib/commonjs/hooks/useLayoutConfig.js.map +1 -0
  39. package/lib/commonjs/hooks/useOffsetX.js +2 -0
  40. package/lib/commonjs/hooks/useOffsetX.js.map +1 -0
  41. package/lib/commonjs/hooks/useOnProgressChange.js +2 -0
  42. package/lib/commonjs/hooks/useOnProgressChange.js.map +1 -0
  43. package/lib/commonjs/hooks/usePanGestureProxy.js +2 -0
  44. package/lib/commonjs/hooks/usePanGestureProxy.js.map +1 -0
  45. package/lib/commonjs/hooks/usePropsErrorBoundary.js +2 -0
  46. package/lib/commonjs/hooks/usePropsErrorBoundary.js.map +1 -0
  47. package/lib/commonjs/hooks/useSizeResolver.js +2 -0
  48. package/lib/commonjs/hooks/useSizeResolver.js.map +1 -0
  49. package/lib/commonjs/hooks/useUpdateGestureConfig.js +2 -0
  50. package/lib/commonjs/hooks/useUpdateGestureConfig.js.map +1 -0
  51. package/lib/commonjs/hooks/useVisibleRanges.js +2 -0
  52. package/lib/commonjs/hooks/useVisibleRanges.js.map +1 -0
  53. package/lib/commonjs/index.js +2 -0
  54. package/lib/commonjs/index.js.map +1 -0
  55. package/lib/commonjs/layouts/index.js +2 -0
  56. package/lib/commonjs/layouts/index.js.map +1 -0
  57. package/lib/commonjs/layouts/normal.js +2 -0
  58. package/lib/commonjs/layouts/normal.js.map +1 -0
  59. package/lib/commonjs/layouts/parallax.js +2 -0
  60. package/lib/commonjs/layouts/parallax.js.map +1 -0
  61. package/lib/commonjs/layouts/stack.js +2 -0
  62. package/lib/commonjs/layouts/stack.js.map +1 -0
  63. package/lib/commonjs/package.json +1 -0
  64. package/lib/commonjs/store/index.js +2 -0
  65. package/lib/commonjs/store/index.js.map +1 -0
  66. package/lib/commonjs/types.js +2 -0
  67. package/lib/commonjs/types.js.map +1 -0
  68. package/lib/commonjs/utils/compute-gesture-translation.js +2 -0
  69. package/lib/commonjs/utils/compute-gesture-translation.js.map +1 -0
  70. package/lib/commonjs/utils/compute-offset-if-data-changed.js +2 -0
  71. package/lib/commonjs/utils/compute-offset-if-data-changed.js.map +1 -0
  72. package/lib/commonjs/utils/compute-offset-if-size-changed.js +2 -0
  73. package/lib/commonjs/utils/compute-offset-if-size-changed.js.map +1 -0
  74. package/lib/commonjs/utils/compute-offset-if-sizes-changed.js +2 -0
  75. package/lib/commonjs/utils/compute-offset-if-sizes-changed.js.map +1 -0
  76. package/lib/commonjs/utils/computed-with-auto-fill-data.js +2 -0
  77. package/lib/commonjs/utils/computed-with-auto-fill-data.js.map +1 -0
  78. package/lib/commonjs/utils/deal-with-animation.js +2 -0
  79. package/lib/commonjs/utils/deal-with-animation.js.map +1 -0
  80. package/lib/commonjs/utils/handleroffset-direction.js +2 -0
  81. package/lib/commonjs/utils/handleroffset-direction.js.map +1 -0
  82. package/lib/commonjs/utils/log.js +2 -0
  83. package/lib/commonjs/utils/log.js.map +1 -0
  84. package/lib/commonjs/utils/sanitize-animation-style.js +2 -0
  85. package/lib/commonjs/utils/sanitize-animation-style.js.map +1 -0
  86. package/lib/commonjs/utils/size-resolver.js +2 -0
  87. package/lib/commonjs/utils/size-resolver.js.map +1 -0
  88. package/lib/module/components/Carousel.js +2 -0
  89. package/lib/module/components/Carousel.js.map +1 -0
  90. package/lib/module/components/CarouselLayout.js +2 -0
  91. package/lib/module/components/CarouselLayout.js.map +1 -0
  92. package/lib/module/components/ItemLayout.js +2 -0
  93. package/lib/module/components/ItemLayout.js.map +1 -0
  94. package/lib/module/components/ItemRenderer.js +2 -0
  95. package/lib/module/components/ItemRenderer.js.map +1 -0
  96. package/lib/module/components/LazyView.js +2 -0
  97. package/lib/module/components/LazyView.js.map +1 -0
  98. package/lib/module/components/Pagination/Basic/PaginationItem.js +2 -0
  99. package/lib/module/components/Pagination/Basic/PaginationItem.js.map +1 -0
  100. package/lib/module/components/Pagination/Basic/index.js +2 -0
  101. package/lib/module/components/Pagination/Basic/index.js.map +1 -0
  102. package/lib/module/components/Pagination/Custom/PaginationItem.js +2 -0
  103. package/lib/module/components/Pagination/Custom/PaginationItem.js.map +1 -0
  104. package/lib/module/components/Pagination/Custom/index.js +2 -0
  105. package/lib/module/components/Pagination/Custom/index.js.map +1 -0
  106. package/lib/module/components/Pagination/index.js +2 -0
  107. package/lib/module/components/Pagination/index.js.map +1 -0
  108. package/lib/module/components/ScrollViewGesture.js +2 -0
  109. package/lib/module/components/ScrollViewGesture.js.map +1 -0
  110. package/lib/module/constants/index.js +2 -0
  111. package/lib/module/constants/index.js.map +1 -0
  112. package/lib/module/hooks/useAutoPlay.js +2 -0
  113. package/lib/module/hooks/useAutoPlay.js.map +1 -0
  114. package/lib/module/hooks/useCarouselController.js +2 -0
  115. package/lib/module/hooks/useCarouselController.js.map +1 -0
  116. package/lib/module/hooks/useCheckMounted.js +2 -0
  117. package/lib/module/hooks/useCheckMounted.js.map +1 -0
  118. package/lib/module/hooks/useCommonVariables.js +2 -0
  119. package/lib/module/hooks/useCommonVariables.js.map +1 -0
  120. package/lib/module/hooks/useInitProps.js +2 -0
  121. package/lib/module/hooks/useInitProps.js.map +1 -0
  122. package/lib/module/hooks/useLayoutConfig.js +2 -0
  123. package/lib/module/hooks/useLayoutConfig.js.map +1 -0
  124. package/lib/module/hooks/useOffsetX.js +2 -0
  125. package/lib/module/hooks/useOffsetX.js.map +1 -0
  126. package/lib/module/hooks/useOnProgressChange.js +2 -0
  127. package/lib/module/hooks/useOnProgressChange.js.map +1 -0
  128. package/lib/module/hooks/usePanGestureProxy.js +2 -0
  129. package/lib/module/hooks/usePanGestureProxy.js.map +1 -0
  130. package/lib/module/hooks/usePropsErrorBoundary.js +2 -0
  131. package/lib/module/hooks/usePropsErrorBoundary.js.map +1 -0
  132. package/lib/module/hooks/useSizeResolver.js +2 -0
  133. package/lib/module/hooks/useSizeResolver.js.map +1 -0
  134. package/lib/module/hooks/useUpdateGestureConfig.js +2 -0
  135. package/lib/module/hooks/useUpdateGestureConfig.js.map +1 -0
  136. package/lib/module/hooks/useVisibleRanges.js +2 -0
  137. package/lib/module/hooks/useVisibleRanges.js.map +1 -0
  138. package/lib/module/index.js +2 -0
  139. package/lib/module/index.js.map +1 -0
  140. package/lib/module/layouts/index.js +2 -0
  141. package/lib/module/layouts/index.js.map +1 -0
  142. package/lib/module/layouts/normal.js +2 -0
  143. package/lib/module/layouts/normal.js.map +1 -0
  144. package/lib/module/layouts/parallax.js +2 -0
  145. package/lib/module/layouts/parallax.js.map +1 -0
  146. package/lib/module/layouts/stack.js +2 -0
  147. package/lib/module/layouts/stack.js.map +1 -0
  148. package/lib/module/store/index.js +2 -0
  149. package/lib/module/store/index.js.map +1 -0
  150. package/lib/module/types.js +2 -0
  151. package/lib/module/types.js.map +1 -0
  152. package/lib/module/utils/compute-gesture-translation.js +2 -0
  153. package/lib/module/utils/compute-gesture-translation.js.map +1 -0
  154. package/lib/module/utils/compute-offset-if-data-changed.js +2 -0
  155. package/lib/module/utils/compute-offset-if-data-changed.js.map +1 -0
  156. package/lib/module/utils/compute-offset-if-size-changed.js +2 -0
  157. package/lib/module/utils/compute-offset-if-size-changed.js.map +1 -0
  158. package/lib/module/utils/compute-offset-if-sizes-changed.js +2 -0
  159. package/lib/module/utils/compute-offset-if-sizes-changed.js.map +1 -0
  160. package/lib/module/utils/computed-with-auto-fill-data.js +2 -0
  161. package/lib/module/utils/computed-with-auto-fill-data.js.map +1 -0
  162. package/lib/module/utils/deal-with-animation.js +2 -0
  163. package/lib/module/utils/deal-with-animation.js.map +1 -0
  164. package/lib/module/utils/handleroffset-direction.js +2 -0
  165. package/lib/module/utils/handleroffset-direction.js.map +1 -0
  166. package/lib/module/utils/log.js +2 -0
  167. package/lib/module/utils/log.js.map +1 -0
  168. package/lib/module/utils/sanitize-animation-style.js +2 -0
  169. package/lib/module/utils/sanitize-animation-style.js.map +1 -0
  170. package/lib/module/utils/size-resolver.js +2 -0
  171. package/lib/module/utils/size-resolver.js.map +1 -0
  172. package/lib/typescript/components/Carousel.d.ts +8 -0
  173. package/lib/typescript/components/Carousel.d.ts.map +1 -0
  174. package/lib/typescript/components/CarouselLayout.d.ts +6 -0
  175. package/lib/typescript/components/CarouselLayout.d.ts.map +1 -0
  176. package/lib/typescript/components/ItemLayout.d.ts +15 -0
  177. package/lib/typescript/components/ItemLayout.d.ts.map +1 -0
  178. package/lib/typescript/components/ItemRenderer.d.ts +24 -0
  179. package/lib/typescript/components/ItemRenderer.d.ts.map +1 -0
  180. package/lib/typescript/components/LazyView.d.ts +8 -0
  181. package/lib/typescript/components/LazyView.d.ts.map +1 -0
  182. package/lib/typescript/components/Pagination/Basic/PaginationItem.d.ts +29 -0
  183. package/lib/typescript/components/Pagination/Basic/PaginationItem.d.ts.map +1 -0
  184. package/lib/typescript/components/Pagination/Basic/index.d.ts +23 -0
  185. package/lib/typescript/components/Pagination/Basic/index.d.ts.map +1 -0
  186. package/lib/typescript/components/Pagination/Custom/PaginationItem.d.ts +35 -0
  187. package/lib/typescript/components/Pagination/Custom/PaginationItem.d.ts.map +1 -0
  188. package/lib/typescript/components/Pagination/Custom/index.d.ts +26 -0
  189. package/lib/typescript/components/Pagination/Custom/index.d.ts.map +1 -0
  190. package/lib/typescript/components/Pagination/index.d.ts +5 -0
  191. package/lib/typescript/components/Pagination/index.d.ts.map +1 -0
  192. package/lib/typescript/components/ScrollViewGesture.d.ts +19 -0
  193. package/lib/typescript/components/ScrollViewGesture.d.ts.map +1 -0
  194. package/lib/typescript/constants/index.d.ts +9 -0
  195. package/lib/typescript/constants/index.d.ts.map +1 -0
  196. package/lib/typescript/hooks/useAutoPlay.d.ts +12 -0
  197. package/lib/typescript/hooks/useAutoPlay.d.ts.map +1 -0
  198. package/lib/typescript/hooks/useCarouselController.d.ts +28 -0
  199. package/lib/typescript/hooks/useCarouselController.d.ts.map +1 -0
  200. package/lib/typescript/hooks/useCheckMounted.d.ts +3 -0
  201. package/lib/typescript/hooks/useCheckMounted.d.ts.map +1 -0
  202. package/lib/typescript/hooks/useCommonVariables.d.ts +13 -0
  203. package/lib/typescript/hooks/useCommonVariables.d.ts.map +1 -0
  204. package/lib/typescript/hooks/useInitProps.d.ts +17 -0
  205. package/lib/typescript/hooks/useInitProps.d.ts.map +1 -0
  206. package/lib/typescript/hooks/useLayoutConfig.d.ts +10 -0
  207. package/lib/typescript/hooks/useLayoutConfig.d.ts.map +1 -0
  208. package/lib/typescript/hooks/useOffsetX.d.ts +24 -0
  209. package/lib/typescript/hooks/useOffsetX.d.ts.map +1 -0
  210. package/lib/typescript/hooks/useOnProgressChange.d.ts +14 -0
  211. package/lib/typescript/hooks/useOnProgressChange.d.ts.map +1 -0
  212. package/lib/typescript/hooks/usePanGestureProxy.d.ts +10 -0
  213. package/lib/typescript/hooks/usePanGestureProxy.d.ts.map +1 -0
  214. package/lib/typescript/hooks/usePropsErrorBoundary.d.ts +5 -0
  215. package/lib/typescript/hooks/usePropsErrorBoundary.d.ts.map +1 -0
  216. package/lib/typescript/hooks/useSizeResolver.d.ts +27 -0
  217. package/lib/typescript/hooks/useSizeResolver.d.ts.map +1 -0
  218. package/lib/typescript/hooks/useUpdateGestureConfig.d.ts +6 -0
  219. package/lib/typescript/hooks/useUpdateGestureConfig.d.ts.map +1 -0
  220. package/lib/typescript/hooks/useVisibleRanges.d.ts +23 -0
  221. package/lib/typescript/hooks/useVisibleRanges.d.ts.map +1 -0
  222. package/lib/typescript/index.d.ts +7 -0
  223. package/lib/typescript/index.d.ts.map +1 -0
  224. package/lib/typescript/layouts/index.d.ts +11 -0
  225. package/lib/typescript/layouts/index.d.ts.map +1 -0
  226. package/lib/typescript/layouts/normal.d.ts +16 -0
  227. package/lib/typescript/layouts/normal.d.ts.map +1 -0
  228. package/lib/typescript/layouts/parallax.d.ts +50 -0
  229. package/lib/typescript/layouts/parallax.d.ts.map +1 -0
  230. package/lib/typescript/layouts/stack.d.ts +38 -0
  231. package/lib/typescript/layouts/stack.d.ts.map +1 -0
  232. package/lib/typescript/store/index.d.ts +38 -0
  233. package/lib/typescript/store/index.d.ts.map +1 -0
  234. package/lib/typescript/types.d.ts +326 -0
  235. package/lib/typescript/types.d.ts.map +1 -0
  236. package/lib/typescript/utils/compute-gesture-translation.d.ts +9 -0
  237. package/lib/typescript/utils/compute-gesture-translation.d.ts.map +1 -0
  238. package/lib/typescript/utils/compute-offset-if-data-changed.d.ts +9 -0
  239. package/lib/typescript/utils/compute-offset-if-data-changed.d.ts.map +1 -0
  240. package/lib/typescript/utils/compute-offset-if-size-changed.d.ts +6 -0
  241. package/lib/typescript/utils/compute-offset-if-size-changed.d.ts.map +1 -0
  242. package/lib/typescript/utils/compute-offset-if-sizes-changed.d.ts +14 -0
  243. package/lib/typescript/utils/compute-offset-if-sizes-changed.d.ts.map +1 -0
  244. package/lib/typescript/utils/computed-with-auto-fill-data.d.ts +23 -0
  245. package/lib/typescript/utils/computed-with-auto-fill-data.d.ts.map +1 -0
  246. package/lib/typescript/utils/deal-with-animation.d.ts +3 -0
  247. package/lib/typescript/utils/deal-with-animation.d.ts.map +1 -0
  248. package/lib/typescript/utils/handleroffset-direction.d.ts +4 -0
  249. package/lib/typescript/utils/handleroffset-direction.d.ts.map +1 -0
  250. package/lib/typescript/utils/log.d.ts +7 -0
  251. package/lib/typescript/utils/log.d.ts.map +1 -0
  252. package/lib/typescript/utils/sanitize-animation-style.d.ts +3 -0
  253. package/lib/typescript/utils/sanitize-animation-style.d.ts.map +1 -0
  254. package/lib/typescript/utils/size-resolver.d.ts +87 -0
  255. package/lib/typescript/utils/size-resolver.d.ts.map +1 -0
  256. package/package.json +151 -0
  257. package/src/components/Carousel.test.tsx +1153 -0
  258. package/src/components/Carousel.tsx +35 -0
  259. package/src/components/CarouselLayout.tsx +231 -0
  260. package/src/components/ItemLayout.tsx +217 -0
  261. package/src/components/ItemRenderer.tsx +114 -0
  262. package/src/components/LazyView.test.tsx +61 -0
  263. package/src/components/LazyView.tsx +14 -0
  264. package/src/components/Pagination/Basic/PaginationItem.tsx +149 -0
  265. package/src/components/Pagination/Basic/index.tsx +98 -0
  266. package/src/components/Pagination/Custom/PaginationItem.tsx +166 -0
  267. package/src/components/Pagination/Custom/index.tsx +111 -0
  268. package/src/components/Pagination/Pagination.test.tsx +178 -0
  269. package/src/components/Pagination/index.tsx +7 -0
  270. package/src/components/ScrollViewGesture.tsx +577 -0
  271. package/src/components/rnr-demo.test.tsx +53 -0
  272. package/src/constants/index.ts +11 -0
  273. package/src/hooks/useAutoPlay.test.ts +194 -0
  274. package/src/hooks/useAutoPlay.ts +58 -0
  275. package/src/hooks/useCarouselController.test.tsx +1158 -0
  276. package/src/hooks/useCarouselController.tsx +525 -0
  277. package/src/hooks/useCheckMounted.test.ts +47 -0
  278. package/src/hooks/useCheckMounted.ts +14 -0
  279. package/src/hooks/useCommonVariables.test.tsx +384 -0
  280. package/src/hooks/useCommonVariables.ts +202 -0
  281. package/src/hooks/useInitProps.test.tsx +134 -0
  282. package/src/hooks/useInitProps.ts +111 -0
  283. package/src/hooks/useLayoutConfig.test.tsx +247 -0
  284. package/src/hooks/useLayoutConfig.ts +30 -0
  285. package/src/hooks/useOffsetX.test.ts +110 -0
  286. package/src/hooks/useOffsetX.ts +109 -0
  287. package/src/hooks/useOnProgressChange.test.tsx +207 -0
  288. package/src/hooks/useOnProgressChange.ts +105 -0
  289. package/src/hooks/usePanGestureProxy.test.tsx +368 -0
  290. package/src/hooks/usePanGestureProxy.ts +144 -0
  291. package/src/hooks/usePropsErrorBoundary.ts +138 -0
  292. package/src/hooks/useSizeResolver.test.tsx +112 -0
  293. package/src/hooks/useSizeResolver.ts +106 -0
  294. package/src/hooks/useUpdateGestureConfig.test.ts +89 -0
  295. package/src/hooks/useUpdateGestureConfig.ts +14 -0
  296. package/src/hooks/useVisibleRanges.test.tsx +366 -0
  297. package/src/hooks/useVisibleRanges.tsx +123 -0
  298. package/src/index.tsx +13 -0
  299. package/src/layouts/index.tsx +12 -0
  300. package/src/layouts/normal.ts +32 -0
  301. package/src/layouts/parallax.test.ts +239 -0
  302. package/src/layouts/parallax.ts +83 -0
  303. package/src/layouts/stack.test.ts +252 -0
  304. package/src/layouts/stack.ts +306 -0
  305. package/src/store/index.test.tsx +314 -0
  306. package/src/store/index.tsx +66 -0
  307. package/src/types.ts +348 -0
  308. package/src/utils/compute-gesture-translation.test.ts +70 -0
  309. package/src/utils/compute-gesture-translation.ts +29 -0
  310. package/src/utils/compute-offset-if-data-changed.test.ts +133 -0
  311. package/src/utils/compute-offset-if-data-changed.ts +44 -0
  312. package/src/utils/compute-offset-if-size-changed.test.ts +78 -0
  313. package/src/utils/compute-offset-if-size-changed.ts +14 -0
  314. package/src/utils/compute-offset-if-sizes-changed.test.ts +74 -0
  315. package/src/utils/compute-offset-if-sizes-changed.ts +44 -0
  316. package/src/utils/computed-with-auto-fill-data.test.ts +298 -0
  317. package/src/utils/computed-with-auto-fill-data.ts +92 -0
  318. package/src/utils/deal-with-animation.test.ts +181 -0
  319. package/src/utils/deal-with-animation.ts +17 -0
  320. package/src/utils/handleroffset-direction.test.ts +124 -0
  321. package/src/utils/handleroffset-direction.ts +18 -0
  322. package/src/utils/index.test.ts +90 -0
  323. package/src/utils/log.test.ts +134 -0
  324. package/src/utils/log.ts +12 -0
  325. package/src/utils/sanitize-animation-style.test.ts +40 -0
  326. package/src/utils/sanitize-animation-style.ts +20 -0
  327. package/src/utils/size-resolver.test.ts +193 -0
  328. package/src/utils/size-resolver.ts +216 -0
@@ -0,0 +1,35 @@
1
+ import React from "react";
2
+ import { useCommonVariables } from "../hooks/useCommonVariables";
3
+ import { useInitProps } from "../hooks/useInitProps";
4
+ import { usePropsErrorBoundary } from "../hooks/usePropsErrorBoundary";
5
+ import { useSizeResolver } from "../hooks/useSizeResolver";
6
+ import { GlobalStateProvider } from "../store";
7
+ import type { ICarouselInstance, TCarouselProps } from "../types";
8
+ import { CarouselLayout } from "./CarouselLayout";
9
+
10
+ const Carousel = React.forwardRef<ICarouselInstance, TCarouselProps<any>>((_props, ref) => {
11
+ const props = useInitProps(_props);
12
+ const { dataLength, getItemSize } = props;
13
+ const commonVariables = useCommonVariables(props);
14
+ usePropsErrorBoundary({ ...props, dataLength });
15
+
16
+ const sizeResolver = useSizeResolver({
17
+ dataLength,
18
+ getItemSize,
19
+ uniformSize: commonVariables.resolvedSize,
20
+ });
21
+
22
+ return (
23
+ <GlobalStateProvider value={{ props, common: commonVariables, sizeResolver }}>
24
+ <CarouselLayout ref={ref} />
25
+ </GlobalStateProvider>
26
+ );
27
+ });
28
+
29
+ type CarouselComponent = <T>(
30
+ props: React.PropsWithChildren<TCarouselProps<T>> & {
31
+ ref?: React.Ref<ICarouselInstance>;
32
+ }
33
+ ) => React.ReactElement;
34
+
35
+ export default Carousel as CarouselComponent;
@@ -0,0 +1,231 @@
1
+ import React from "react";
2
+ import { StyleSheet, type ViewStyle } from "react-native";
3
+ import { GestureHandlerRootView } from "react-native-gesture-handler";
4
+ import { useAnimatedReaction, useAnimatedStyle, useDerivedValue } from "react-native-reanimated";
5
+ import { scheduleOnRN } from "react-native-worklets";
6
+ import { useAutoPlay } from "../hooks/useAutoPlay";
7
+ import { useCarouselController } from "../hooks/useCarouselController";
8
+ import { useLayoutConfig } from "../hooks/useLayoutConfig";
9
+ import { useOnProgressChange } from "../hooks/useOnProgressChange";
10
+ import { useGlobalState } from "../store";
11
+ import { ICarouselInstance } from "../types";
12
+ import { computedRealIndexWithAutoFillData } from "../utils/computed-with-auto-fill-data";
13
+ import { ItemRenderer } from "./ItemRenderer";
14
+ import { ScrollViewGesture } from "./ScrollViewGesture";
15
+
16
+ export type TAnimationStyle = (value: number) => ViewStyle;
17
+
18
+ export const CarouselLayout = React.forwardRef<ICarouselInstance>((_props, ref) => {
19
+ const { props, common, sizeResolver } = useGlobalState();
20
+
21
+ const {
22
+ testID,
23
+ loop,
24
+ autoFillData,
25
+ // Fill data with autoFillData
26
+ data,
27
+ // Length of fill data
28
+ dataLength,
29
+ // Length of raw data
30
+ rawDataLength,
31
+ mode,
32
+ style,
33
+ contentContainerStyle,
34
+ vertical,
35
+ autoPlay,
36
+ windowSize,
37
+ autoPlayReverse,
38
+ autoPlayInterval,
39
+ scrollAnimationDuration,
40
+ withAnimation,
41
+ fixedDirection,
42
+ renderItem,
43
+ onScrollEnd,
44
+ onSnapToItem,
45
+ onScrollStart,
46
+ onProgressChange,
47
+ customAnimation,
48
+ defaultIndex,
49
+ variableSize,
50
+ } = props;
51
+
52
+ const { size, handlerOffset, resolvedSize, sizePhase } = common;
53
+ const layoutConfig = useLayoutConfig({ ...props, size, sizeResolver });
54
+
55
+ const isSizeReady = useDerivedValue(() => {
56
+ if (variableSize) return sizeResolver.total.value > 0;
57
+ const currentSize = resolvedSize.value ?? 0;
58
+ return sizePhase.value === "ready" && currentSize > 0;
59
+ }, [resolvedSize, sizePhase, variableSize, sizeResolver]);
60
+
61
+ const offsetX = useDerivedValue(() => {
62
+ const totalSize = variableSize
63
+ ? sizeResolver.total.value
64
+ : (resolvedSize.value ?? 0) * dataLength;
65
+ if (totalSize <= 0) return 0;
66
+
67
+ const value = handlerOffset.value;
68
+ if (!loop || totalSize === 0) {
69
+ return value;
70
+ }
71
+
72
+ const x = value % totalSize;
73
+ return Number.isNaN(x) ? 0 : x;
74
+ }, [loop, dataLength, handlerOffset, resolvedSize, variableSize, sizeResolver]);
75
+
76
+ useOnProgressChange({
77
+ autoFillData,
78
+ loop,
79
+ size,
80
+ sizeReady: isSizeReady,
81
+ offsetX,
82
+ rawDataLength,
83
+ onProgressChange,
84
+ sizeResolver,
85
+ variableSize,
86
+ });
87
+
88
+ const carouselController = useCarouselController({
89
+ ref,
90
+ loop,
91
+ size,
92
+ dataLength,
93
+ autoFillData,
94
+ handlerOffset,
95
+ withAnimation,
96
+ defaultIndex,
97
+ fixedDirection,
98
+ duration: scrollAnimationDuration,
99
+ onScrollEnd: () => scheduleOnRN(_onScrollEnd),
100
+ onScrollStart: () => !!onScrollStart && scheduleOnRN(onScrollStart),
101
+ });
102
+
103
+ const {
104
+ getSharedIndex,
105
+ // index, // Animated index. Could be used for dynamic dimension
106
+ } = carouselController;
107
+
108
+ const _onScrollEnd = React.useCallback(() => {
109
+ const _sharedIndex = Math.round(getSharedIndex());
110
+
111
+ const realIndex = computedRealIndexWithAutoFillData({
112
+ index: _sharedIndex,
113
+ dataLength: rawDataLength,
114
+ loop,
115
+ autoFillData,
116
+ });
117
+
118
+ if (onSnapToItem) onSnapToItem(realIndex);
119
+
120
+ if (onScrollEnd) onScrollEnd(realIndex);
121
+ }, [loop, autoFillData, rawDataLength, getSharedIndex, onSnapToItem, onScrollEnd]);
122
+
123
+ const {
124
+ start: startAutoPlay,
125
+ pause: pauseAutoPlay,
126
+ trigger: triggerAutoPlay,
127
+ } = useAutoPlay({
128
+ autoPlay,
129
+ autoPlayInterval,
130
+ autoPlayReverse,
131
+ carouselController,
132
+ });
133
+
134
+ useAnimatedReaction(
135
+ () => ({ ready: isSizeReady.value }),
136
+ (state, previous) => {
137
+ if (!autoPlay) return;
138
+ if (state.ready === previous?.ready) return;
139
+
140
+ if (state.ready) scheduleOnRN(triggerAutoPlay);
141
+ else scheduleOnRN(pauseAutoPlay);
142
+ },
143
+ [autoPlay]
144
+ );
145
+
146
+ const scrollViewGestureOnScrollStart = React.useCallback(() => {
147
+ pauseAutoPlay();
148
+ onScrollStart?.();
149
+ }, [onScrollStart, pauseAutoPlay]);
150
+
151
+ const scrollViewGestureOnScrollEnd = React.useCallback(() => {
152
+ startAutoPlay();
153
+ _onScrollEnd();
154
+ }, [_onScrollEnd, startAutoPlay]);
155
+
156
+ const scrollViewGestureOnTouchBegin = React.useCallback(pauseAutoPlay, [pauseAutoPlay]);
157
+
158
+ const scrollViewGestureOnTouchEnd = React.useCallback(startAutoPlay, [startAutoPlay]);
159
+
160
+ const { opacity, transform, ...restContentContainerStyle } =
161
+ StyleSheet.flatten(contentContainerStyle) || {};
162
+ const flattenedStyle = StyleSheet.flatten(style) || {};
163
+
164
+ const layoutStyle = useAnimatedStyle(() => {
165
+ const { width, height } = flattenedStyle;
166
+ const measuredSize = resolvedSize.value ?? 0;
167
+
168
+ const computedWidth = width ?? (vertical ? "100%" : measuredSize || "100%");
169
+ const computedHeight = height ?? (vertical ? measuredSize || "100%" : "100%");
170
+
171
+ return {
172
+ width: computedWidth,
173
+ height: computedHeight,
174
+ opacity: isSizeReady.value ? 1 : 0,
175
+ };
176
+ }, [flattenedStyle, isSizeReady, vertical, resolvedSize, sizePhase]);
177
+
178
+ return (
179
+ <GestureHandlerRootView testID={testID} style={[styles.layoutContainer, style]}>
180
+ <ScrollViewGesture
181
+ size={size}
182
+ key={mode}
183
+ translation={handlerOffset}
184
+ style={[
185
+ styles.contentContainer,
186
+ layoutStyle,
187
+ restContentContainerStyle,
188
+ vertical ? styles.itemsVertical : styles.itemsHorizontal,
189
+ ]}
190
+ testID="carousel-content-container"
191
+ onLayout={props.onLayout}
192
+ onScrollStart={scrollViewGestureOnScrollStart}
193
+ onScrollEnd={scrollViewGestureOnScrollEnd}
194
+ onTouchBegin={scrollViewGestureOnTouchBegin}
195
+ onTouchEnd={scrollViewGestureOnTouchEnd}
196
+ >
197
+ <ItemRenderer
198
+ data={data}
199
+ dataLength={dataLength}
200
+ rawDataLength={rawDataLength}
201
+ loop={loop}
202
+ size={size}
203
+ windowSize={windowSize}
204
+ autoFillData={autoFillData}
205
+ offsetX={offsetX}
206
+ handlerOffset={handlerOffset}
207
+ layoutConfig={layoutConfig}
208
+ renderItem={renderItem}
209
+ customAnimation={customAnimation}
210
+ sizeResolver={sizeResolver}
211
+ />
212
+ </ScrollViewGesture>
213
+ </GestureHandlerRootView>
214
+ );
215
+ });
216
+
217
+ const styles = StyleSheet.create({
218
+ layoutContainer: {
219
+ display: "flex",
220
+ overflow: "hidden",
221
+ },
222
+ contentContainer: {
223
+ overflow: "hidden",
224
+ },
225
+ itemsHorizontal: {
226
+ flexDirection: "row",
227
+ },
228
+ itemsVertical: {
229
+ flexDirection: "column",
230
+ },
231
+ });
@@ -0,0 +1,217 @@
1
+ import React from "react";
2
+ import type { LayoutChangeEvent, ViewStyle } from "react-native";
3
+ import { StyleSheet } from "react-native";
4
+ import type { SharedValue } from "react-native-reanimated";
5
+ import Animated, {
6
+ useAnimatedStyle,
7
+ useDerivedValue,
8
+ useSharedValue,
9
+ } from "react-native-reanimated";
10
+ import { scheduleOnUI } from "react-native-worklets";
11
+
12
+ import type { IOpts } from "../hooks/useOffsetX";
13
+ import { useOffsetX } from "../hooks/useOffsetX";
14
+ import type { IVisibleRanges } from "../hooks/useVisibleRanges";
15
+ import type { ILayoutConfig } from "../layouts/stack";
16
+ import { useGlobalState } from "../store";
17
+ import type { TCarouselProps } from "../types";
18
+ import { sanitizeAnimationStyle } from "../utils/sanitize-animation-style";
19
+
20
+ export type TAnimationStyle = NonNullable<TCarouselProps["customAnimation"]>;
21
+
22
+ export const ItemLayout: React.FC<{
23
+ index: number;
24
+ handlerOffset: SharedValue<number>;
25
+ visibleRanges: IVisibleRanges;
26
+ animationStyle: TAnimationStyle;
27
+ children: (ctx: {
28
+ animationValue: SharedValue<number>;
29
+ }) => React.ReactElement;
30
+ }> = (props) => {
31
+ const { handlerOffset, index, children, visibleRanges, animationStyle } = props;
32
+
33
+ const {
34
+ props: {
35
+ loop,
36
+ dataLength,
37
+ width,
38
+ height,
39
+ vertical,
40
+ customConfig,
41
+ mode,
42
+ modeConfig,
43
+ style,
44
+ itemWidth,
45
+ itemHeight,
46
+ variableSize,
47
+ },
48
+ common,
49
+ sizeResolver,
50
+ layout: { updateItemDimensions },
51
+ } = useGlobalState();
52
+
53
+ const measuredSize = useSharedValue<{ width: number | null; height: number | null }>({
54
+ width: null,
55
+ height: null,
56
+ });
57
+
58
+ const fallbackSize = common.size;
59
+ // Prefer size from `style` (v5), then fallback to deprecated `width`/`height` for v4 compatibility.
60
+ const { width: styleWidth, height: styleHeight } = StyleSheet.flatten(style) || {};
61
+ const styleWidthNumber = typeof styleWidth === "number" ? styleWidth : undefined;
62
+ const styleHeightNumber = typeof styleHeight === "number" ? styleHeight : undefined;
63
+
64
+ // Variable-size mode reads each item's size from the resolver up-front; the
65
+ // measurement plumbing below is bypassed so onLayout never overrides the
66
+ // user's declaration.
67
+ const variableItemSize = variableSize ? sizeResolver.itemSize(index) : undefined;
68
+
69
+ // When itemWidth/itemHeight is provided, use it for item dimensions (not container style)
70
+ const explicitItemSize = vertical ? itemHeight : itemWidth;
71
+ const explicitAxisSize = vertical ? (styleHeightNumber ?? height) : (styleWidthNumber ?? width);
72
+ // Variable mode → per-item size; uniform fallback to itemWidth/Height or container.
73
+ const size = (variableItemSize ?? explicitItemSize ?? explicitAxisSize ?? fallbackSize) || 0;
74
+ const effectivePageSize = size > 0 ? size : undefined;
75
+
76
+ const dimensionsStyle = useAnimatedStyle<ViewStyle>(() => {
77
+ if (variableSize) {
78
+ const itemPx = sizeResolver.itemSize(index);
79
+ const w = vertical ? (typeof width === "number" ? width : "100%") : itemPx;
80
+ const h = vertical ? itemPx : typeof height === "number" ? height : "100%";
81
+ return { width: w, height: h };
82
+ }
83
+ // When itemWidth/itemHeight is provided, use it for item width/height
84
+ const widthCandidate = vertical ? width : (explicitItemSize ?? explicitAxisSize);
85
+ const heightCandidate = vertical ? (explicitItemSize ?? explicitAxisSize) : height;
86
+
87
+ const computedWidth =
88
+ typeof widthCandidate === "number"
89
+ ? widthCandidate
90
+ : (measuredSize.value.width ?? (vertical ? "100%" : (effectivePageSize ?? "100%")));
91
+
92
+ const computedHeight =
93
+ typeof heightCandidate === "number"
94
+ ? heightCandidate
95
+ : (measuredSize.value.height ?? (vertical ? (effectivePageSize ?? "100%") : "100%"));
96
+
97
+ return {
98
+ width: computedWidth,
99
+ height: computedHeight,
100
+ };
101
+ }, [
102
+ vertical,
103
+ width,
104
+ height,
105
+ explicitAxisSize,
106
+ explicitItemSize,
107
+ effectivePageSize,
108
+ variableSize,
109
+ sizeResolver,
110
+ index,
111
+ ]);
112
+
113
+ let offsetXConfig: IOpts = {
114
+ handlerOffset,
115
+ index,
116
+ size,
117
+ dataLength,
118
+ loop,
119
+ resolver: variableSize ? sizeResolver : undefined,
120
+ ...(typeof customConfig === "function" ? customConfig() : {}),
121
+ };
122
+
123
+ if (mode === "horizontal-stack") {
124
+ const { snapDirection, showLength } = modeConfig as ILayoutConfig;
125
+
126
+ offsetXConfig = {
127
+ handlerOffset,
128
+ index,
129
+ size,
130
+ dataLength,
131
+ loop,
132
+ type: snapDirection === "right" ? "negative" : "positive",
133
+ viewCount: showLength,
134
+ resolver: variableSize ? sizeResolver : undefined,
135
+ };
136
+ }
137
+
138
+ const x = useOffsetX(offsetXConfig, visibleRanges);
139
+ const animationValue = useDerivedValue(() => {
140
+ // In variable mode each item normalises `x` by its own size, so the
141
+ // animation `value` keeps the same [-1, 0, 1] meaning every item has in
142
+ // uniform mode (-1 = one item-width left of center).
143
+ const itemSize = variableSize ? sizeResolver.itemSize(index) : size;
144
+ if (!itemSize) return 0;
145
+ return x.value / itemSize;
146
+ }, [x, size, variableSize, sizeResolver, index]);
147
+ const animatedStyle = useAnimatedStyle<ViewStyle>(() => {
148
+ const itemSize = variableSize ? sizeResolver.itemSize(index) : size;
149
+ const safeSize = itemSize || 1;
150
+ return sanitizeAnimationStyle(animationStyle(x.value / safeSize, index));
151
+ }, [animationStyle, index, x, size, variableSize, sizeResolver]);
152
+
153
+ // TODO: For dynamic dimension in the future
154
+ // function handleLayout(e: LayoutChangeEvent) {
155
+ // const { width, height } = e.nativeEvent.layout;
156
+ // updateItemDimensions(index, { width, height });
157
+ // }
158
+
159
+ const child = children({ animationValue });
160
+
161
+ type LayoutableProps = {
162
+ collapsable?: boolean;
163
+ onLayout?: (event: LayoutChangeEvent) => void;
164
+ };
165
+
166
+ const enhancedChild = React.isValidElement<LayoutableProps>(child)
167
+ ? variableSize
168
+ ? // Variable-size mode: per-item dimensions are authoritative (declared
169
+ // by getItemWidth/getItemHeight), so onLayout measurements must not
170
+ // overwrite them. Forward the user's original onLayout if any.
171
+ React.cloneElement(child, { collapsable: false })
172
+ : React.cloneElement(child, {
173
+ collapsable: false,
174
+ onLayout: (event: LayoutChangeEvent) => {
175
+ const { width: layoutWidth, height: layoutHeight } = event.nativeEvent.layout;
176
+ if (layoutWidth > 0 && layoutHeight > 0) {
177
+ scheduleOnUI(() => {
178
+ const { width: prevWidth, height: prevHeight } = measuredSize.value;
179
+ if (prevWidth === layoutWidth && prevHeight === layoutHeight) return;
180
+
181
+ measuredSize.value = {
182
+ width: layoutWidth,
183
+ height: layoutHeight,
184
+ };
185
+ updateItemDimensions(index, {
186
+ width: layoutWidth,
187
+ height: layoutHeight,
188
+ });
189
+ });
190
+ }
191
+
192
+ child.props?.onLayout?.(event);
193
+ },
194
+ })
195
+ : child;
196
+
197
+ return (
198
+ <Animated.View
199
+ style={[
200
+ {
201
+ position: "absolute",
202
+ pointerEvents: "box-none",
203
+ },
204
+ dimensionsStyle,
205
+ animatedStyle,
206
+ ]}
207
+ /**
208
+ * We use this testID to know when the carousel item is ready to be tested in test.
209
+ * e.g.
210
+ * The testID of first item will be changed to __CAROUSEL_ITEM_0_READY__ from __CAROUSEL_ITEM_0_NOT_READY__ when the item is ready.
211
+ * */
212
+ testID={`__CAROUSEL_ITEM_${index}__`}
213
+ >
214
+ {enhancedChild}
215
+ </Animated.View>
216
+ );
217
+ };
@@ -0,0 +1,114 @@
1
+ import React from "react";
2
+ import type { FC } from "react";
3
+ import type { ViewStyle } from "react-native";
4
+ import type { SharedValue } from "react-native-reanimated";
5
+ import { useAnimatedReaction } from "react-native-reanimated";
6
+ import { scheduleOnRN } from "react-native-worklets";
7
+
8
+ import type { TAnimationStyle } from "./ItemLayout";
9
+ import { ItemLayout } from "./ItemLayout";
10
+
11
+ import type { VisibleRanges } from "../hooks/useVisibleRanges";
12
+ import { useVisibleRanges } from "../hooks/useVisibleRanges";
13
+ import type { CarouselRenderItem } from "../types";
14
+ import { computedRealIndexWithAutoFillData } from "../utils/computed-with-auto-fill-data";
15
+ import type { SizeResolver } from "../utils/size-resolver";
16
+
17
+ interface Props {
18
+ data: any[];
19
+ dataLength: number;
20
+ rawDataLength: number;
21
+ loop: boolean;
22
+ size: number;
23
+ windowSize?: number;
24
+ autoFillData: boolean;
25
+ offsetX: SharedValue<number>;
26
+ handlerOffset: SharedValue<number>;
27
+ layoutConfig: TAnimationStyle;
28
+ renderItem: CarouselRenderItem<any>;
29
+ customAnimation?: (value: number, index: number) => ViewStyle;
30
+ sizeResolver: SizeResolver;
31
+ }
32
+
33
+ export const ItemRenderer: FC<Props> = (props) => {
34
+ const {
35
+ data,
36
+ size,
37
+ windowSize,
38
+ handlerOffset,
39
+ offsetX,
40
+ dataLength,
41
+ rawDataLength,
42
+ loop,
43
+ autoFillData,
44
+ layoutConfig,
45
+ renderItem,
46
+ customAnimation,
47
+ sizeResolver,
48
+ } = props;
49
+
50
+ const visibleRanges = useVisibleRanges({
51
+ total: dataLength,
52
+ viewSize: size,
53
+ translation: handlerOffset,
54
+ windowSize,
55
+ loop,
56
+ resolver: sizeResolver,
57
+ });
58
+
59
+ // Initialize with a sensible default to avoid blank render on first frame
60
+ const initialRanges: VisibleRanges = React.useMemo(
61
+ () => ({
62
+ negativeRange: [0, 0],
63
+ positiveRange: [0, Math.min(dataLength - 1, (windowSize ?? dataLength) - 1)],
64
+ }),
65
+ [dataLength, windowSize]
66
+ );
67
+
68
+ const [displayedItems, setDisplayedItems] = React.useState<VisibleRanges>(initialRanges);
69
+
70
+ useAnimatedReaction(
71
+ () => visibleRanges.value,
72
+ (ranges) => scheduleOnRN(setDisplayedItems, ranges),
73
+ [visibleRanges]
74
+ );
75
+
76
+ return (
77
+ <>
78
+ {data.map((item, index) => {
79
+ const realIndex = computedRealIndexWithAutoFillData({
80
+ index,
81
+ dataLength: rawDataLength,
82
+ loop,
83
+ autoFillData,
84
+ });
85
+
86
+ const { negativeRange, positiveRange } = displayedItems;
87
+
88
+ const shouldRender =
89
+ (index >= negativeRange[0] && index <= negativeRange[1]) ||
90
+ (index >= positiveRange[0] && index <= positiveRange[1]);
91
+
92
+ if (!shouldRender) return null;
93
+
94
+ return (
95
+ <ItemLayout
96
+ key={index}
97
+ index={index}
98
+ handlerOffset={offsetX}
99
+ visibleRanges={visibleRanges}
100
+ animationStyle={customAnimation || layoutConfig}
101
+ >
102
+ {({ animationValue }) =>
103
+ renderItem({
104
+ item,
105
+ index: realIndex,
106
+ animationValue,
107
+ })
108
+ }
109
+ </ItemLayout>
110
+ );
111
+ })}
112
+ </>
113
+ );
114
+ };
@@ -0,0 +1,61 @@
1
+ import { render } from "@testing-library/react-native";
2
+ import React from "react";
3
+ import { Text } from "react-native";
4
+
5
+ import { LazyView } from "./LazyView";
6
+
7
+ describe("LazyView", () => {
8
+ it("should render children when shouldUpdate is true", () => {
9
+ const { getByText } = render(
10
+ <LazyView shouldUpdate={true}>
11
+ <Text>Test Child</Text>
12
+ </LazyView>
13
+ );
14
+
15
+ expect(getByText("Test Child")).toBeTruthy();
16
+ });
17
+
18
+ it("should not render children when shouldUpdate is false", () => {
19
+ const { queryByText } = render(
20
+ <LazyView shouldUpdate={false}>
21
+ <Text>Test Child</Text>
22
+ </LazyView>
23
+ );
24
+
25
+ expect(queryByText("Test Child")).toBeNull();
26
+ });
27
+
28
+ it("should render empty fragment when shouldUpdate is false", () => {
29
+ const { toJSON } = render(
30
+ <LazyView shouldUpdate={false}>
31
+ <Text>Test Child</Text>
32
+ </LazyView>
33
+ );
34
+
35
+ expect(toJSON()).toBeNull();
36
+ });
37
+
38
+ it("should handle multiple children when shouldUpdate is true", () => {
39
+ const { getByText } = render(
40
+ <LazyView shouldUpdate={true}>
41
+ <Text>First Child</Text>
42
+ <Text>Second Child</Text>
43
+ </LazyView>
44
+ );
45
+
46
+ expect(getByText("First Child")).toBeTruthy();
47
+ expect(getByText("Second Child")).toBeTruthy();
48
+ });
49
+
50
+ it("should not render multiple children when shouldUpdate is false", () => {
51
+ const { queryByText } = render(
52
+ <LazyView shouldUpdate={false}>
53
+ <Text>First Child</Text>
54
+ <Text>Second Child</Text>
55
+ </LazyView>
56
+ );
57
+
58
+ expect(queryByText("First Child")).toBeNull();
59
+ expect(queryByText("Second Child")).toBeNull();
60
+ });
61
+ });
@@ -0,0 +1,14 @@
1
+ import type { PropsWithChildren } from "react";
2
+ import React from "react";
3
+
4
+ interface Props {
5
+ shouldUpdate: boolean;
6
+ }
7
+
8
+ export const LazyView: React.FC<PropsWithChildren<Props>> = (props) => {
9
+ const { shouldUpdate, children } = props;
10
+
11
+ if (!shouldUpdate) return <></>;
12
+
13
+ return <>{children}</>;
14
+ };