@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,1158 @@
1
+ import React from "react";
2
+ import { useSharedValue } from "react-native-reanimated";
3
+
4
+ import { act, renderHook } from "@testing-library/react-hooks";
5
+
6
+ import { useImperativeHandle, useRef } from "react";
7
+ import { View } from "react-native";
8
+ import { GlobalStateContext, IContext } from "../store";
9
+ import { ICarouselInstance } from "../types";
10
+ import { useCarouselController } from "./useCarouselController";
11
+ import { TCarouselSizePhase } from "./useCommonVariables";
12
+
13
+ // Mock Reanimated
14
+ jest.mock("react-native-reanimated", () => {
15
+ const mockAnimatedReaction = jest.fn((deps, cb) => {
16
+ const depsResult = deps();
17
+ cb(depsResult);
18
+ return () => {};
19
+ });
20
+
21
+ return {
22
+ useSharedValue: jest.fn((initialValue) => ({
23
+ value: initialValue,
24
+ })),
25
+ useDerivedValue: jest.fn((callback) => ({
26
+ value: callback(),
27
+ })),
28
+ useAnimatedReaction: mockAnimatedReaction,
29
+ withTiming: jest.fn((toValue, config, callback) => {
30
+ if (callback) callback(true);
31
+
32
+ return toValue;
33
+ }),
34
+ mockAnimatedReaction,
35
+ Easing: {
36
+ bezier: () => ({
37
+ factory: () => 0,
38
+ }),
39
+ },
40
+ };
41
+ });
42
+
43
+ jest.mock("react-native-worklets", () => {
44
+ const mockScheduleOnRN = jest.fn((fn, ...args) => fn(...args));
45
+ return {
46
+ scheduleOnRN: mockScheduleOnRN,
47
+ mockScheduleOnRN,
48
+ };
49
+ });
50
+
51
+ // Get mock functions for testing
52
+ const { mockAnimatedReaction } = jest.requireMock("react-native-reanimated");
53
+
54
+ const { mockScheduleOnRN } = jest.requireMock("react-native-worklets");
55
+ // Update the React mock to include useRef
56
+ jest.mock("react", () => {
57
+ const originalModule = jest.requireActual("react");
58
+ return {
59
+ ...originalModule,
60
+ useRef: jest.fn((initialValue) => ({ current: initialValue })),
61
+ useImperativeHandle: jest.fn((ref, createHandle) => createHandle()),
62
+ };
63
+ });
64
+
65
+ // Add mock for GlobalStateContext
66
+ const mockGlobalState: IContext = {
67
+ props: {
68
+ overscrollEnabled: true,
69
+ loop: true,
70
+ pagingEnabled: true,
71
+ snapEnabled: true,
72
+ enabled: true,
73
+ scrollAnimationDuration: 500,
74
+ withAnimation: undefined,
75
+ dataLength: 5,
76
+ data: Array.from({ length: 5 }, (_, i) => i),
77
+ width: 300,
78
+ height: 300,
79
+ renderItem: () => <View style={{ flex: 1 }} />,
80
+ autoFillData: false,
81
+ defaultIndex: 0,
82
+ autoPlayInterval: 0,
83
+ rawData: [],
84
+ rawDataLength: 0,
85
+ },
86
+ common: {
87
+ size: 300,
88
+ sizeExplicit: true,
89
+ validLength: 5,
90
+ handlerOffset: useSharedValue(0),
91
+ resolvedSize: useSharedValue<number | null>(300),
92
+ sizePhase: useSharedValue<TCarouselSizePhase>("ready"),
93
+ },
94
+ layout: {
95
+ // @ts-ignore
96
+ containerSize: { value: { width: 300, height: 300 } },
97
+ // @ts-ignore
98
+ itemDimensions: { value: {} },
99
+ updateItemDimensions: jest.fn(),
100
+ updateContainerSize: jest.fn(),
101
+ },
102
+ };
103
+
104
+ // Add wrapper for renderHook
105
+ const wrapper: React.FC<{ children: React.ReactNode }> = ({ children }) => (
106
+ <GlobalStateContext.Provider value={mockGlobalState}>{children}</GlobalStateContext.Provider>
107
+ );
108
+
109
+ describe("useCarouselController", () => {
110
+ let mockHandlerOffset: ReturnType<typeof useSharedValue<number>>;
111
+ let ref: ReturnType<typeof useRef>;
112
+ let defaultProps: any;
113
+
114
+ beforeEach(() => {
115
+ jest.clearAllMocks();
116
+ mockHandlerOffset = useSharedValue(0);
117
+ ref = useRef<ICarouselInstance>(null!);
118
+ defaultProps = {
119
+ ref,
120
+ size: 300,
121
+ loop: true,
122
+ dataLength: 5,
123
+ handlerOffset: mockHandlerOffset,
124
+ autoFillData: false,
125
+ duration: 300,
126
+ };
127
+
128
+ mockHandlerOffset.value = 0;
129
+ mockAnimatedReaction.mockImplementation((deps: () => any, cb: (depsResult: any) => void) => {
130
+ const depsResult = deps();
131
+ cb(depsResult);
132
+ return () => {};
133
+ });
134
+ });
135
+
136
+ it("should initialize with default index", () => {
137
+ mockHandlerOffset.value = -600; // size * 2
138
+ const { result } = renderHook(
139
+ () =>
140
+ useCarouselController({
141
+ ...defaultProps,
142
+ defaultIndex: 2,
143
+ }),
144
+ { wrapper }
145
+ );
146
+
147
+ expect(result.current.getCurrentIndex()).toBe(2);
148
+ });
149
+
150
+ it("should move to next slide", () => {
151
+ const { result } = renderHook(() => useCarouselController(defaultProps), { wrapper });
152
+
153
+ act(() => {
154
+ result.current.next();
155
+ });
156
+
157
+ expect(mockHandlerOffset.value).toBe(-300); // size * 1
158
+ });
159
+
160
+ it("should move to previous slide", () => {
161
+ const { result } = renderHook(() => useCarouselController(defaultProps), { wrapper });
162
+
163
+ act(() => {
164
+ result.current.prev();
165
+ });
166
+
167
+ expect(mockHandlerOffset.value).toBe(300); // size * -1
168
+ });
169
+
170
+ it("should handle loop behavior correctly", () => {
171
+ const { result } = renderHook(
172
+ () =>
173
+ useCarouselController({
174
+ ...defaultProps,
175
+ loop: true,
176
+ }),
177
+ { wrapper }
178
+ );
179
+
180
+ // Move to last slide
181
+ act(() => {
182
+ result.current.scrollTo({ index: 4 });
183
+ });
184
+
185
+ // Try to go next (should loop to first)
186
+ act(() => {
187
+ result.current.next();
188
+ });
189
+
190
+ expect(mockHandlerOffset.value).toBe(-1500); // size * 5
191
+ });
192
+
193
+ it("should prevent movement when loop is disabled and at bounds", () => {
194
+ const { result } = renderHook(
195
+ () =>
196
+ useCarouselController({
197
+ ...defaultProps,
198
+ loop: false,
199
+ }),
200
+ { wrapper }
201
+ );
202
+
203
+ // Try to go previous at start
204
+ act(() => {
205
+ result.current.prev();
206
+ });
207
+ expect(mockHandlerOffset.value).toBe(0);
208
+
209
+ // Go to end
210
+ act(() => {
211
+ result.current.scrollTo({ index: 4 });
212
+ });
213
+
214
+ // Try to go next at end
215
+ act(() => {
216
+ result.current.next();
217
+ });
218
+ expect(mockHandlerOffset.value).toBe(-1200); // size * 4
219
+ });
220
+
221
+ it("should scroll to specific index", () => {
222
+ const { result } = renderHook(() => useCarouselController(defaultProps), { wrapper });
223
+
224
+ act(() => {
225
+ result.current.scrollTo({ index: 3 });
226
+ });
227
+
228
+ expect(mockHandlerOffset.value).toBe(-900); // size * 3
229
+ });
230
+
231
+ it("should keep negative offsets when scrollTo() moves backward in non-loop mode", () => {
232
+ const { result } = renderHook(
233
+ () =>
234
+ useCarouselController({
235
+ ...defaultProps,
236
+ loop: false,
237
+ }),
238
+ { wrapper }
239
+ );
240
+
241
+ act(() => {
242
+ result.current.scrollTo({ index: 3, animated: false });
243
+ });
244
+ expect(mockHandlerOffset.value).toBe(-900);
245
+
246
+ act(() => {
247
+ result.current.scrollTo({ index: 2, animated: false });
248
+ });
249
+ expect(mockHandlerOffset.value).toBe(-600);
250
+
251
+ act(() => {
252
+ result.current.scrollTo({ index: 1, animated: false });
253
+ });
254
+ expect(mockHandlerOffset.value).toBe(-300);
255
+ });
256
+
257
+ it("should keep negative offsets when animated backward scrollTo() runs in non-loop mode", () => {
258
+ const onFinished = jest.fn();
259
+ const { result } = renderHook(
260
+ () =>
261
+ useCarouselController({
262
+ ...defaultProps,
263
+ loop: false,
264
+ }),
265
+ { wrapper }
266
+ );
267
+
268
+ act(() => {
269
+ result.current.scrollTo({ index: 3, animated: true });
270
+ });
271
+ expect(mockHandlerOffset.value).toBe(-900);
272
+
273
+ act(() => {
274
+ result.current.scrollTo({ index: 2, animated: true, onFinished });
275
+ });
276
+ expect(mockHandlerOffset.value).toBe(-600);
277
+ expect(onFinished).toHaveBeenCalled();
278
+ });
279
+
280
+ it("should map scrollTo({ index: 0 }) to zero offset from end in non-loop mode", () => {
281
+ const { result } = renderHook(
282
+ () =>
283
+ useCarouselController({
284
+ ...defaultProps,
285
+ loop: false,
286
+ }),
287
+ { wrapper }
288
+ );
289
+
290
+ act(() => {
291
+ result.current.scrollTo({ index: 4, animated: false });
292
+ });
293
+ expect(mockHandlerOffset.value).toBe(-1200);
294
+
295
+ act(() => {
296
+ result.current.scrollTo({ index: 0, animated: false });
297
+ });
298
+ expect(Math.abs(mockHandlerOffset.value)).toBe(0);
299
+ });
300
+
301
+ it("should handle animation callbacks", () => {
302
+ const onFinished = jest.fn();
303
+ const { result } = renderHook(() => useCarouselController(defaultProps), { wrapper });
304
+
305
+ act(() => {
306
+ result.current.next({
307
+ animated: true,
308
+ onFinished,
309
+ });
310
+ });
311
+
312
+ expect(onFinished).toHaveBeenCalled();
313
+ });
314
+
315
+ it("should respect animation duration", () => {
316
+ const { result } = renderHook(
317
+ () =>
318
+ useCarouselController({
319
+ ...defaultProps,
320
+ duration: 500,
321
+ }),
322
+ { wrapper }
323
+ );
324
+
325
+ const onFinished = jest.fn();
326
+ act(() => {
327
+ result.current.next({
328
+ animated: true,
329
+ onFinished,
330
+ });
331
+ });
332
+
333
+ expect(onFinished).toHaveBeenCalled();
334
+ });
335
+
336
+ it("should handle non-animated transitions", () => {
337
+ const { result } = renderHook(() => useCarouselController(defaultProps), { wrapper });
338
+
339
+ act(() => {
340
+ result.current.scrollTo({ index: 2, animated: false });
341
+ });
342
+
343
+ expect(mockHandlerOffset.value).toBe(-600); // size * 2
344
+ });
345
+
346
+ it("should handle multiple slide movements", () => {
347
+ const { result } = renderHook(() => useCarouselController(defaultProps), { wrapper });
348
+
349
+ act(() => {
350
+ result.current.next({ count: 2 });
351
+ });
352
+
353
+ expect(mockHandlerOffset.value).toBe(-600); // size * 2
354
+ });
355
+
356
+ it("should prevent overscroll when page size is smaller than container and overscroll is disabled", () => {
357
+ // Configure multi-item layout: page size 100, container width 300 (3 items per view)
358
+ mockGlobalState.props.overscrollEnabled = false;
359
+ mockGlobalState.props.loop = false;
360
+ mockGlobalState.common.size = 100;
361
+ mockGlobalState.common.resolvedSize.value = 100;
362
+ mockGlobalState.layout.containerSize.value = { width: 300, height: 300 };
363
+
364
+ // Simulate currently at index 3 (handlerOffset = -pageSize * 3)
365
+ mockHandlerOffset.value = -300;
366
+
367
+ const { result } = renderHook(
368
+ () =>
369
+ useCarouselController({
370
+ ...defaultProps,
371
+ loop: false,
372
+ size: 100,
373
+ dataLength: 5,
374
+ handlerOffset: mockHandlerOffset,
375
+ }),
376
+ { wrapper }
377
+ );
378
+
379
+ act(() => {
380
+ result.current.next();
381
+ });
382
+
383
+ // Should block advancing because remaining width (2 * 100) is less than container width (300)
384
+ expect(mockHandlerOffset.value).toBe(-300);
385
+
386
+ // Reset shared global values for other tests
387
+ mockGlobalState.props.overscrollEnabled = true;
388
+ mockGlobalState.props.loop = true;
389
+ mockGlobalState.common.size = 300;
390
+ mockGlobalState.common.resolvedSize.value = 300;
391
+ mockGlobalState.layout.containerSize.value = { width: 300, height: 300 };
392
+ });
393
+
394
+ it("should fall back to propWidth when container size is unknown", () => {
395
+ mockGlobalState.props.overscrollEnabled = false;
396
+ mockGlobalState.props.loop = false;
397
+ mockGlobalState.props.width = 240;
398
+ mockGlobalState.common.size = 100;
399
+ mockGlobalState.common.resolvedSize.value = 100;
400
+ mockGlobalState.layout.containerSize.value = { width: 0, height: 0 };
401
+ mockHandlerOffset.value = 0;
402
+
403
+ const { result } = renderHook(
404
+ () =>
405
+ useCarouselController({
406
+ ...defaultProps,
407
+ size: 100,
408
+ width: 240,
409
+ loop: false,
410
+ handlerOffset: mockHandlerOffset,
411
+ }),
412
+ { wrapper }
413
+ );
414
+
415
+ result.current.index.value = 4; // remaining width = 1 * 100 < effective width 240
416
+
417
+ act(() => {
418
+ result.current.next();
419
+ });
420
+
421
+ expect(mockHandlerOffset.value).toBe(0);
422
+
423
+ // reset
424
+ mockGlobalState.props.overscrollEnabled = true;
425
+ mockGlobalState.props.loop = true;
426
+ mockGlobalState.props.width = 300;
427
+ mockGlobalState.common.size = 300;
428
+ mockGlobalState.common.resolvedSize.value = 300;
429
+ mockGlobalState.layout.containerSize.value = { width: 300, height: 300 };
430
+ });
431
+
432
+ it("should fall back to style width when container and prop width are unavailable", () => {
433
+ mockGlobalState.props.overscrollEnabled = false;
434
+ mockGlobalState.props.loop = false;
435
+ mockGlobalState.props.width = undefined as any;
436
+ mockGlobalState.props.style = { width: 220 };
437
+ mockGlobalState.common.size = 100;
438
+ mockGlobalState.common.resolvedSize.value = 100;
439
+ mockGlobalState.layout.containerSize.value = { width: 0, height: 0 };
440
+ mockHandlerOffset.value = 0;
441
+
442
+ const { result } = renderHook(
443
+ () =>
444
+ useCarouselController({
445
+ ...defaultProps,
446
+ size: 100,
447
+ style: mockGlobalState.props.style,
448
+ width: undefined,
449
+ loop: false,
450
+ handlerOffset: mockHandlerOffset,
451
+ }),
452
+ { wrapper }
453
+ );
454
+
455
+ result.current.index.value = 4;
456
+
457
+ act(() => {
458
+ result.current.next();
459
+ });
460
+
461
+ expect(mockHandlerOffset.value).toBe(0);
462
+
463
+ mockGlobalState.props.overscrollEnabled = true;
464
+ mockGlobalState.props.loop = true;
465
+ mockGlobalState.props.width = 300;
466
+ mockGlobalState.props.style = {};
467
+ mockGlobalState.common.size = 300;
468
+ mockGlobalState.common.resolvedSize.value = 300;
469
+ mockGlobalState.layout.containerSize.value = { width: 300, height: 300 };
470
+ });
471
+
472
+ it("should fall back to propHeight in vertical mode when container size is unknown", () => {
473
+ mockGlobalState.props.overscrollEnabled = false;
474
+ mockGlobalState.props.loop = false;
475
+ mockGlobalState.props.vertical = true;
476
+ mockGlobalState.props.height = 150;
477
+ mockGlobalState.common.size = 80;
478
+ mockGlobalState.common.resolvedSize.value = 80;
479
+ mockGlobalState.layout.containerSize.value = { width: 0, height: 0 };
480
+ mockHandlerOffset.value = 0;
481
+
482
+ const { result } = renderHook(
483
+ () =>
484
+ useCarouselController({
485
+ ...defaultProps,
486
+ size: 80,
487
+ height: 150,
488
+ loop: false,
489
+ handlerOffset: mockHandlerOffset,
490
+ dataLength: 5,
491
+ }),
492
+ { wrapper }
493
+ );
494
+
495
+ result.current.index.value = 4;
496
+
497
+ act(() => {
498
+ result.current.next();
499
+ });
500
+
501
+ expect(mockHandlerOffset.value).toBe(0);
502
+
503
+ // reset
504
+ mockGlobalState.props.overscrollEnabled = true;
505
+ mockGlobalState.props.loop = true;
506
+ mockGlobalState.props.vertical = false;
507
+ mockGlobalState.props.height = 300;
508
+ mockGlobalState.common.size = 300;
509
+ mockGlobalState.common.resolvedSize.value = 300;
510
+ mockGlobalState.layout.containerSize.value = { width: 300, height: 300 };
511
+ });
512
+
513
+ it("should use propWidth branch when container width is zero", () => {
514
+ mockGlobalState.props.overscrollEnabled = false;
515
+ mockGlobalState.props.loop = false;
516
+ mockGlobalState.props.width = 240;
517
+ mockGlobalState.props.style = {};
518
+ mockGlobalState.common.size = 120;
519
+ mockGlobalState.common.resolvedSize.value = 120;
520
+ mockGlobalState.layout.containerSize.value = { width: 0, height: 0 };
521
+ mockHandlerOffset.value = 0;
522
+
523
+ const { result } = renderHook(
524
+ () =>
525
+ useCarouselController({
526
+ ...defaultProps,
527
+ size: 120,
528
+ width: 240,
529
+ loop: false,
530
+ handlerOffset: mockHandlerOffset,
531
+ }),
532
+ { wrapper }
533
+ );
534
+
535
+ // at index 3 of 5, remaining width = 2 * 120 = 240, equals effective width; overscroll block triggers
536
+ result.current.index.value = 3;
537
+
538
+ act(() => {
539
+ result.current.next();
540
+ });
541
+
542
+ expect(mockHandlerOffset.value).toBe(0);
543
+
544
+ // reset
545
+ mockGlobalState.props.overscrollEnabled = true;
546
+ mockGlobalState.props.loop = true;
547
+ mockGlobalState.props.width = 300;
548
+ mockGlobalState.props.style = {};
549
+ mockGlobalState.common.size = 300;
550
+ mockGlobalState.common.resolvedSize.value = 300;
551
+ mockGlobalState.layout.containerSize.value = { width: 300, height: 300 };
552
+ });
553
+
554
+ it("should fall back to style height in vertical mode when container and prop height are unavailable", () => {
555
+ mockGlobalState.props.overscrollEnabled = false;
556
+ mockGlobalState.props.loop = false;
557
+ mockGlobalState.props.vertical = true;
558
+ mockGlobalState.props.height = undefined as any;
559
+ mockGlobalState.props.style = { height: 160 };
560
+ mockGlobalState.common.size = 80;
561
+ mockGlobalState.common.resolvedSize.value = 80;
562
+ mockGlobalState.layout.containerSize.value = { width: 0, height: 0 };
563
+ mockHandlerOffset.value = 0;
564
+
565
+ const { result } = renderHook(
566
+ () =>
567
+ useCarouselController({
568
+ ...defaultProps,
569
+ size: 80,
570
+ style: mockGlobalState.props.style,
571
+ height: undefined,
572
+ loop: false,
573
+ handlerOffset: mockHandlerOffset,
574
+ dataLength: 5,
575
+ }),
576
+ { wrapper }
577
+ );
578
+
579
+ result.current.index.value = 4;
580
+
581
+ act(() => {
582
+ result.current.next();
583
+ });
584
+
585
+ expect(mockHandlerOffset.value).toBe(0);
586
+
587
+ mockGlobalState.props.overscrollEnabled = true;
588
+ mockGlobalState.props.loop = true;
589
+ mockGlobalState.props.vertical = false;
590
+ mockGlobalState.props.height = 300;
591
+ mockGlobalState.props.style = {};
592
+ mockGlobalState.common.size = 300;
593
+ mockGlobalState.common.resolvedSize.value = 300;
594
+ mockGlobalState.layout.containerSize.value = { width: 300, height: 300 };
595
+ });
596
+
597
+ it("should use pageSize fallback multiplier when no size info is available", () => {
598
+ mockGlobalState.props.overscrollEnabled = false;
599
+ mockGlobalState.props.loop = false;
600
+ mockGlobalState.props.width = undefined as any;
601
+ mockGlobalState.props.height = undefined as any;
602
+ mockGlobalState.common.size = 100;
603
+ mockGlobalState.common.resolvedSize.value = 100;
604
+ mockGlobalState.layout.containerSize.value = { width: 0, height: 0 };
605
+ mockHandlerOffset.value = 0;
606
+
607
+ const { result } = renderHook(
608
+ () =>
609
+ useCarouselController({
610
+ ...defaultProps,
611
+ size: 100,
612
+ width: undefined,
613
+ height: undefined,
614
+ loop: false,
615
+ handlerOffset: mockHandlerOffset,
616
+ }),
617
+ { wrapper }
618
+ );
619
+
620
+ act(() => {
621
+ result.current.next({ animated: false });
622
+ });
623
+
624
+ expect(mockHandlerOffset.value).toBe(-100);
625
+
626
+ // reset
627
+ mockGlobalState.props.overscrollEnabled = true;
628
+ mockGlobalState.props.loop = true;
629
+ mockGlobalState.props.width = 300;
630
+ mockGlobalState.props.height = 300;
631
+ mockGlobalState.common.size = 300;
632
+ mockGlobalState.common.resolvedSize.value = 300;
633
+ mockGlobalState.layout.containerSize.value = { width: 300, height: 300 };
634
+ });
635
+
636
+ it("should use propHeight branch when container height is zero (vertical)", () => {
637
+ mockGlobalState.props.overscrollEnabled = false;
638
+ mockGlobalState.props.loop = false;
639
+ mockGlobalState.props.vertical = true;
640
+ mockGlobalState.props.height = 180;
641
+ mockGlobalState.props.style = {};
642
+ mockGlobalState.common.size = 90;
643
+ mockGlobalState.common.resolvedSize.value = 90;
644
+ mockGlobalState.layout.containerSize.value = { width: 0, height: 0 };
645
+ mockHandlerOffset.value = 0;
646
+
647
+ const { result } = renderHook(
648
+ () =>
649
+ useCarouselController({
650
+ ...defaultProps,
651
+ vertical: true,
652
+ size: 90,
653
+ height: 180,
654
+ loop: false,
655
+ handlerOffset: mockHandlerOffset,
656
+ dataLength: 5,
657
+ }),
658
+ { wrapper }
659
+ );
660
+
661
+ result.current.index.value = 3; // remaining height = 2 * 90 = 180, equals effective height
662
+
663
+ act(() => {
664
+ result.current.next();
665
+ });
666
+
667
+ expect(mockHandlerOffset.value).toBe(0);
668
+
669
+ mockGlobalState.props.overscrollEnabled = true;
670
+ mockGlobalState.props.loop = true;
671
+ mockGlobalState.props.vertical = false;
672
+ mockGlobalState.props.height = 300;
673
+ mockGlobalState.props.style = {};
674
+ mockGlobalState.common.size = 300;
675
+ mockGlobalState.common.resolvedSize.value = 300;
676
+ mockGlobalState.layout.containerSize.value = { width: 300, height: 300 };
677
+ });
678
+
679
+ it("should animate scrollTo when animated is true", () => {
680
+ const { result } = renderHook(() => useCarouselController(defaultProps), { wrapper });
681
+
682
+ act(() => {
683
+ result.current.scrollTo({ index: 1, animated: true });
684
+ });
685
+
686
+ expect(result.current.index.value).toBe(1);
687
+ expect(mockHandlerOffset.value).toBe(-300);
688
+ });
689
+
690
+ // it("should maintain correct index with autoFillData", () => {
691
+ // const { result } = renderHook(
692
+ // () =>
693
+ // useCarouselController({
694
+ // ...defaultProps,
695
+ // autoFillData: true,
696
+ // dataLength: 3,
697
+ // }),
698
+ // { wrapper }
699
+ // );
700
+
701
+ // act(() => {
702
+ // result.current.next();
703
+ // result.current.next();
704
+ // });
705
+
706
+ // expect(result.current.getCurrentIndex()).toBe(2);
707
+ // });
708
+
709
+ it("should handle animated reactions correctly", () => {
710
+ renderHook(() => useCarouselController(defaultProps), { wrapper });
711
+
712
+ expect(mockAnimatedReaction).toHaveBeenCalled();
713
+ expect(mockScheduleOnRN).toHaveBeenCalled();
714
+ });
715
+
716
+ it("should handle scheduleOnRN correctly", () => {
717
+ const { result } = renderHook(() => useCarouselController(defaultProps), { wrapper });
718
+
719
+ act(() => {
720
+ result.current.next();
721
+ });
722
+
723
+ expect(mockScheduleOnRN).toHaveBeenCalled();
724
+ });
725
+ });
726
+
727
+ describe("useCarouselController imperative handle", () => {
728
+ let mockHandlerOffset: ReturnType<typeof useSharedValue<number>>;
729
+ let ref: ReturnType<typeof useRef>;
730
+ let defaultProps: any;
731
+
732
+ beforeEach(() => {
733
+ jest.clearAllMocks();
734
+ mockHandlerOffset = useSharedValue(0);
735
+ ref = useRef<ICarouselInstance>(null!);
736
+ defaultProps = {
737
+ ref,
738
+ size: 300,
739
+ loop: true,
740
+ dataLength: 5,
741
+ handlerOffset: mockHandlerOffset,
742
+ autoFillData: false,
743
+ duration: 300,
744
+ };
745
+ mockHandlerOffset.value = 0;
746
+ });
747
+
748
+ // it("should expose imperative methods through ref", () => {
749
+ // renderHook(() => useCarouselController(defaultProps), { wrapper });
750
+
751
+ // // Verify useImperativeHandle was called
752
+ // expect(useImperativeHandle).toHaveBeenCalledWith(ref, expect.any(Function));
753
+
754
+ // // Get the handle creator function
755
+ // const createHandle = (useImperativeHandle as jest.Mock).mock.calls[0][1];
756
+ // const handle = createHandle();
757
+
758
+ // // Verify exposed methods
759
+ // expect(handle).toHaveProperty("getCurrentIndex");
760
+ // expect(handle).toHaveProperty("next");
761
+ // expect(handle).toHaveProperty("prev");
762
+ // expect(handle).toHaveProperty("scrollTo");
763
+ // });
764
+
765
+ it("should maintain correct index through imperative calls", () => {
766
+ const { result } = renderHook(() => useCarouselController(defaultProps), { wrapper });
767
+
768
+ // Get handle methods
769
+ const createHandle = (useImperativeHandle as jest.Mock).mock.calls[0][1];
770
+ const handle = createHandle();
771
+
772
+ // Test sequence of imperative calls
773
+ act(() => {
774
+ handle.next();
775
+ handle.next();
776
+ });
777
+ expect(handle.getCurrentIndex()).toBe(2);
778
+
779
+ act(() => {
780
+ handle.prev();
781
+ });
782
+ expect(handle.getCurrentIndex()).toBe(1);
783
+
784
+ act(() => {
785
+ handle.scrollTo({ index: 3 });
786
+ });
787
+ expect(handle.getCurrentIndex()).toBe(3);
788
+ });
789
+
790
+ it("should handle animation callbacks through imperative calls", () => {
791
+ const { result } = renderHook(() => useCarouselController(defaultProps), { wrapper });
792
+ const onFinished = jest.fn();
793
+
794
+ // Get handle methods
795
+ const createHandle = (useImperativeHandle as jest.Mock).mock.calls[0][1];
796
+ const handle = createHandle();
797
+
798
+ act(() => {
799
+ handle.next({ animated: true, onFinished });
800
+ });
801
+
802
+ expect(onFinished).toHaveBeenCalled();
803
+ });
804
+
805
+ it("should respect loop settings through imperative calls", () => {
806
+ const { result } = renderHook(
807
+ () =>
808
+ useCarouselController({
809
+ ...defaultProps,
810
+ loop: false,
811
+ }),
812
+ { wrapper }
813
+ );
814
+
815
+ // Get handle methods
816
+ const createHandle = (useImperativeHandle as jest.Mock).mock.calls[0][1];
817
+ const handle = createHandle();
818
+
819
+ // Try to go past the end
820
+ act(() => {
821
+ handle.scrollTo({ index: 4 });
822
+ handle.next();
823
+ });
824
+ expect(handle.getCurrentIndex()).toBe(4);
825
+
826
+ // Try to go before the start
827
+ act(() => {
828
+ handle.scrollTo({ index: 0 });
829
+ handle.prev();
830
+ });
831
+ expect(handle.getCurrentIndex()).toBe(0);
832
+ });
833
+
834
+ it("should handle multiple slide movements through imperative calls", () => {
835
+ const { result } = renderHook(() => useCarouselController(defaultProps), { wrapper });
836
+
837
+ // Get handle methods
838
+ const createHandle = (useImperativeHandle as jest.Mock).mock.calls[0][1];
839
+ const handle = createHandle();
840
+
841
+ act(() => {
842
+ handle.next({ count: 2 });
843
+ });
844
+
845
+ expect(handle.getCurrentIndex()).toBe(2);
846
+ expect(mockHandlerOffset.value).toBe(-600); // size * 2
847
+ });
848
+ });
849
+
850
+ describe("useCarouselController edge cases and uncovered lines", () => {
851
+ let mockHandlerOffset: ReturnType<typeof useSharedValue<number>>;
852
+ let ref: ReturnType<typeof useRef>;
853
+ let defaultProps: any;
854
+
855
+ beforeEach(() => {
856
+ jest.clearAllMocks();
857
+ mockHandlerOffset = useSharedValue<number>(0);
858
+ ref = useRef<ICarouselInstance>(null!);
859
+ defaultProps = {
860
+ ref,
861
+ size: 300,
862
+ loop: false,
863
+ dataLength: 5,
864
+ handlerOffset: mockHandlerOffset,
865
+ autoFillData: false,
866
+ duration: 300,
867
+ };
868
+ mockHandlerOffset.value = 0;
869
+ });
870
+
871
+ it("should handle next() without animation - uncovered line 213-214", () => {
872
+ const { result } = renderHook(() => useCarouselController(defaultProps), { wrapper });
873
+ const onFinished = jest.fn();
874
+
875
+ act(() => {
876
+ result.current.next({ animated: false, onFinished });
877
+ });
878
+
879
+ expect(mockHandlerOffset.value).toBe(-300); // size * 1
880
+ expect(onFinished).toHaveBeenCalled();
881
+ });
882
+
883
+ it("should handle prev() without animation - uncovered line 245-246", () => {
884
+ const { result } = renderHook(
885
+ () =>
886
+ useCarouselController({
887
+ ...defaultProps,
888
+ loop: true, // Enable loop to allow prev
889
+ }),
890
+ { wrapper }
891
+ );
892
+
893
+ // First move to a position where prev is valid
894
+ act(() => {
895
+ result.current.next({ animated: false }); // Move to index 1
896
+ });
897
+
898
+ const onFinished = jest.fn();
899
+
900
+ act(() => {
901
+ result.current.prev({ animated: false, onFinished });
902
+ });
903
+
904
+ // Should move back to index 0 (could be -0)
905
+ expect(Math.abs(mockHandlerOffset.value)).toBe(0);
906
+ expect(onFinished).toHaveBeenCalled();
907
+ });
908
+
909
+ it("should handle scrollTo() without animation when target equals current index - uncovered line 265", () => {
910
+ const { result } = renderHook(() => useCarouselController(defaultProps), { wrapper });
911
+
912
+ // Set index to 1
913
+ act(() => {
914
+ result.current.next({ animated: false });
915
+ });
916
+
917
+ const onFinished = jest.fn();
918
+
919
+ // Try to scroll to same index
920
+ act(() => {
921
+ result.current.scrollTo({ index: 1, animated: false, onFinished });
922
+ });
923
+
924
+ // Should return early and not call onFinished
925
+ expect(onFinished).not.toHaveBeenCalled();
926
+ expect(mockHandlerOffset.value).toBe(-300); // Should remain unchanged
927
+ });
928
+
929
+ it("should handle scrollTo() without animation - uncovered line 294-296", () => {
930
+ const { result } = renderHook(
931
+ () =>
932
+ useCarouselController({
933
+ ...defaultProps,
934
+ loop: true,
935
+ }),
936
+ { wrapper }
937
+ );
938
+ const onFinished = jest.fn();
939
+
940
+ act(() => {
941
+ result.current.scrollTo({ index: 2, animated: false, onFinished });
942
+ });
943
+
944
+ expect(mockHandlerOffset.value).toBe(-600); // size * 2
945
+ expect(onFinished).toHaveBeenCalled();
946
+ });
947
+
948
+ it("should handle scrollTo() with count parameter - uncovered line 321-326", () => {
949
+ const { result } = renderHook(() => useCarouselController(defaultProps), { wrapper });
950
+
951
+ // Test negative count
952
+ act(() => {
953
+ result.current.scrollTo({ count: -2 });
954
+ });
955
+
956
+ expect(mockHandlerOffset.value).toBe(0); // At start, can't go further back
957
+
958
+ // Reset and test positive count
959
+ act(() => {
960
+ result.current.scrollTo({ count: 2 });
961
+ });
962
+
963
+ expect(mockHandlerOffset.value).toBe(-600); // size * 2
964
+ });
965
+
966
+ it("should handle scrollTo() with invalid count (should return early)", () => {
967
+ const { result } = renderHook(() => useCarouselController(defaultProps), { wrapper });
968
+
969
+ act(() => {
970
+ result.current.scrollTo({ count: 0 }); // Should return early
971
+ });
972
+
973
+ expect(mockHandlerOffset.value).toBe(0); // Should remain unchanged
974
+ });
975
+
976
+ it("should handle overscroll protection when overscrollEnabled is false", () => {
977
+ const restrictedGlobalState = {
978
+ ...mockGlobalState,
979
+ props: {
980
+ ...mockGlobalState.props,
981
+ overscrollEnabled: false,
982
+ },
983
+ layout: {
984
+ ...mockGlobalState.layout,
985
+ containerSize: { value: { width: 300, height: 300 } },
986
+ },
987
+ } as IContext;
988
+
989
+ const restrictedWrapper: React.FC<{ children: React.ReactNode }> = ({ children }) => (
990
+ <GlobalStateContext.Provider value={restrictedGlobalState}>
991
+ {children}
992
+ </GlobalStateContext.Provider>
993
+ );
994
+
995
+ const { result } = renderHook(
996
+ () =>
997
+ useCarouselController({
998
+ ...defaultProps,
999
+ loop: false,
1000
+ dataLength: 4,
1001
+ }),
1002
+ { wrapper: restrictedWrapper }
1003
+ );
1004
+
1005
+ // Move to index 2 where remaining visible content would be too small
1006
+ act(() => {
1007
+ result.current.scrollTo({ index: 2, animated: false });
1008
+ });
1009
+
1010
+ // Try to move next - should be blocked by overscroll protection
1011
+ act(() => {
1012
+ result.current.next();
1013
+ });
1014
+
1015
+ // The test logic may vary, just ensure it moved
1016
+ expect(typeof mockHandlerOffset.value).toBe("number");
1017
+ });
1018
+
1019
+ it("should call onScrollStart and onScrollEnd callbacks", () => {
1020
+ const onScrollStart = jest.fn();
1021
+ const onScrollEnd = jest.fn();
1022
+
1023
+ const { result } = renderHook(
1024
+ () =>
1025
+ useCarouselController({
1026
+ ...defaultProps,
1027
+ onScrollStart,
1028
+ onScrollEnd,
1029
+ }),
1030
+ { wrapper }
1031
+ );
1032
+
1033
+ act(() => {
1034
+ result.current.next({ animated: true });
1035
+ });
1036
+
1037
+ expect(onScrollStart).toHaveBeenCalled();
1038
+ expect(onScrollEnd).toHaveBeenCalled();
1039
+ });
1040
+
1041
+ it("should handle disabled carousel (empty data)", () => {
1042
+ const { result } = renderHook(
1043
+ () =>
1044
+ useCarouselController({
1045
+ ...defaultProps,
1046
+ dataLength: 0,
1047
+ }),
1048
+ { wrapper }
1049
+ );
1050
+
1051
+ act(() => {
1052
+ result.current.next();
1053
+ });
1054
+
1055
+ expect(mockHandlerOffset.value).toBe(0); // Should not move
1056
+ });
1057
+
1058
+ it("should handle autoFillData with computedRealIndexWithAutoFillData", () => {
1059
+ const { result } = renderHook(
1060
+ () =>
1061
+ useCarouselController({
1062
+ ...defaultProps,
1063
+ autoFillData: true,
1064
+ dataLength: 3,
1065
+ }),
1066
+ { wrapper }
1067
+ );
1068
+
1069
+ act(() => {
1070
+ result.current.next();
1071
+ });
1072
+
1073
+ const currentIndex = result.current.getCurrentIndex();
1074
+ expect(typeof currentIndex).toBe("number");
1075
+ });
1076
+
1077
+ it("should handle positive fixed direction in scrollTo", () => {
1078
+ const { result } = renderHook(
1079
+ () =>
1080
+ useCarouselController({
1081
+ ...defaultProps,
1082
+ loop: true,
1083
+ fixedDirection: "positive",
1084
+ }),
1085
+ { wrapper }
1086
+ );
1087
+
1088
+ act(() => {
1089
+ result.current.scrollTo({ index: 3, animated: false });
1090
+ });
1091
+
1092
+ expect(mockHandlerOffset.value).toBe(900); // size * 3
1093
+ });
1094
+
1095
+ it("should handle negative fixed direction in scrollTo", () => {
1096
+ const { result } = renderHook(
1097
+ () =>
1098
+ useCarouselController({
1099
+ ...defaultProps,
1100
+ loop: true,
1101
+ fixedDirection: "negative",
1102
+ }),
1103
+ { wrapper }
1104
+ );
1105
+
1106
+ act(() => {
1107
+ result.current.scrollTo({ index: 3, animated: false });
1108
+ });
1109
+
1110
+ expect(mockHandlerOffset.value).toBe(-900); // size * 3
1111
+ });
1112
+
1113
+ it("should handle scrollTo when loop position is close to next cycle", () => {
1114
+ const { result } = renderHook(
1115
+ () =>
1116
+ useCarouselController({
1117
+ ...defaultProps,
1118
+ loop: true,
1119
+ }),
1120
+ { wrapper }
1121
+ );
1122
+
1123
+ mockHandlerOffset.value = -900; // 3 * size, more than half-way through current cycle
1124
+
1125
+ act(() => {
1126
+ result.current.scrollTo({ index: 1, animated: false });
1127
+ });
1128
+
1129
+ expect(mockHandlerOffset.value).toBe(-1800);
1130
+ });
1131
+
1132
+ it("should get shared index correctly", () => {
1133
+ const { result } = renderHook(() => useCarouselController(defaultProps), { wrapper });
1134
+
1135
+ const sharedIndex = result.current.getSharedIndex();
1136
+ expect(typeof sharedIndex).toBe("number");
1137
+ });
1138
+
1139
+ it("should handle currentFixedPage calculation for non-loop mode", () => {
1140
+ const { result } = renderHook(
1141
+ () =>
1142
+ useCarouselController({
1143
+ ...defaultProps,
1144
+ loop: false,
1145
+ }),
1146
+ { wrapper }
1147
+ );
1148
+
1149
+ // Set a specific offset to test the calculation
1150
+ mockHandlerOffset.value = -450; // Between indices
1151
+
1152
+ act(() => {
1153
+ result.current.next();
1154
+ });
1155
+
1156
+ expect(typeof mockHandlerOffset.value).toBe("number");
1157
+ });
1158
+ });