@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,525 @@
1
+ import React, { useRef } from "react";
2
+ import { StyleSheet } from "react-native";
3
+ import { SharedValue, useAnimatedReaction, useSharedValue } from "react-native-reanimated";
4
+ import { scheduleOnRN } from "react-native-worklets";
5
+
6
+ import { Easing } from "../constants";
7
+ import { useGlobalState } from "../store";
8
+ import type {
9
+ ICarouselInstance,
10
+ TCarouselActionOptions,
11
+ TCarouselProps,
12
+ WithTimingAnimation,
13
+ } from "../types";
14
+ import {
15
+ computedRealIndexWithAutoFillData,
16
+ convertToSharedIndex,
17
+ } from "../utils/computed-with-auto-fill-data";
18
+ import { dealWithAnimation } from "../utils/deal-with-animation";
19
+ import { handlerOffsetDirection } from "../utils/handleroffset-direction";
20
+ import { round } from "../utils/log";
21
+
22
+ interface IOpts {
23
+ ref: React.ForwardedRef<ICarouselInstance>;
24
+ loop: boolean;
25
+ size: number;
26
+ dataLength: number;
27
+ handlerOffset: SharedValue<number>;
28
+ autoFillData: TCarouselProps["autoFillData"];
29
+ withAnimation?: TCarouselProps["withAnimation"];
30
+ fixedDirection?: TCarouselProps["fixedDirection"];
31
+ duration?: number;
32
+ defaultIndex?: number;
33
+ onScrollStart?: () => void;
34
+ onScrollEnd?: () => void;
35
+ }
36
+
37
+ export interface ICarouselController {
38
+ getSharedIndex: () => number;
39
+ prev: (opts?: TCarouselActionOptions) => void;
40
+ next: (opts?: TCarouselActionOptions) => void;
41
+ getCurrentIndex: () => number;
42
+ scrollTo: (opts?: TCarouselActionOptions) => void;
43
+ index: SharedValue<number>;
44
+ }
45
+
46
+ export function useCarouselController(options: IOpts): ICarouselController {
47
+ const {
48
+ ref,
49
+ size,
50
+ loop,
51
+ dataLength,
52
+ handlerOffset,
53
+ withAnimation,
54
+ defaultIndex = 0,
55
+ duration,
56
+ autoFillData,
57
+ fixedDirection,
58
+ } = options;
59
+
60
+ const globalState = useGlobalState();
61
+
62
+ const {
63
+ props: { overscrollEnabled, vertical, style, width, height, variableSize },
64
+ layout: { containerSize },
65
+ common: { sizePhase, resolvedSize },
66
+ sizeResolver,
67
+ } = globalState;
68
+
69
+ const dataInfo = React.useMemo(
70
+ () => ({
71
+ length: dataLength,
72
+ disable: !dataLength,
73
+ originalLength: dataLength,
74
+ }),
75
+ [dataLength]
76
+ );
77
+
78
+ const index = useSharedValue<number>(defaultIndex);
79
+ // The Index displayed to the user
80
+ const sharedIndex = useRef<number>(defaultIndex);
81
+ const sharedPreIndex = useRef<number>(defaultIndex);
82
+
83
+ const currentFixedPage = React.useCallback(() => {
84
+ if (variableSize) {
85
+ const total = sizeResolver.total.value;
86
+ if (total <= 0) return 0;
87
+ if (loop) {
88
+ // Map handlerOffset into a single loop of length `total`, then look
89
+ // up the item index for that intra-loop offset.
90
+ const wrapped = ((-handlerOffset.value % total) + total) % total;
91
+ return sizeResolver.indexAt(wrapped);
92
+ }
93
+ const idx = sizeResolver.indexAt(-handlerOffset.value);
94
+ return Math.max(0, Math.min(dataInfo.length - 1, idx));
95
+ }
96
+ if (size <= 0) return 0;
97
+ if (loop) return -Math.round(handlerOffset.value / size);
98
+
99
+ // In non-loop mode, treat the offset as negative when moving forward.
100
+ // Clamp within valid range to avoid wrapping when a tiny positive offset
101
+ // appears after overscroll at index 0.
102
+ const rawPage = -handlerOffset.value / size;
103
+ const rounded = Math.round(rawPage);
104
+ const clamped = Math.max(0, Math.min(dataInfo.length - 1, rounded));
105
+ return clamped;
106
+ }, [handlerOffset, dataInfo, size, loop, variableSize, sizeResolver]);
107
+
108
+ function setSharedIndex(newSharedIndex: number) {
109
+ sharedIndex.current = newSharedIndex;
110
+ }
111
+
112
+ useAnimatedReaction(
113
+ () => {
114
+ if (variableSize) {
115
+ const total = sizeResolver.total.value;
116
+ if (total <= 0) return { i: 0, newSharedIndexValue: 0 };
117
+ const handlerOffsetValue = handlerOffset.value;
118
+ // Wrap into a single loop length so item index is well-defined no
119
+ // matter how many full loops the user has scrolled.
120
+ const wrapped = ((-handlerOffsetValue % total) + total) % total;
121
+ const i = sizeResolver.indexAt(wrapped);
122
+ const newSharedIndexValue = convertToSharedIndex({
123
+ loop,
124
+ rawDataLength: dataInfo.originalLength,
125
+ autoFillData: autoFillData!,
126
+ index: i,
127
+ });
128
+ return { i, newSharedIndexValue };
129
+ }
130
+
131
+ if (size <= 0) {
132
+ return {
133
+ i: 0,
134
+ newSharedIndexValue: 0,
135
+ };
136
+ }
137
+
138
+ const handlerOffsetValue = handlerOffset.value;
139
+ const toInt = round(handlerOffsetValue / size) % dataInfo.length;
140
+ const isPositive = handlerOffsetValue <= 0;
141
+ const i = isPositive ? Math.abs(toInt) : Math.abs(toInt > 0 ? dataInfo.length - toInt : 0);
142
+
143
+ const newSharedIndexValue = convertToSharedIndex({
144
+ loop,
145
+ rawDataLength: dataInfo.originalLength,
146
+ autoFillData: autoFillData!,
147
+ index: i,
148
+ });
149
+
150
+ return {
151
+ i,
152
+ newSharedIndexValue,
153
+ };
154
+ },
155
+ ({ i, newSharedIndexValue }) => {
156
+ index.value = i;
157
+ scheduleOnRN(setSharedIndex, newSharedIndexValue);
158
+ },
159
+ [
160
+ sharedPreIndex,
161
+ sharedIndex,
162
+ size,
163
+ dataInfo,
164
+ index,
165
+ loop,
166
+ autoFillData,
167
+ handlerOffset,
168
+ variableSize,
169
+ sizeResolver,
170
+ ]
171
+ );
172
+
173
+ const getCurrentIndex = React.useCallback(() => {
174
+ const realIndex = computedRealIndexWithAutoFillData({
175
+ index: index.value,
176
+ dataLength: dataInfo.originalLength,
177
+ loop,
178
+ autoFillData: autoFillData!,
179
+ });
180
+
181
+ return realIndex;
182
+ }, [index, autoFillData, dataInfo, loop]);
183
+
184
+ const canSliding = React.useCallback(() => {
185
+ if (variableSize) {
186
+ const total = sizeResolver.total.value;
187
+ return !dataInfo.disable && total > 0;
188
+ }
189
+ const currentSize = resolvedSize.value ?? size;
190
+ const ready = sizePhase.value === "ready" && !!currentSize;
191
+
192
+ return !dataInfo.disable && ready;
193
+ }, [dataInfo, resolvedSize, sizePhase, size, variableSize, sizeResolver]);
194
+
195
+ const onScrollEnd = React.useCallback(() => {
196
+ options.onScrollEnd?.();
197
+ }, [options]);
198
+
199
+ const onScrollStart = React.useCallback(() => {
200
+ options.onScrollStart?.();
201
+ }, [options]);
202
+
203
+ const scrollWithTiming = React.useCallback(
204
+ (toValue: number, onFinished?: () => void) => {
205
+ "worklet";
206
+ const callback = (isFinished: boolean) => {
207
+ "worklet";
208
+ if (isFinished) {
209
+ scheduleOnRN(onScrollEnd);
210
+ onFinished && scheduleOnRN(onFinished);
211
+ }
212
+ };
213
+
214
+ const defaultWithAnimation: WithTimingAnimation = {
215
+ type: "timing",
216
+ config: { duration, easing: Easing.easeOutQuart },
217
+ };
218
+
219
+ return dealWithAnimation(withAnimation ?? defaultWithAnimation)(toValue, callback);
220
+ },
221
+ [duration, withAnimation, onScrollEnd]
222
+ );
223
+
224
+ const flattenedStyle = StyleSheet.flatten(style) || {};
225
+
226
+ const next = React.useCallback(
227
+ (opts: TCarouselActionOptions = {}) => {
228
+ "worklet";
229
+ const { count = 1, animated = true, onFinished } = opts;
230
+ if (!canSliding()) return;
231
+
232
+ if (!loop) {
233
+ const newIndex = index.value + count;
234
+ const isOutOfBounds = newIndex > dataInfo.length - 1;
235
+ if (isOutOfBounds) {
236
+ return;
237
+ }
238
+ }
239
+
240
+ /*
241
+ [Overscroll Protection Logic]
242
+
243
+ This section handles the overscroll protection when overscrollEnabled is false.
244
+ It prevents scrolling beyond the visible content area.
245
+
246
+ Example scenario:
247
+ - Container width: 300px
248
+ - Item width: 75px (4 items per view)
249
+ - Total items: 6
250
+
251
+ Initial state (index = 0):
252
+ [0][1][2][3] | [4][5]
253
+ visible | remaining
254
+
255
+ After 2 slides (index = 2):
256
+ [0][1] | [2][3][4][5]
257
+ hidden | visible
258
+
259
+ The visibleContentWidth calculation:
260
+ - At index 2, remaining items = 4 (items 2,3,4,5)
261
+ - visibleContentWidth = 4 * 75px = 300px
262
+
263
+ If we try to slide again:
264
+ - New visibleContentWidth would be: 2 * 75px = 150px (only items 4,5 remain)
265
+ - Since 150px < container width (300px), the slide is prevented
266
+
267
+ This ensures we don't scroll beyond the last set of fully visible items,
268
+ maintaining a clean UX without partial item visibility at the edges.
269
+ */
270
+ // For overscroll calculation, use the intended item size, not the measured container size
271
+ // In the new dynamic size system, the measured `size` could reflect the container rather than
272
+ // each item, so prefer explicit width/height props and fall back to style-based dimensions.
273
+ const styleWidth =
274
+ typeof flattenedStyle.width === "number" ? flattenedStyle.width : undefined;
275
+ const styleHeight =
276
+ typeof flattenedStyle.height === "number" ? flattenedStyle.height : undefined;
277
+ const propWidth = typeof width === "number" ? width : undefined;
278
+ const propHeight = typeof height === "number" ? height : undefined;
279
+
280
+ // Use the page size (derived from itemWidth/itemHeight) for overscroll calculations.
281
+ // Fallback to container/style dimensions only if page size is unavailable.
282
+ const pageSize =
283
+ size > 0
284
+ ? size
285
+ : vertical
286
+ ? (propHeight ?? styleHeight ?? 0)
287
+ : (propWidth ?? styleWidth ?? 0);
288
+
289
+ const visibleContentWidth = variableSize
290
+ ? sizeResolver.total.value - sizeResolver.offsetAt(index.value)
291
+ : (dataInfo.length - index.value) * pageSize;
292
+
293
+ // Get effective container width, with fallback for cases where containerSize
294
+ // hasn't been updated yet (e.g., in tests or during initialization)
295
+ const getEffectiveContainerWidth = () => {
296
+ // 1. Use measured value if available
297
+ if (containerSize.value.width > 0) {
298
+ return containerSize.value.width;
299
+ }
300
+
301
+ // 2. Fallback to style width/height when no measurement available
302
+ if (!vertical) {
303
+ if (propWidth && propWidth > 0) {
304
+ return propWidth;
305
+ }
306
+ if (styleWidth && styleWidth > 0) {
307
+ return styleWidth;
308
+ }
309
+ }
310
+ if (vertical) {
311
+ if (propHeight && propHeight > 0) {
312
+ return propHeight;
313
+ }
314
+ if (styleHeight && styleHeight > 0) {
315
+ return styleHeight;
316
+ }
317
+ }
318
+
319
+ // 3. Final fallback - assume multiple items are visible
320
+ return pageSize * 3; // Assume 3 items per view as reasonable default
321
+ };
322
+
323
+ const effectiveContainerWidth = getEffectiveContainerWidth();
324
+
325
+ if (!overscrollEnabled && effectiveContainerWidth > 0) {
326
+ if (!(visibleContentWidth > effectiveContainerWidth)) {
327
+ return;
328
+ }
329
+ }
330
+
331
+ onScrollStart?.();
332
+
333
+ const nextPage = currentFixedPage() + count;
334
+ index.value = nextPage;
335
+
336
+ // Translate the target item index to a translation offset. In variable
337
+ // mode we walk the prefix table; loop iterations add full `total` spans.
338
+ const offsetForPage = (page: number): number => {
339
+ if (!variableSize) return -page * size;
340
+ const total = sizeResolver.total.value;
341
+ const len = dataInfo.length;
342
+ if (total <= 0 || len <= 0) return 0;
343
+ const fullLoops = Math.floor(page / len);
344
+ const wrapped = ((page % len) + len) % len;
345
+ return -(sizeResolver.offsetAt(wrapped) + fullLoops * total);
346
+ };
347
+
348
+ if (animated) {
349
+ handlerOffset.value = scrollWithTiming(offsetForPage(nextPage), onFinished) as any;
350
+ } else {
351
+ handlerOffset.value = offsetForPage(nextPage);
352
+ onFinished?.();
353
+ }
354
+ },
355
+ [
356
+ canSliding,
357
+ loop,
358
+ index,
359
+ dataInfo,
360
+ onScrollStart,
361
+ handlerOffset,
362
+ size,
363
+ scrollWithTiming,
364
+ currentFixedPage,
365
+ overscrollEnabled,
366
+ containerSize,
367
+ vertical,
368
+ flattenedStyle,
369
+ width,
370
+ height,
371
+ variableSize,
372
+ sizeResolver,
373
+ ]
374
+ );
375
+
376
+ const prev = React.useCallback(
377
+ (opts: TCarouselActionOptions = {}) => {
378
+ const { count = 1, animated = true, onFinished } = opts;
379
+ if (!canSliding()) return;
380
+
381
+ if (!loop && index.value <= 0) return;
382
+
383
+ onScrollStart?.();
384
+
385
+ const prevPage = currentFixedPage() - count;
386
+ index.value = prevPage;
387
+
388
+ const offsetForPage = (page: number): number => {
389
+ if (!variableSize) return -page * size;
390
+ const total = sizeResolver.total.value;
391
+ const len = dataInfo.length;
392
+ if (total <= 0 || len <= 0) return 0;
393
+ const fullLoops = Math.floor(page / len);
394
+ const wrapped = ((page % len) + len) % len;
395
+ return -(sizeResolver.offsetAt(wrapped) + fullLoops * total);
396
+ };
397
+
398
+ if (animated) {
399
+ handlerOffset.value = scrollWithTiming(offsetForPage(prevPage), onFinished);
400
+ } else {
401
+ handlerOffset.value = offsetForPage(prevPage);
402
+ onFinished?.();
403
+ }
404
+ },
405
+ [
406
+ canSliding,
407
+ loop,
408
+ index,
409
+ onScrollStart,
410
+ handlerOffset,
411
+ size,
412
+ scrollWithTiming,
413
+ currentFixedPage,
414
+ variableSize,
415
+ sizeResolver,
416
+ dataInfo,
417
+ ]
418
+ );
419
+
420
+ const to = React.useCallback(
421
+ (opts: { i: number; animated: boolean; onFinished?: () => void }) => {
422
+ const { i, animated = false, onFinished } = opts;
423
+
424
+ if (i === index.value) return;
425
+
426
+ if (!canSliding()) return;
427
+
428
+ onScrollStart?.();
429
+
430
+ // Per-item start offset along the scroll axis.
431
+ const offsetAtIndex = (idx: number): number => {
432
+ if (variableSize) return sizeResolver.offsetAt(idx);
433
+ return idx * size;
434
+ };
435
+ const totalSpan = variableSize ? sizeResolver.total.value : dataInfo.length * size;
436
+
437
+ let finalOffset: number;
438
+
439
+ if (!loop) {
440
+ // Non-loop mode always uses direct page-to-offset mapping.
441
+ // This avoids sign flips when moving to lower indices.
442
+ finalOffset = -offsetAtIndex(i);
443
+ } else {
444
+ // direction -> 1 | -1
445
+ let direction: -1 | 1;
446
+ if (fixedDirection === "positive") direction = 1;
447
+ else if (fixedDirection === "negative") direction = -1;
448
+ else direction = handlerOffsetDirection(handlerOffset);
449
+
450
+ // target offset for one loop
451
+ const itemOffset = offsetAtIndex(i) * direction;
452
+ const isCloseToNextLoop =
453
+ totalSpan > 0 ? Math.abs(handlerOffset.value % totalSpan) / totalSpan >= 0.5 : false;
454
+
455
+ finalOffset =
456
+ (Math.floor(Math.abs(handlerOffset.value / (totalSpan || 1))) +
457
+ (isCloseToNextLoop ? 1 : 0)) *
458
+ totalSpan *
459
+ direction +
460
+ itemOffset;
461
+ }
462
+
463
+ if (animated) {
464
+ index.value = i;
465
+ handlerOffset.value = scrollWithTiming(finalOffset, onFinished);
466
+ } else {
467
+ handlerOffset.value = finalOffset;
468
+ index.value = i;
469
+ onFinished?.();
470
+ }
471
+ },
472
+ [
473
+ size,
474
+ loop,
475
+ index,
476
+ fixedDirection,
477
+ handlerOffset,
478
+ dataInfo.length,
479
+ canSliding,
480
+ onScrollStart,
481
+ scrollWithTiming,
482
+ variableSize,
483
+ sizeResolver,
484
+ ]
485
+ );
486
+
487
+ const scrollTo = React.useCallback(
488
+ (opts: TCarouselActionOptions = {}) => {
489
+ const { index: i, count, animated = false, onFinished } = opts;
490
+
491
+ if (typeof i === "number" && i > -1) {
492
+ to({ i, animated, onFinished });
493
+ return;
494
+ }
495
+
496
+ if (!count) return;
497
+
498
+ const n = Math.round(count);
499
+
500
+ if (n < 0) prev({ count: Math.abs(n), animated, onFinished });
501
+ else next({ count: n, animated, onFinished });
502
+ },
503
+ [prev, next, to]
504
+ );
505
+
506
+ React.useImperativeHandle(
507
+ ref,
508
+ () => ({
509
+ next,
510
+ prev,
511
+ getCurrentIndex,
512
+ scrollTo,
513
+ }),
514
+ [getCurrentIndex, next, prev, scrollTo]
515
+ );
516
+
517
+ return {
518
+ next,
519
+ prev,
520
+ scrollTo,
521
+ getCurrentIndex,
522
+ getSharedIndex: () => sharedIndex.current,
523
+ index,
524
+ };
525
+ }
@@ -0,0 +1,47 @@
1
+ import { renderHook } from "@testing-library/react-hooks";
2
+
3
+ import { useCheckMounted } from "./useCheckMounted";
4
+
5
+ describe("useCheckMounted", () => {
6
+ it("should be mounted after initialization", () => {
7
+ const { result } = renderHook(() => useCheckMounted());
8
+
9
+ expect(result.current.current).toBe(true);
10
+ });
11
+
12
+ it("should be unmounted after cleanup", () => {
13
+ const { result, unmount } = renderHook(() => useCheckMounted());
14
+
15
+ expect(result.current.current).toBe(true);
16
+
17
+ unmount();
18
+
19
+ expect(result.current.current).toBe(false);
20
+ });
21
+
22
+ it("should maintain mounted state during component lifecycle", () => {
23
+ const { result, rerender } = renderHook(() => useCheckMounted());
24
+
25
+ expect(result.current.current).toBe(true);
26
+
27
+ rerender();
28
+
29
+ expect(result.current.current).toBe(true);
30
+ });
31
+
32
+ it("should handle multiple mount/unmount cycles", () => {
33
+ // First instance
34
+ const hook1 = renderHook(() => useCheckMounted());
35
+ expect(hook1.result.current.current).toBe(true);
36
+
37
+ hook1.unmount();
38
+ expect(hook1.result.current.current).toBe(false);
39
+
40
+ // Second instance
41
+ const hook2 = renderHook(() => useCheckMounted());
42
+ expect(hook2.result.current.current).toBe(true);
43
+
44
+ hook2.unmount();
45
+ expect(hook2.result.current.current).toBe(false);
46
+ });
47
+ });
@@ -0,0 +1,14 @@
1
+ import React from "react";
2
+
3
+ export function useCheckMounted() {
4
+ const mounted = React.useRef(false);
5
+
6
+ React.useEffect(() => {
7
+ mounted.current = true;
8
+ return () => {
9
+ mounted.current = false;
10
+ };
11
+ }, []);
12
+
13
+ return mounted;
14
+ }