@lodev09/react-native-true-sheet 4.0.0-beta.0 → 4.0.0-beta.2

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 (388) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +42 -31
  3. package/RNTrueSheet.podspec +10 -2
  4. package/android/build.gradle +2 -1
  5. package/android/src/main/java/com/lodev09/truesheet/TrueSheetContainerView.kt +174 -49
  6. package/android/src/main/java/com/lodev09/truesheet/TrueSheetContainerViewManager.kt +7 -0
  7. package/android/src/main/java/com/lodev09/truesheet/TrueSheetContentView.kt +371 -18
  8. package/android/src/main/java/com/lodev09/truesheet/TrueSheetContentViewManager.kt +14 -0
  9. package/android/src/main/java/com/lodev09/truesheet/TrueSheetFooterView.kt +156 -21
  10. package/android/src/main/java/com/lodev09/truesheet/TrueSheetFooterViewManager.kt +14 -0
  11. package/android/src/main/java/com/lodev09/truesheet/TrueSheetHeaderView.kt +38 -0
  12. package/android/src/main/java/com/lodev09/truesheet/TrueSheetHeaderViewManager.kt +28 -0
  13. package/android/src/main/java/com/lodev09/truesheet/TrueSheetModule.kt +84 -24
  14. package/android/src/main/java/com/lodev09/truesheet/TrueSheetPackage.kt +5 -4
  15. package/android/src/main/java/com/lodev09/truesheet/TrueSheetPeekView.kt +72 -0
  16. package/android/src/main/java/com/lodev09/truesheet/TrueSheetPeekViewManager.kt +33 -0
  17. package/android/src/main/java/com/lodev09/truesheet/TrueSheetStateUpdater.kt +45 -0
  18. package/android/src/main/java/com/lodev09/truesheet/TrueSheetView.kt +526 -231
  19. package/android/src/main/java/com/lodev09/truesheet/TrueSheetViewController.kt +1224 -603
  20. package/android/src/main/java/com/lodev09/truesheet/TrueSheetViewManager.kt +136 -29
  21. package/android/src/main/java/com/lodev09/truesheet/core/RNScreensEventObserver.kt +63 -0
  22. package/android/src/main/java/com/lodev09/truesheet/core/TrueSheetBottomSheetBehavior.kt +36 -0
  23. package/android/src/main/java/com/lodev09/truesheet/core/TrueSheetBottomSheetView.kt +255 -0
  24. package/android/src/main/java/com/lodev09/truesheet/core/TrueSheetCoordinatorLayout.kt +303 -0
  25. package/android/src/main/java/com/lodev09/truesheet/core/TrueSheetDetentCalculator.kt +277 -0
  26. package/android/src/main/java/com/lodev09/truesheet/core/TrueSheetDimView.kt +162 -0
  27. package/android/src/main/java/com/lodev09/truesheet/core/TrueSheetGrabberView.kt +180 -0
  28. package/android/src/main/java/com/lodev09/truesheet/core/TrueSheetKeyboardObserver.kt +207 -0
  29. package/android/src/main/java/com/lodev09/truesheet/core/TrueSheetStackManager.kt +220 -0
  30. package/android/src/main/java/com/lodev09/truesheet/events/TrueSheetDragEvents.kt +71 -0
  31. package/android/src/main/java/com/lodev09/truesheet/events/TrueSheetFocusEvents.kt +65 -0
  32. package/android/src/main/java/com/lodev09/truesheet/events/TrueSheetLifecycleEvents.kt +112 -0
  33. package/android/src/main/java/com/lodev09/truesheet/events/TrueSheetStateEvents.kt +56 -0
  34. package/android/src/main/java/com/lodev09/truesheet/utils/KeyboardUtils.kt +84 -0
  35. package/android/src/main/java/com/lodev09/truesheet/utils/ScreenUtils.kt +93 -67
  36. package/android/src/main/java/com/lodev09/truesheet/utils/TouchEventDeduper.kt +31 -0
  37. package/android/src/main/java/com/lodev09/truesheet/utils/ViewUtils.kt +30 -0
  38. package/android/src/main/jni/CMakeLists.txt +63 -0
  39. package/android/src/main/jni/TrueSheetSpec.h +19 -0
  40. package/android/src/main/jni/TrueSheetStateUpdater.cpp +96 -0
  41. package/common/cpp/react/renderer/components/TrueSheetSpec/TrueSheetContentViewComponentDescriptor.h +24 -0
  42. package/common/cpp/react/renderer/components/TrueSheetSpec/TrueSheetContentViewShadowNode.cpp +43 -0
  43. package/common/cpp/react/renderer/components/TrueSheetSpec/TrueSheetContentViewShadowNode.h +28 -0
  44. package/common/cpp/react/renderer/components/TrueSheetSpec/TrueSheetContentViewState.cpp +11 -0
  45. package/common/cpp/react/renderer/components/TrueSheetSpec/TrueSheetContentViewState.h +37 -0
  46. package/common/cpp/react/renderer/components/TrueSheetSpec/TrueSheetFooterViewComponentDescriptor.h +24 -0
  47. package/common/cpp/react/renderer/components/TrueSheetSpec/TrueSheetFooterViewShadowNode.cpp +56 -0
  48. package/common/cpp/react/renderer/components/TrueSheetSpec/TrueSheetFooterViewShadowNode.h +28 -0
  49. package/common/cpp/react/renderer/components/TrueSheetSpec/TrueSheetFooterViewState.cpp +11 -0
  50. package/common/cpp/react/renderer/components/TrueSheetSpec/TrueSheetFooterViewState.h +41 -0
  51. package/common/cpp/react/renderer/components/TrueSheetSpec/TrueSheetInsets.cpp +18 -0
  52. package/common/cpp/react/renderer/components/TrueSheetSpec/TrueSheetInsets.h +16 -0
  53. package/common/cpp/react/renderer/components/TrueSheetSpec/TrueSheetViewComponentDescriptor.h +28 -0
  54. package/common/cpp/react/renderer/components/TrueSheetSpec/TrueSheetViewShadowNode.cpp +61 -0
  55. package/common/cpp/react/renderer/components/TrueSheetSpec/TrueSheetViewShadowNode.h +45 -0
  56. package/common/cpp/react/renderer/components/TrueSheetSpec/TrueSheetViewState.cpp +23 -0
  57. package/common/cpp/react/renderer/components/TrueSheetSpec/TrueSheetViewState.h +52 -0
  58. package/ios/TrueSheetContainerView.h +81 -6
  59. package/ios/TrueSheetContainerView.mm +275 -21
  60. package/ios/TrueSheetContentView.h +38 -1
  61. package/ios/TrueSheetContentView.mm +413 -43
  62. package/ios/TrueSheetFooterView.h +27 -2
  63. package/ios/TrueSheetFooterView.mm +141 -35
  64. package/ios/{events/OnDidDismissEvent.h → TrueSheetHeaderView.h} +10 -7
  65. package/ios/TrueSheetHeaderView.mm +64 -0
  66. package/ios/TrueSheetModule.mm +92 -5
  67. package/ios/TrueSheetPeekView.h +32 -0
  68. package/ios/TrueSheetPeekView.mm +99 -0
  69. package/ios/TrueSheetView.h +7 -15
  70. package/ios/TrueSheetView.mm +633 -215
  71. package/ios/TrueSheetViewController.h +84 -16
  72. package/ios/TrueSheetViewController.mm +1133 -333
  73. package/ios/core/RNScreensEventObserver.h +46 -0
  74. package/ios/core/RNScreensEventObserver.mm +280 -0
  75. package/ios/core/TrueSheetBlurView.h +27 -0
  76. package/ios/core/TrueSheetBlurView.mm +82 -0
  77. package/ios/core/TrueSheetDetentCalculator.h +107 -0
  78. package/ios/core/TrueSheetDetentCalculator.mm +197 -0
  79. package/ios/core/TrueSheetGrabberView.h +72 -0
  80. package/ios/core/TrueSheetGrabberView.mm +178 -0
  81. package/ios/core/TrueSheetKeyboardObserver.h +39 -0
  82. package/ios/core/TrueSheetKeyboardObserver.mm +112 -0
  83. package/ios/events/TrueSheetDragEvents.h +39 -0
  84. package/ios/events/TrueSheetDragEvents.mm +62 -0
  85. package/ios/events/{OnPositionChangeEvent.h → TrueSheetFocusEvents.h} +8 -5
  86. package/ios/events/TrueSheetFocusEvents.mm +49 -0
  87. package/ios/events/TrueSheetLifecycleEvents.h +40 -0
  88. package/ios/events/TrueSheetLifecycleEvents.mm +71 -0
  89. package/ios/events/TrueSheetStateEvents.h +35 -0
  90. package/ios/events/TrueSheetStateEvents.mm +49 -0
  91. package/ios/tvos/TrueSheetStubs.mm +154 -0
  92. package/ios/{events/OnMountEvent.h → utils/BlurUtil.h} +5 -7
  93. package/ios/utils/BlurUtil.mm +69 -0
  94. package/ios/utils/GestureUtil.h +7 -0
  95. package/ios/utils/GestureUtil.mm +12 -0
  96. package/ios/utils/PlatformUtil.h +15 -0
  97. package/ios/utils/UIView+FirstResponder.h +15 -0
  98. package/ios/utils/UIView+FirstResponder.mm +26 -0
  99. package/ios/{events/OnWillDismissEvent.h → utils/UIView+ScrollEdgeInteraction.h} +6 -7
  100. package/ios/utils/UIView+ScrollEdgeInteraction.mm +62 -0
  101. package/ios/utils/WindowUtil.mm +17 -1
  102. package/lib/module/TrueSheet.js +230 -64
  103. package/lib/module/TrueSheet.js.map +1 -1
  104. package/lib/module/TrueSheet.web.js +1203 -0
  105. package/lib/module/TrueSheet.web.js.map +1 -0
  106. package/lib/module/TrueSheetPeek.js +15 -0
  107. package/lib/module/TrueSheetPeek.js.map +1 -0
  108. package/lib/module/TrueSheetPeek.web.js +55 -0
  109. package/lib/module/TrueSheetPeek.web.js.map +1 -0
  110. package/lib/module/TrueSheetProvider.js +28 -0
  111. package/lib/module/TrueSheetProvider.js.map +1 -0
  112. package/lib/module/TrueSheetProvider.web.js +157 -0
  113. package/lib/module/TrueSheetProvider.web.js.map +1 -0
  114. package/lib/module/fabric/TrueSheetContainerViewNativeComponent.ts +1 -1
  115. package/lib/module/fabric/TrueSheetContentViewNativeComponent.ts +5 -1
  116. package/lib/module/fabric/TrueSheetFooterViewNativeComponent.ts +10 -2
  117. package/lib/module/fabric/TrueSheetHeaderViewNativeComponent.ts +8 -0
  118. package/lib/module/fabric/TrueSheetPeekViewNativeComponent.ts +8 -0
  119. package/lib/module/fabric/TrueSheetViewNativeComponent.ts +105 -18
  120. package/lib/module/index.js +3 -3
  121. package/lib/module/index.js.map +1 -1
  122. package/lib/module/mocks/index.js +93 -0
  123. package/lib/module/mocks/index.js.map +1 -0
  124. package/lib/module/mocks/navigation.js +95 -0
  125. package/lib/module/mocks/navigation.js.map +1 -0
  126. package/lib/module/mocks/navigationExpoRouter.js +21 -0
  127. package/lib/module/mocks/navigationExpoRouter.js.map +1 -0
  128. package/lib/module/mocks/reanimated.js +91 -0
  129. package/lib/module/mocks/reanimated.js.map +1 -0
  130. package/lib/module/navigation/TrueSheetNavigatorContent.js +73 -0
  131. package/lib/module/navigation/TrueSheetNavigatorContent.js.map +1 -0
  132. package/lib/module/navigation/actions.js +50 -0
  133. package/lib/module/navigation/actions.js.map +1 -0
  134. package/lib/module/navigation/createTrueSheetRouter.js +166 -0
  135. package/lib/module/navigation/createTrueSheetRouter.js.map +1 -0
  136. package/lib/module/navigation/expo-router/index.js +48 -0
  137. package/lib/module/navigation/expo-router/index.js.map +1 -0
  138. package/lib/module/navigation/index.js +47 -0
  139. package/lib/module/navigation/index.js.map +1 -0
  140. package/lib/module/navigation/navigator.js +10 -0
  141. package/lib/module/navigation/navigator.js.map +1 -0
  142. package/lib/module/navigation/screen/ReanimatedTrueSheetScreen.js +56 -0
  143. package/lib/module/navigation/screen/ReanimatedTrueSheetScreen.js.map +1 -0
  144. package/lib/module/navigation/screen/TrueSheetScreen.js +49 -0
  145. package/lib/module/navigation/screen/TrueSheetScreen.js.map +1 -0
  146. package/lib/module/navigation/screen/index.js +5 -0
  147. package/lib/module/navigation/screen/index.js.map +1 -0
  148. package/lib/module/navigation/screen/types.js +4 -0
  149. package/lib/module/navigation/screen/types.js.map +1 -0
  150. package/lib/module/navigation/screen/useSheetScreenState.js +68 -0
  151. package/lib/module/navigation/screen/useSheetScreenState.js.map +1 -0
  152. package/lib/module/navigation/types.js +4 -0
  153. package/lib/module/navigation/types.js.map +1 -0
  154. package/lib/module/navigation/useTrueSheetNavigation.js +24 -0
  155. package/lib/module/navigation/useTrueSheetNavigation.js.map +1 -0
  156. package/lib/module/reanimated/ReanimatedTrueSheet.js +15 -9
  157. package/lib/module/reanimated/ReanimatedTrueSheet.js.map +1 -1
  158. package/lib/module/reanimated/ReanimatedTrueSheet.web.js +81 -0
  159. package/lib/module/reanimated/ReanimatedTrueSheet.web.js.map +1 -0
  160. package/lib/module/reanimated/ReanimatedTrueSheetProvider.js +4 -2
  161. package/lib/module/reanimated/ReanimatedTrueSheetProvider.js.map +1 -1
  162. package/lib/module/reanimated/index.js +2 -2
  163. package/lib/module/reanimated/index.js.map +1 -1
  164. package/lib/module/reanimated/useReanimatedPositionChangeHandler.web.js +20 -0
  165. package/lib/module/reanimated/useReanimatedPositionChangeHandler.web.js.map +1 -0
  166. package/lib/module/specs/NativeTrueSheetModule.js.map +1 -1
  167. package/lib/module/web/constants.js +16 -0
  168. package/lib/module/web/constants.js.map +1 -0
  169. package/lib/module/web/dom.js +10 -0
  170. package/lib/module/web/dom.js.map +1 -0
  171. package/lib/module/web/vaul/README.md +9 -0
  172. package/lib/module/web/vaul/browser.js +30 -0
  173. package/lib/module/web/vaul/browser.js.map +1 -0
  174. package/lib/module/web/vaul/constants.js +15 -0
  175. package/lib/module/web/vaul/constants.js.map +1 -0
  176. package/lib/module/web/vaul/context.js +59 -0
  177. package/lib/module/web/vaul/context.js.map +1 -0
  178. package/lib/module/web/vaul/helpers.js +99 -0
  179. package/lib/module/web/vaul/helpers.js.map +1 -0
  180. package/lib/module/web/vaul/index.js +1309 -0
  181. package/lib/module/web/vaul/index.js.map +1 -0
  182. package/lib/module/web/vaul/style.css +287 -0
  183. package/lib/module/web/vaul/style.css.d.js +2 -0
  184. package/lib/module/web/vaul/style.css.d.js.map +1 -0
  185. package/lib/module/web/vaul/types.js +2 -0
  186. package/lib/module/web/vaul/types.js.map +1 -0
  187. package/lib/module/web/vaul/use-composed-refs.js +34 -0
  188. package/lib/module/web/vaul/use-composed-refs.js.map +1 -0
  189. package/lib/module/web/vaul/use-controllable-state.js +54 -0
  190. package/lib/module/web/vaul/use-controllable-state.js.map +1 -0
  191. package/lib/module/web/vaul/use-position-fixed.js +123 -0
  192. package/lib/module/web/vaul/use-position-fixed.js.map +1 -0
  193. package/lib/module/web/vaul/use-prevent-scroll.js +258 -0
  194. package/lib/module/web/vaul/use-prevent-scroll.js.map +1 -0
  195. package/lib/module/web/vaul/use-scale-background.js +57 -0
  196. package/lib/module/web/vaul/use-scale-background.js.map +1 -0
  197. package/lib/module/web/vaul/use-snap-points.js +305 -0
  198. package/lib/module/web/vaul/use-snap-points.js.map +1 -0
  199. package/lib/typescript/src/TrueSheet.d.ts +51 -14
  200. package/lib/typescript/src/TrueSheet.d.ts.map +1 -1
  201. package/lib/typescript/src/TrueSheet.types.d.ts +463 -54
  202. package/lib/typescript/src/TrueSheet.types.d.ts.map +1 -1
  203. package/lib/typescript/src/TrueSheet.web.d.ts +5 -0
  204. package/lib/typescript/src/TrueSheet.web.d.ts.map +1 -0
  205. package/lib/typescript/src/TrueSheetPeek.d.ts +9 -0
  206. package/lib/typescript/src/TrueSheetPeek.d.ts.map +1 -0
  207. package/lib/typescript/src/TrueSheetPeek.web.d.ts +28 -0
  208. package/lib/typescript/src/TrueSheetPeek.web.d.ts.map +1 -0
  209. package/lib/typescript/src/TrueSheetProvider.d.ts +18 -0
  210. package/lib/typescript/src/TrueSheetProvider.d.ts.map +1 -0
  211. package/lib/typescript/src/TrueSheetProvider.web.d.ts +27 -0
  212. package/lib/typescript/src/TrueSheetProvider.web.d.ts.map +1 -0
  213. package/lib/typescript/src/fabric/TrueSheetContainerViewNativeComponent.d.ts.map +1 -1
  214. package/lib/typescript/src/fabric/TrueSheetContentViewNativeComponent.d.ts.map +1 -1
  215. package/lib/typescript/src/fabric/TrueSheetFooterViewNativeComponent.d.ts +2 -0
  216. package/lib/typescript/src/fabric/TrueSheetFooterViewNativeComponent.d.ts.map +1 -1
  217. package/lib/typescript/src/fabric/TrueSheetHeaderViewNativeComponent.d.ts +6 -0
  218. package/lib/typescript/src/fabric/TrueSheetHeaderViewNativeComponent.d.ts.map +1 -0
  219. package/lib/typescript/src/fabric/TrueSheetPeekViewNativeComponent.d.ts +6 -0
  220. package/lib/typescript/src/fabric/TrueSheetPeekViewNativeComponent.d.ts.map +1 -0
  221. package/lib/typescript/src/fabric/TrueSheetViewNativeComponent.d.ts +67 -16
  222. package/lib/typescript/src/fabric/TrueSheetViewNativeComponent.d.ts.map +1 -1
  223. package/lib/typescript/src/index.d.ts +2 -2
  224. package/lib/typescript/src/index.d.ts.map +1 -1
  225. package/lib/typescript/src/mocks/index.d.ts +43 -0
  226. package/lib/typescript/src/mocks/index.d.ts.map +1 -0
  227. package/lib/typescript/src/mocks/navigation.d.ts +70 -0
  228. package/lib/typescript/src/mocks/navigation.d.ts.map +1 -0
  229. package/lib/typescript/src/mocks/navigationExpoRouter.d.ts +22 -0
  230. package/lib/typescript/src/mocks/navigationExpoRouter.d.ts.map +1 -0
  231. package/lib/typescript/src/mocks/reanimated.d.ts +48 -0
  232. package/lib/typescript/src/mocks/reanimated.d.ts.map +1 -0
  233. package/lib/typescript/src/navigation/TrueSheetNavigatorContent.d.ts +5 -0
  234. package/lib/typescript/src/navigation/TrueSheetNavigatorContent.d.ts.map +1 -0
  235. package/lib/typescript/src/navigation/actions.d.ts +71 -0
  236. package/lib/typescript/src/navigation/actions.d.ts.map +1 -0
  237. package/lib/typescript/src/navigation/createTrueSheetRouter.d.ts +14 -0
  238. package/lib/typescript/src/navigation/createTrueSheetRouter.d.ts.map +1 -0
  239. package/lib/typescript/src/navigation/expo-router/index.d.ts +37 -0
  240. package/lib/typescript/src/navigation/expo-router/index.d.ts.map +1 -0
  241. package/lib/typescript/src/navigation/index.d.ts +46 -0
  242. package/lib/typescript/src/navigation/index.d.ts.map +1 -0
  243. package/lib/typescript/src/navigation/navigator.d.ts +7 -0
  244. package/lib/typescript/src/navigation/navigator.d.ts.map +1 -0
  245. package/lib/typescript/src/navigation/screen/ReanimatedTrueSheetScreen.d.ts +3 -0
  246. package/lib/typescript/src/navigation/screen/ReanimatedTrueSheetScreen.d.ts.map +1 -0
  247. package/lib/typescript/src/navigation/screen/TrueSheetScreen.d.ts +3 -0
  248. package/lib/typescript/src/navigation/screen/TrueSheetScreen.d.ts.map +1 -0
  249. package/lib/typescript/src/navigation/screen/index.d.ts +4 -0
  250. package/lib/typescript/src/navigation/screen/index.d.ts.map +1 -0
  251. package/lib/typescript/src/navigation/screen/types.d.ts +14 -0
  252. package/lib/typescript/src/navigation/screen/types.d.ts.map +1 -0
  253. package/lib/typescript/src/navigation/screen/useSheetScreenState.d.ts +33 -0
  254. package/lib/typescript/src/navigation/screen/useSheetScreenState.d.ts.map +1 -0
  255. package/lib/typescript/src/navigation/types.d.ts +177 -0
  256. package/lib/typescript/src/navigation/types.d.ts.map +1 -0
  257. package/lib/typescript/src/navigation/useTrueSheetNavigation.d.ts +23 -0
  258. package/lib/typescript/src/navigation/useTrueSheetNavigation.d.ts.map +1 -0
  259. package/lib/typescript/src/reanimated/ReanimatedTrueSheet.d.ts.map +1 -1
  260. package/lib/typescript/src/reanimated/ReanimatedTrueSheet.web.d.ts +41 -0
  261. package/lib/typescript/src/reanimated/ReanimatedTrueSheet.web.d.ts.map +1 -0
  262. package/lib/typescript/src/reanimated/ReanimatedTrueSheetProvider.d.ts +8 -2
  263. package/lib/typescript/src/reanimated/ReanimatedTrueSheetProvider.d.ts.map +1 -1
  264. package/lib/typescript/src/reanimated/useReanimatedPositionChangeHandler.web.d.ts +15 -0
  265. package/lib/typescript/src/reanimated/useReanimatedPositionChangeHandler.web.d.ts.map +1 -0
  266. package/lib/typescript/src/specs/NativeTrueSheetModule.d.ts +25 -3
  267. package/lib/typescript/src/specs/NativeTrueSheetModule.d.ts.map +1 -1
  268. package/lib/typescript/src/web/constants.d.ts +14 -0
  269. package/lib/typescript/src/web/constants.d.ts.map +1 -0
  270. package/lib/typescript/src/web/dom.d.ts +7 -0
  271. package/lib/typescript/src/web/dom.d.ts.map +1 -0
  272. package/lib/typescript/src/web/vaul/browser.d.ts +8 -0
  273. package/lib/typescript/src/web/vaul/browser.d.ts.map +1 -0
  274. package/lib/typescript/src/web/vaul/constants.d.ts +13 -0
  275. package/lib/typescript/src/web/vaul/constants.d.ts.map +1 -0
  276. package/lib/typescript/src/web/vaul/context.d.ts +53 -0
  277. package/lib/typescript/src/web/vaul/context.d.ts.map +1 -0
  278. package/lib/typescript/src/web/vaul/helpers.d.ts +17 -0
  279. package/lib/typescript/src/web/vaul/helpers.d.ts.map +1 -0
  280. package/lib/typescript/src/web/vaul/index.d.ts +228 -0
  281. package/lib/typescript/src/web/vaul/index.d.ts.map +1 -0
  282. package/lib/typescript/src/web/vaul/types.d.ts +7 -0
  283. package/lib/typescript/src/web/vaul/types.d.ts.map +1 -0
  284. package/lib/typescript/src/web/vaul/use-composed-refs.d.ts +14 -0
  285. package/lib/typescript/src/web/vaul/use-composed-refs.d.ts.map +1 -0
  286. package/lib/typescript/src/web/vaul/use-controllable-state.d.ts +9 -0
  287. package/lib/typescript/src/web/vaul/use-controllable-state.d.ts.map +1 -0
  288. package/lib/typescript/src/web/vaul/use-position-fixed.d.ts +19 -0
  289. package/lib/typescript/src/web/vaul/use-position-fixed.d.ts.map +1 -0
  290. package/lib/typescript/src/web/vaul/use-prevent-scroll.d.ts +18 -0
  291. package/lib/typescript/src/web/vaul/use-prevent-scroll.d.ts.map +1 -0
  292. package/lib/typescript/src/web/vaul/use-scale-background.d.ts +2 -0
  293. package/lib/typescript/src/web/vaul/use-scale-background.d.ts.map +1 -0
  294. package/lib/typescript/src/web/vaul/use-snap-points.d.ts +38 -0
  295. package/lib/typescript/src/web/vaul/use-snap-points.d.ts.map +1 -0
  296. package/package.json +95 -36
  297. package/react-native.config.js +9 -2
  298. package/src/TrueSheet.tsx +281 -62
  299. package/src/TrueSheet.types.ts +525 -71
  300. package/src/TrueSheet.web.tsx +1362 -0
  301. package/src/TrueSheetPeek.tsx +11 -0
  302. package/src/TrueSheetPeek.web.tsx +64 -0
  303. package/src/TrueSheetProvider.tsx +33 -0
  304. package/src/TrueSheetProvider.web.tsx +220 -0
  305. package/src/fabric/TrueSheetContainerViewNativeComponent.ts +1 -1
  306. package/src/fabric/TrueSheetContentViewNativeComponent.ts +5 -1
  307. package/src/fabric/TrueSheetFooterViewNativeComponent.ts +10 -2
  308. package/src/fabric/TrueSheetHeaderViewNativeComponent.ts +8 -0
  309. package/src/fabric/TrueSheetPeekViewNativeComponent.ts +8 -0
  310. package/src/fabric/TrueSheetViewNativeComponent.ts +105 -18
  311. package/src/index.ts +2 -2
  312. package/src/mocks/index.ts +89 -0
  313. package/src/mocks/navigation.ts +79 -0
  314. package/src/mocks/navigationExpoRouter.ts +40 -0
  315. package/src/mocks/reanimated.ts +100 -0
  316. package/src/navigation/TrueSheetNavigatorContent.tsx +106 -0
  317. package/src/navigation/actions.ts +78 -0
  318. package/src/navigation/createTrueSheetRouter.ts +222 -0
  319. package/src/navigation/expo-router/index.ts +89 -0
  320. package/src/navigation/index.ts +81 -0
  321. package/src/navigation/navigator.ts +18 -0
  322. package/src/navigation/screen/ReanimatedTrueSheetScreen.tsx +61 -0
  323. package/src/navigation/screen/TrueSheetScreen.tsx +54 -0
  324. package/src/navigation/screen/index.ts +3 -0
  325. package/src/navigation/screen/types.ts +19 -0
  326. package/src/navigation/screen/useSheetScreenState.ts +100 -0
  327. package/src/navigation/types.ts +251 -0
  328. package/src/navigation/useTrueSheetNavigation.ts +26 -0
  329. package/src/reanimated/ReanimatedTrueSheet.tsx +12 -7
  330. package/src/reanimated/ReanimatedTrueSheet.web.tsx +75 -0
  331. package/src/reanimated/ReanimatedTrueSheetProvider.tsx +12 -8
  332. package/src/reanimated/useReanimatedPositionChangeHandler.web.ts +31 -0
  333. package/src/specs/NativeTrueSheetModule.ts +28 -3
  334. package/src/web/constants.ts +13 -0
  335. package/src/web/dom.ts +9 -0
  336. package/src/web/vaul/README.md +9 -0
  337. package/src/web/vaul/browser.ts +38 -0
  338. package/src/web/vaul/constants.ts +20 -0
  339. package/src/web/vaul/context.ts +101 -0
  340. package/src/web/vaul/helpers.ts +131 -0
  341. package/src/web/vaul/index.tsx +1740 -0
  342. package/src/web/vaul/style.css +287 -0
  343. package/src/web/vaul/style.css.d.ts +1 -0
  344. package/src/web/vaul/types.ts +7 -0
  345. package/src/web/vaul/use-composed-refs.ts +35 -0
  346. package/src/web/vaul/use-controllable-state.ts +66 -0
  347. package/src/web/vaul/use-position-fixed.ts +147 -0
  348. package/src/web/vaul/use-prevent-scroll.ts +309 -0
  349. package/src/web/vaul/use-scale-background.ts +64 -0
  350. package/src/web/vaul/use-snap-points.ts +455 -0
  351. package/android/src/main/java/com/lodev09/truesheet/events/DetentChangeEvent.kt +0 -26
  352. package/android/src/main/java/com/lodev09/truesheet/events/DidDismissEvent.kt +0 -20
  353. package/android/src/main/java/com/lodev09/truesheet/events/DidPresentEvent.kt +0 -26
  354. package/android/src/main/java/com/lodev09/truesheet/events/DragBeginEvent.kt +0 -26
  355. package/android/src/main/java/com/lodev09/truesheet/events/DragChangeEvent.kt +0 -26
  356. package/android/src/main/java/com/lodev09/truesheet/events/DragEndEvent.kt +0 -26
  357. package/android/src/main/java/com/lodev09/truesheet/events/MountEvent.kt +0 -20
  358. package/android/src/main/java/com/lodev09/truesheet/events/PositionChangeEvent.kt +0 -32
  359. package/android/src/main/java/com/lodev09/truesheet/events/SizeChangeEvent.kt +0 -27
  360. package/android/src/main/java/com/lodev09/truesheet/events/WillDismissEvent.kt +0 -20
  361. package/android/src/main/java/com/lodev09/truesheet/events/WillPresentEvent.kt +0 -26
  362. package/android/src/main/res/values/styles.xml +0 -8
  363. package/ios/events/OnDetentChangeEvent.h +0 -28
  364. package/ios/events/OnDetentChangeEvent.mm +0 -30
  365. package/ios/events/OnDidDismissEvent.mm +0 -25
  366. package/ios/events/OnDidPresentEvent.h +0 -28
  367. package/ios/events/OnDidPresentEvent.mm +0 -30
  368. package/ios/events/OnDragBeginEvent.h +0 -28
  369. package/ios/events/OnDragBeginEvent.mm +0 -30
  370. package/ios/events/OnDragChangeEvent.h +0 -28
  371. package/ios/events/OnDragChangeEvent.mm +0 -30
  372. package/ios/events/OnDragEndEvent.h +0 -28
  373. package/ios/events/OnDragEndEvent.mm +0 -30
  374. package/ios/events/OnMountEvent.mm +0 -25
  375. package/ios/events/OnPositionChangeEvent.mm +0 -32
  376. package/ios/events/OnSizeChangeEvent.h +0 -28
  377. package/ios/events/OnSizeChangeEvent.mm +0 -30
  378. package/ios/events/OnWillDismissEvent.mm +0 -25
  379. package/ios/events/OnWillPresentEvent.h +0 -28
  380. package/ios/events/OnWillPresentEvent.mm +0 -30
  381. package/ios/utils/LayoutUtil.h +0 -44
  382. package/ios/utils/LayoutUtil.mm +0 -50
  383. package/lib/module/TrueSheetGrabber.js +0 -51
  384. package/lib/module/TrueSheetGrabber.js.map +0 -1
  385. package/lib/typescript/src/TrueSheetGrabber.d.ts +0 -39
  386. package/lib/typescript/src/TrueSheetGrabber.d.ts.map +0 -1
  387. package/src/TrueSheetGrabber.tsx +0 -82
  388. package/src/__mocks__/index.js +0 -67
@@ -0,0 +1,79 @@
1
+ import type { ParamListBase } from '@react-navigation/native';
2
+
3
+ import type { TrueSheetNavigationProp } from '../navigation/types';
4
+
5
+ /**
6
+ * Mock createTrueSheetNavigator for testing.
7
+ * Import from '@lodev09/react-native-true-sheet/navigation/mock' in your test setup.
8
+ */
9
+ export const createTrueSheetNavigator = jest.fn(() => ({
10
+ Navigator: jest.fn(({ children }: { children: React.ReactNode }) => children),
11
+ Screen: jest.fn(() => null),
12
+ Group: jest.fn(() => null),
13
+ }));
14
+
15
+ /**
16
+ * Mock createTrueSheetScreen for testing the static API.
17
+ */
18
+ export const createTrueSheetScreen = jest.fn((config: object) => config);
19
+
20
+ /**
21
+ * Mock TrueSheetActions for testing.
22
+ */
23
+ export const TrueSheetActions = {
24
+ push: jest.fn((name: string, params?: object) => ({ type: 'PUSH', payload: { name, params } })),
25
+ pop: jest.fn((count?: number) => ({ type: 'POP', payload: { count } })),
26
+ popTo: jest.fn((name: string, params?: object) => ({
27
+ type: 'POP_TO',
28
+ payload: { name, params },
29
+ })),
30
+ popToTop: jest.fn(() => ({ type: 'POP_TO_TOP' })),
31
+ replace: jest.fn((name: string, params?: object) => ({
32
+ type: 'REPLACE',
33
+ payload: { name, params },
34
+ })),
35
+ resize: jest.fn((index: number) => ({ type: 'RESIZE', index })),
36
+ dismiss: jest.fn(() => ({ type: 'DISMISS' })),
37
+ remove: jest.fn(() => ({ type: 'REMOVE' })),
38
+ };
39
+
40
+ /**
41
+ * Mock useTrueSheetNavigation hook for testing.
42
+ */
43
+ export const useTrueSheetNavigation = jest.fn(<T extends ParamListBase = ParamListBase>() => {
44
+ // Partial drops react-navigation's private-brand member (PrivateValueStore),
45
+ // which no mock can implement — the members themselves stay type-checked.
46
+ const navigation: Partial<TrueSheetNavigationProp<T>> = {
47
+ navigate: jest.fn(),
48
+ goBack: jest.fn(),
49
+ reset: jest.fn(),
50
+ setParams: jest.fn(),
51
+ dispatch: jest.fn(),
52
+ isFocused: jest.fn(() => true),
53
+ canGoBack: jest.fn(() => true),
54
+ getId: jest.fn(),
55
+ getParent: jest.fn(),
56
+ getState: jest.fn(),
57
+ addListener: jest.fn(() => jest.fn()),
58
+ removeListener: jest.fn(),
59
+ setOptions: jest.fn(),
60
+ push: jest.fn(),
61
+ pop: jest.fn(),
62
+ popTo: jest.fn(),
63
+ popToTop: jest.fn(),
64
+ replace: jest.fn(),
65
+ resize: jest.fn(),
66
+ };
67
+ return navigation as TrueSheetNavigationProp<T>;
68
+ });
69
+
70
+ export type { TrueSheetActionType } from '../navigation/actions';
71
+ export type { DetentInfoEventPayload, PositionChangeEventPayload } from '../TrueSheet.types';
72
+ export type {
73
+ TrueSheetNavigationEventMap,
74
+ TrueSheetNavigationHelpers,
75
+ TrueSheetNavigationOptions,
76
+ TrueSheetNavigationProp,
77
+ TrueSheetNavigationState,
78
+ TrueSheetScreenProps,
79
+ } from '../navigation/types';
@@ -0,0 +1,40 @@
1
+ import type { ParamListBase } from '@react-navigation/native';
2
+
3
+ import type { TrueSheetNavigationProp } from '../navigation/types';
4
+ import {
5
+ TrueSheetActions,
6
+ useTrueSheetNavigation as useTrueSheetNavigationMock,
7
+ } from './navigation';
8
+
9
+ /**
10
+ * Mock Sheet layout for testing.
11
+ * Import from '@lodev09/react-native-true-sheet/navigation/expo-router/mock' in your test setup.
12
+ */
13
+ export const Sheet = Object.assign(
14
+ jest.fn(({ children }: { children: React.ReactNode }) => children),
15
+ {
16
+ Screen: jest.fn(() => null),
17
+ Protected: jest.fn(() => null),
18
+ }
19
+ );
20
+
21
+ /**
22
+ * Mock useTrueSheetNavigation hook for testing.
23
+ */
24
+ export const useTrueSheetNavigation = jest.fn(
25
+ <T extends ParamListBase = ParamListBase>(): TrueSheetNavigationProp<T> =>
26
+ useTrueSheetNavigationMock() as TrueSheetNavigationProp<T>
27
+ );
28
+
29
+ export { TrueSheetActions };
30
+
31
+ export type { TrueSheetActionType } from '../navigation/actions';
32
+ export type { DetentInfoEventPayload, PositionChangeEventPayload } from '../TrueSheet.types';
33
+ export type {
34
+ TrueSheetNavigationEventMap,
35
+ TrueSheetNavigationHelpers,
36
+ TrueSheetNavigationOptions,
37
+ TrueSheetNavigationProp,
38
+ TrueSheetNavigationState,
39
+ TrueSheetScreenProps,
40
+ } from '../navigation/types';
@@ -0,0 +1,100 @@
1
+ import React, { createElement, isValidElement, type ReactNode } from 'react';
2
+ import { View } from 'react-native';
3
+ import type { SharedValue } from 'react-native-reanimated';
4
+
5
+ import type { TrueSheetProps, PositionChangeEventPayload } from '../TrueSheet.types';
6
+
7
+ interface TrueSheetState {
8
+ shouldRenderNativeView: boolean;
9
+ }
10
+
11
+ interface MockReanimatedTrueSheetContextValue {
12
+ animatedPosition: SharedValue<number>;
13
+ animatedIndex: SharedValue<number>;
14
+ animatedDetent: SharedValue<number>;
15
+ }
16
+
17
+ const createMockSharedValue = <T>(initialValue: T): SharedValue<T> => ({
18
+ value: initialValue,
19
+ get: () => initialValue,
20
+ set: () => {},
21
+ addListener: () => {},
22
+ removeListener: () => {},
23
+ modify: () => {},
24
+ });
25
+
26
+ /**
27
+ * Mock ReanimatedTrueSheet component for testing.
28
+ * Import from '@lodev09/react-native-true-sheet/reanimated/mock' in your test setup.
29
+ */
30
+ export class ReanimatedTrueSheet extends React.Component<TrueSheetProps, TrueSheetState> {
31
+ static instances: Record<string, ReanimatedTrueSheet> = {};
32
+
33
+ static dismiss = jest.fn((_name: string, _animated?: boolean) => Promise.resolve());
34
+ static dismissStack = jest.fn((_name: string, _animated?: boolean) => Promise.resolve());
35
+ static present = jest.fn((_name: string, _index?: number, _animated?: boolean) =>
36
+ Promise.resolve()
37
+ );
38
+ static resize = jest.fn((_name: string, _index: number) => Promise.resolve());
39
+
40
+ dismiss = jest.fn((_animated?: boolean) => Promise.resolve());
41
+ dismissStack = jest.fn((_animated?: boolean) => Promise.resolve());
42
+ present = jest.fn((_index?: number, _animated?: boolean) => Promise.resolve());
43
+ resize = jest.fn((_index: number) => Promise.resolve());
44
+
45
+ componentDidMount() {
46
+ const { name } = this.props;
47
+ if (name) {
48
+ ReanimatedTrueSheet.instances[name] = this;
49
+ }
50
+ }
51
+
52
+ componentWillUnmount() {
53
+ const { name } = this.props;
54
+ if (name) {
55
+ delete ReanimatedTrueSheet.instances[name];
56
+ }
57
+ }
58
+
59
+ private renderHeader(): ReactNode {
60
+ const { header } = this.props;
61
+ if (!header) return null;
62
+ return isValidElement(header) ? header : createElement(header);
63
+ }
64
+
65
+ private renderFooter(): ReactNode {
66
+ const { footer } = this.props;
67
+ if (!footer) return null;
68
+ return isValidElement(footer) ? footer : createElement(footer);
69
+ }
70
+
71
+ render() {
72
+ const { children, style } = this.props;
73
+ return React.createElement(View, { style }, this.renderHeader(), children, this.renderFooter());
74
+ }
75
+ }
76
+
77
+ /**
78
+ * Mock ReanimatedTrueSheetProvider for testing.
79
+ */
80
+ export function ReanimatedTrueSheetProvider({ children }: { children: React.ReactNode }) {
81
+ return children;
82
+ }
83
+
84
+ /**
85
+ * Mock useReanimatedTrueSheet hook for testing.
86
+ */
87
+ export const useReanimatedTrueSheet = jest.fn(
88
+ (): MockReanimatedTrueSheetContextValue => ({
89
+ animatedPosition: createMockSharedValue(0),
90
+ animatedIndex: createMockSharedValue(-1),
91
+ animatedDetent: createMockSharedValue(0),
92
+ })
93
+ );
94
+
95
+ /**
96
+ * Mock useReanimatedPositionChangeHandler hook for testing.
97
+ */
98
+ export const useReanimatedPositionChangeHandler = jest.fn(
99
+ (_handler: (payload: PositionChangeEventPayload) => void, _dependencies?: unknown[]) => jest.fn()
100
+ );
@@ -0,0 +1,106 @@
1
+ import type { NavigatorArgs } from 'standard-navigation';
2
+
3
+ import type {
4
+ TrueSheetNavigationOptions,
5
+ TrueSheetNavigatorContentExtraProps,
6
+ TrueSheetStandardEventMap,
7
+ } from './types';
8
+ import { TrueSheetScreen, type TrueSheetScreenProps } from './screen';
9
+
10
+ let ReanimatedTrueSheetScreen: React.ComponentType<TrueSheetScreenProps> | null = null;
11
+
12
+ const getReanimatedScreen = (): React.ComponentType<TrueSheetScreenProps> => {
13
+ if (!ReanimatedTrueSheetScreen) {
14
+ ReanimatedTrueSheetScreen =
15
+ require('./screen/ReanimatedTrueSheetScreen').ReanimatedTrueSheetScreen;
16
+ }
17
+ return ReanimatedTrueSheetScreen!;
18
+ };
19
+
20
+ const DEFAULT_DETENTS: ('auto' | number)[] = ['auto'];
21
+
22
+ const clampDetentIndex = (index: number, detentsLength: number): number =>
23
+ Math.min(index, Math.max(detentsLength - 1, 0));
24
+
25
+ export type TrueSheetNavigatorContentProps = NavigatorArgs<
26
+ TrueSheetNavigationOptions,
27
+ TrueSheetStandardEventMap
28
+ > &
29
+ TrueSheetNavigatorContentExtraProps;
30
+
31
+ export const TrueSheetNavigatorContent = ({
32
+ routes,
33
+ dispatch,
34
+ descriptors,
35
+ emitter,
36
+ }: TrueSheetNavigatorContentProps) => {
37
+ // First route is the base screen, rest are sheets.
38
+ // Rendered from the raw routes (not the standard state) so custom fields are
39
+ // available and preloaded routes never present as sheets.
40
+ const [baseRoute, ...sheetRoutes] = routes;
41
+
42
+ const baseDescriptor = baseRoute ? descriptors[baseRoute.key] : null;
43
+
44
+ return (
45
+ <>
46
+ {/* Render base screen */}
47
+ {baseDescriptor?.render()}
48
+
49
+ {/* Render sheet screens */}
50
+ {sheetRoutes.map((route) => {
51
+ const descriptor = descriptors[route.key];
52
+
53
+ if (!descriptor) {
54
+ return null;
55
+ }
56
+
57
+ const { options, render } = descriptor;
58
+ const {
59
+ detentIndex = 0,
60
+ detents = DEFAULT_DETENTS,
61
+ reanimated,
62
+ positionChangeHandler,
63
+ ...sheetProps
64
+ } = options;
65
+ const resolvedIndex = clampDetentIndex(route.resizeIndex ?? detentIndex, detents.length);
66
+
67
+ if (reanimated) {
68
+ const ReanimatedScreen = getReanimatedScreen();
69
+ return (
70
+ <ReanimatedScreen
71
+ key={route.key}
72
+ routeKey={route.key}
73
+ closing={route.closing}
74
+ detentIndex={resolvedIndex}
75
+ resizeKey={route.resizeKey}
76
+ detents={detents}
77
+ dispatch={dispatch}
78
+ emit={emitter.emit}
79
+ positionChangeHandler={positionChangeHandler}
80
+ {...sheetProps}
81
+ >
82
+ {render()}
83
+ </ReanimatedScreen>
84
+ );
85
+ }
86
+
87
+ return (
88
+ <TrueSheetScreen
89
+ key={route.key}
90
+ routeKey={route.key}
91
+ closing={route.closing}
92
+ detentIndex={resolvedIndex}
93
+ resizeKey={route.resizeKey}
94
+ detents={detents}
95
+ dispatch={dispatch}
96
+ emit={emitter.emit}
97
+ positionChangeHandler={positionChangeHandler}
98
+ {...sheetProps}
99
+ >
100
+ {render()}
101
+ </TrueSheetScreen>
102
+ );
103
+ })}
104
+ </>
105
+ );
106
+ };
@@ -0,0 +1,78 @@
1
+ export type TrueSheetActionType =
2
+ | {
3
+ type: 'PUSH';
4
+ payload: { name: string; params?: object };
5
+ source?: string;
6
+ target?: string;
7
+ }
8
+ | {
9
+ type: 'POP';
10
+ payload: { count: number };
11
+ source?: string;
12
+ target?: string;
13
+ }
14
+ | {
15
+ type: 'POP_TO';
16
+ payload: { name: string; params?: object; merge?: boolean };
17
+ source?: string;
18
+ target?: string;
19
+ }
20
+ | {
21
+ type: 'POP_TO_TOP';
22
+ source?: string;
23
+ target?: string;
24
+ }
25
+ | {
26
+ type: 'REPLACE';
27
+ payload: { name: string; params?: object };
28
+ source?: string;
29
+ target?: string;
30
+ }
31
+ | {
32
+ type: 'GO_BACK';
33
+ source?: string;
34
+ target?: string;
35
+ }
36
+ | {
37
+ type: 'RESIZE';
38
+ index: number;
39
+ source?: string;
40
+ target?: string;
41
+ }
42
+ | {
43
+ type: 'DISMISS';
44
+ source?: string;
45
+ target?: string;
46
+ }
47
+ | {
48
+ type: 'REMOVE';
49
+ source?: string;
50
+ target?: string;
51
+ };
52
+
53
+ /**
54
+ * Action creators for the TrueSheet navigator.
55
+ * Plain objects matching `StackActions` shapes, plus sheet-specific actions.
56
+ */
57
+ export const TrueSheetActions = {
58
+ push: (name: string, params?: object): TrueSheetActionType => ({
59
+ type: 'PUSH',
60
+ payload: { name, params },
61
+ }),
62
+ pop: (count: number = 1): TrueSheetActionType => ({
63
+ type: 'POP',
64
+ payload: { count },
65
+ }),
66
+ popTo: (name: string, params?: object, options?: { merge?: boolean }): TrueSheetActionType => ({
67
+ type: 'POP_TO',
68
+ payload: { name, params, merge: options?.merge },
69
+ }),
70
+ popToTop: (): TrueSheetActionType => ({ type: 'POP_TO_TOP' }),
71
+ replace: (name: string, params?: object): TrueSheetActionType => ({
72
+ type: 'REPLACE',
73
+ payload: { name, params },
74
+ }),
75
+ resize: (index: number): TrueSheetActionType => ({ type: 'RESIZE', index }),
76
+ dismiss: (): TrueSheetActionType => ({ type: 'DISMISS' }),
77
+ remove: (): TrueSheetActionType => ({ type: 'REMOVE' }),
78
+ };
@@ -0,0 +1,222 @@
1
+ import type {
2
+ NavigationAction,
3
+ NavigationState,
4
+ ParamListBase,
5
+ Router,
6
+ StackRouterOptions,
7
+ } from '@react-navigation/core';
8
+
9
+ import { TrueSheetActions, type TrueSheetActionType } from './actions';
10
+ import type { TrueSheetNavigationState } from './types';
11
+
12
+ export type TrueSheetRouterOptions = StackRouterOptions;
13
+
14
+ /**
15
+ * The base `StackRouter` factory to wrap, typed generically over the state and
16
+ * action types the wrapper threads through — `StackRouter` is structural and
17
+ * never touches the sheet-specific fields.
18
+ * Injected by each entry point so the shared router never imports
19
+ * `@react-navigation/*` at runtime (Expo Router apps don't install it).
20
+ */
21
+ export type StackRouterFactory = <
22
+ State extends NavigationState<ParamListBase>,
23
+ Action extends NavigationAction,
24
+ >(
25
+ options: TrueSheetRouterOptions
26
+ ) => Router<State, Action>;
27
+
28
+ const uid = () => Math.random().toString(36).slice(2, 10);
29
+
30
+ const ensureBaseRoute = <T extends { routes: { name: string }[] }>(
31
+ state: T,
32
+ baseRouteName: string | undefined,
33
+ routeParamList: Record<string, object | undefined> | undefined
34
+ ): T & { index: number; routes: T['routes'] } => {
35
+ if (!baseRouteName) {
36
+ return state as T & { index: number; routes: T['routes'] };
37
+ }
38
+
39
+ const hasBaseRoute = state.routes.some((r) => r.name === baseRouteName);
40
+
41
+ if (!hasBaseRoute) {
42
+ const baseRoute = {
43
+ key: `${baseRouteName}-${uid()}`,
44
+ name: baseRouteName,
45
+ params: routeParamList?.[baseRouteName],
46
+ };
47
+
48
+ return {
49
+ ...state,
50
+ index: state.routes.length,
51
+ routes: [baseRoute, ...state.routes],
52
+ } as T & { index: number; routes: T['routes'] };
53
+ }
54
+
55
+ return state as T & { index: number; routes: T['routes'] };
56
+ };
57
+
58
+ export const createTrueSheetRouter =
59
+ (stackRouter: StackRouterFactory) =>
60
+ (
61
+ routerOptions: TrueSheetRouterOptions
62
+ ): Router<TrueSheetNavigationState<ParamListBase>, TrueSheetActionType> => {
63
+ const baseRouter = stackRouter<TrueSheetNavigationState<ParamListBase>, TrueSheetActionType>(
64
+ routerOptions
65
+ );
66
+
67
+ return {
68
+ ...baseRouter,
69
+ type: 'true-sheet',
70
+
71
+ getInitialState(options) {
72
+ const state = baseRouter.getInitialState(options);
73
+ const baseRouteName = routerOptions.initialRouteName ?? options.routeNames[0];
74
+ const stateWithBaseRoute = ensureBaseRoute(state, baseRouteName, options.routeParamList);
75
+
76
+ return {
77
+ ...stateWithBaseRoute,
78
+ stale: false,
79
+ type: 'true-sheet',
80
+ key: `true-sheet-${uid()}`,
81
+ };
82
+ },
83
+
84
+ getStateForAction(state, action, options) {
85
+ switch (action.type) {
86
+ case 'RESIZE': {
87
+ const routeIndex =
88
+ action.target === state.key && action.source
89
+ ? state.routes.findIndex((r) => r.key === action.source)
90
+ : state.index;
91
+
92
+ return {
93
+ ...state,
94
+ routes: state.routes.map((route, i) =>
95
+ i === routeIndex
96
+ ? {
97
+ ...route,
98
+ resizeIndex: action.index,
99
+ resizeKey: (route.resizeKey ?? 0) + 1,
100
+ }
101
+ : route
102
+ ),
103
+ };
104
+ }
105
+
106
+ case 'GO_BACK':
107
+ case 'DISMISS': {
108
+ return this.getStateForAction(state, TrueSheetActions.pop(1), options);
109
+ }
110
+
111
+ case 'POP': {
112
+ // Only base screen remains - let parent navigator handle it
113
+ if (state.routes.length <= 1) {
114
+ return null;
115
+ }
116
+
117
+ const count =
118
+ 'payload' in action && typeof action.payload?.count === 'number'
119
+ ? action.payload.count
120
+ : 1;
121
+
122
+ // Calculate how many routes we can actually pop (don't pop base screen)
123
+ const maxPopCount = state.routes.length - 1;
124
+ const actualCount = Math.min(count, maxPopCount);
125
+
126
+ // Base screen - let parent navigator handle it
127
+ if (actualCount <= 0) {
128
+ return null;
129
+ }
130
+
131
+ // Target index is the route we want to stay on (land on after pop)
132
+ // closingIndex is the first route to be dismissed (the one after target)
133
+ const targetIndex = state.routes.length - 1 - actualCount;
134
+ const closingIndex = targetIndex + 1;
135
+
136
+ // Mark only the bottom-most route to pop as closing
137
+ // The sheet's dismiss() will handle dismissing sheets above it first
138
+ return {
139
+ ...state,
140
+ index: closingIndex,
141
+ routes: state.routes.map((route, i) =>
142
+ i === closingIndex ? { ...route, closing: true } : route
143
+ ),
144
+ };
145
+ }
146
+
147
+ case 'POP_TO_TOP': {
148
+ const popCount = state.routes.length - 1;
149
+ return this.getStateForAction(state, TrueSheetActions.pop(popCount), options);
150
+ }
151
+
152
+ case 'POP_TO': {
153
+ const targetName =
154
+ 'payload' in action && typeof action.payload?.name === 'string'
155
+ ? action.payload.name
156
+ : null;
157
+
158
+ if (!targetName) {
159
+ return null;
160
+ }
161
+
162
+ const targetIndex = state.routes.findIndex((r) => r.name === targetName);
163
+
164
+ // Target not found or is the current route
165
+ if (targetIndex === -1 || targetIndex >= state.index) {
166
+ return null;
167
+ }
168
+
169
+ const popCount = state.routes.length - 1 - targetIndex;
170
+ return this.getStateForAction(state, TrueSheetActions.pop(popCount), options);
171
+ }
172
+
173
+ case 'REMOVE': {
174
+ // Actually remove the closing route and all routes above it
175
+ const routeKey = action.source;
176
+ const routeIndex = routeKey
177
+ ? state.routes.findIndex((r) => r.key === routeKey)
178
+ : state.routes.findIndex((r) => r.closing);
179
+
180
+ if (routeIndex === -1) {
181
+ return state;
182
+ }
183
+
184
+ // Remove the route and all routes above it (they were dismissed together)
185
+ const routes = state.routes.filter((_, i) => i < routeIndex);
186
+
187
+ return {
188
+ ...state,
189
+ index: Math.min(state.index, routes.length - 1),
190
+ routes,
191
+ };
192
+ }
193
+
194
+ default:
195
+ return baseRouter.getStateForAction(state, action, options);
196
+ }
197
+ },
198
+
199
+ getRehydratedState(partialState, { routeNames, routeParamList, routeGetIdList }) {
200
+ if (partialState.stale === false) {
201
+ return partialState;
202
+ }
203
+
204
+ const state = baseRouter.getRehydratedState(partialState, {
205
+ routeNames,
206
+ routeParamList,
207
+ routeGetIdList,
208
+ });
209
+
210
+ const baseRouteName = routerOptions.initialRouteName ?? routeNames[0];
211
+ const stateWithBaseRoute = ensureBaseRoute(state, baseRouteName, routeParamList);
212
+
213
+ return {
214
+ ...stateWithBaseRoute,
215
+ type: 'true-sheet',
216
+ key: `true-sheet-${uid()}`,
217
+ };
218
+ },
219
+
220
+ actionCreators: TrueSheetActions,
221
+ };
222
+ };