@lodev09/react-native-true-sheet 4.0.0-beta.0 → 4.0.0-beta.10
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.
- package/LICENSE +1 -1
- package/README.md +62 -30
- package/RNTrueSheet.podspec +10 -2
- package/android/build.gradle +24 -2
- package/android/src/main/java/com/lodev09/truesheet/TrueSheetContainerView.kt +189 -47
- package/android/src/main/java/com/lodev09/truesheet/TrueSheetContainerViewManager.kt +7 -0
- package/android/src/main/java/com/lodev09/truesheet/TrueSheetContentView.kt +401 -19
- package/android/src/main/java/com/lodev09/truesheet/TrueSheetContentViewManager.kt +18 -0
- package/android/src/main/java/com/lodev09/truesheet/TrueSheetFooterView.kt +145 -21
- package/android/src/main/java/com/lodev09/truesheet/TrueSheetFooterViewManager.kt +14 -0
- package/android/src/main/java/com/lodev09/truesheet/TrueSheetHeaderView.kt +38 -0
- package/android/src/main/java/com/lodev09/truesheet/TrueSheetHeaderViewManager.kt +28 -0
- package/android/src/main/java/com/lodev09/truesheet/TrueSheetModule.kt +84 -24
- package/android/src/main/java/com/lodev09/truesheet/TrueSheetOverlayView.kt +106 -0
- package/android/src/main/java/com/lodev09/truesheet/TrueSheetOverlayViewManager.kt +45 -0
- package/android/src/main/java/com/lodev09/truesheet/TrueSheetPackage.kt +6 -4
- package/android/src/main/java/com/lodev09/truesheet/TrueSheetPeekView.kt +72 -0
- package/android/src/main/java/com/lodev09/truesheet/TrueSheetPeekViewManager.kt +33 -0
- package/android/src/main/java/com/lodev09/truesheet/TrueSheetStateUpdater.kt +63 -0
- package/android/src/main/java/com/lodev09/truesheet/TrueSheetView.kt +564 -226
- package/android/src/main/java/com/lodev09/truesheet/TrueSheetViewController.kt +1399 -598
- package/android/src/main/java/com/lodev09/truesheet/TrueSheetViewManager.kt +161 -29
- package/android/src/main/java/com/lodev09/truesheet/core/RNScreensEventObserver.kt +63 -0
- package/android/src/main/java/com/lodev09/truesheet/core/TrueSheetBottomSheetBehavior.kt +36 -0
- package/android/src/main/java/com/lodev09/truesheet/core/TrueSheetBottomSheetView.kt +255 -0
- package/android/src/main/java/com/lodev09/truesheet/core/TrueSheetCoordinatorLayout.kt +375 -0
- package/android/src/main/java/com/lodev09/truesheet/core/TrueSheetDetentCalculator.kt +299 -0
- package/android/src/main/java/com/lodev09/truesheet/core/TrueSheetDimView.kt +162 -0
- package/android/src/main/java/com/lodev09/truesheet/core/TrueSheetGrabberView.kt +180 -0
- package/android/src/main/java/com/lodev09/truesheet/core/TrueSheetKeyboardObserver.kt +207 -0
- package/android/src/main/java/com/lodev09/truesheet/core/TrueSheetOverlayRootView.kt +137 -0
- package/android/src/main/java/com/lodev09/truesheet/core/TrueSheetStackManager.kt +220 -0
- package/android/src/main/java/com/lodev09/truesheet/events/TrueSheetDragEvents.kt +71 -0
- package/android/src/main/java/com/lodev09/truesheet/events/TrueSheetFocusEvents.kt +65 -0
- package/android/src/main/java/com/lodev09/truesheet/events/TrueSheetLifecycleEvents.kt +127 -0
- package/android/src/main/java/com/lodev09/truesheet/events/TrueSheetStateEvents.kt +56 -0
- package/android/src/main/java/com/lodev09/truesheet/utils/KeyboardUtils.kt +84 -0
- package/android/src/main/java/com/lodev09/truesheet/utils/ScreenUtils.kt +93 -67
- package/android/src/main/java/com/lodev09/truesheet/utils/TouchEventDeduper.kt +31 -0
- package/android/src/main/java/com/lodev09/truesheet/utils/ViewUtils.kt +42 -0
- package/android/src/main/jni/CMakeLists.txt +63 -0
- package/android/src/main/jni/TrueSheetSpec.h +20 -0
- package/android/src/main/jni/TrueSheetStateUpdater.cpp +96 -0
- package/common/cpp/react/renderer/components/TrueSheetSpec/TrueSheetContentViewComponentDescriptor.h +16 -0
- package/common/cpp/react/renderer/components/TrueSheetSpec/TrueSheetContentViewShadowNode.cpp +68 -0
- package/common/cpp/react/renderer/components/TrueSheetSpec/TrueSheetContentViewShadowNode.h +33 -0
- package/common/cpp/react/renderer/components/TrueSheetSpec/TrueSheetContentViewState.cpp +11 -0
- package/common/cpp/react/renderer/components/TrueSheetSpec/TrueSheetContentViewState.h +39 -0
- package/common/cpp/react/renderer/components/TrueSheetSpec/TrueSheetFooterViewComponentDescriptor.h +24 -0
- package/common/cpp/react/renderer/components/TrueSheetSpec/TrueSheetFooterViewShadowNode.cpp +63 -0
- package/common/cpp/react/renderer/components/TrueSheetSpec/TrueSheetFooterViewShadowNode.h +28 -0
- package/common/cpp/react/renderer/components/TrueSheetSpec/TrueSheetFooterViewState.cpp +11 -0
- package/common/cpp/react/renderer/components/TrueSheetSpec/TrueSheetFooterViewState.h +41 -0
- package/common/cpp/react/renderer/components/TrueSheetSpec/TrueSheetInsets.cpp +18 -0
- package/common/cpp/react/renderer/components/TrueSheetSpec/TrueSheetInsets.h +16 -0
- package/common/cpp/react/renderer/components/TrueSheetSpec/TrueSheetLayoutUtils.h +46 -0
- package/common/cpp/react/renderer/components/TrueSheetSpec/TrueSheetOverlayViewComponentDescriptor.h +21 -0
- package/common/cpp/react/renderer/components/TrueSheetSpec/TrueSheetOverlayViewShadowNode.cpp +17 -0
- package/common/cpp/react/renderer/components/TrueSheetSpec/TrueSheetOverlayViewShadowNode.h +36 -0
- package/common/cpp/react/renderer/components/TrueSheetSpec/TrueSheetViewComponentDescriptor.h +28 -0
- package/common/cpp/react/renderer/components/TrueSheetSpec/TrueSheetViewShadowNode.cpp +30 -0
- package/common/cpp/react/renderer/components/TrueSheetSpec/TrueSheetViewShadowNode.h +45 -0
- package/common/cpp/react/renderer/components/TrueSheetSpec/TrueSheetViewState.cpp +23 -0
- package/common/cpp/react/renderer/components/TrueSheetSpec/TrueSheetViewState.h +52 -0
- package/ios/TrueSheetContainerView.h +88 -6
- package/ios/TrueSheetContainerView.mm +278 -21
- package/ios/TrueSheetContentView.h +54 -1
- package/ios/TrueSheetContentView.mm +371 -47
- package/ios/TrueSheetFooterView.h +33 -2
- package/ios/TrueSheetFooterView.mm +187 -35
- package/ios/{events/OnWillDismissEvent.h → TrueSheetHeaderView.h} +10 -7
- package/ios/TrueSheetHeaderView.mm +64 -0
- package/ios/TrueSheetModule.h +2 -7
- package/ios/TrueSheetModule.mm +98 -20
- package/ios/TrueSheetOverlayView.h +32 -0
- package/ios/TrueSheetOverlayView.mm +161 -0
- package/ios/TrueSheetPeekView.h +32 -0
- package/ios/TrueSheetPeekView.mm +99 -0
- package/ios/TrueSheetView.h +7 -15
- package/ios/TrueSheetView.mm +775 -215
- package/ios/TrueSheetViewController.h +94 -16
- package/ios/TrueSheetViewController.mm +1316 -331
- package/ios/core/RNScreensEventObserver.h +46 -0
- package/ios/core/RNScreensEventObserver.mm +280 -0
- package/ios/core/TrueSheetBlurView.h +27 -0
- package/ios/core/TrueSheetBlurView.mm +82 -0
- package/ios/core/TrueSheetDetentCalculator.h +107 -0
- package/ios/core/TrueSheetDetentCalculator.mm +197 -0
- package/ios/core/TrueSheetGrabberView.h +72 -0
- package/ios/core/TrueSheetGrabberView.mm +188 -0
- package/ios/core/TrueSheetKeyboardObserver.h +39 -0
- package/ios/core/TrueSheetKeyboardObserver.mm +112 -0
- package/ios/core/TrueSheetOverlayContainerView.h +31 -0
- package/ios/core/TrueSheetOverlayContainerView.mm +35 -0
- package/ios/events/TrueSheetDragEvents.h +39 -0
- package/ios/events/TrueSheetDragEvents.mm +62 -0
- package/ios/events/{OnPositionChangeEvent.h → TrueSheetFocusEvents.h} +8 -5
- package/ios/events/TrueSheetFocusEvents.mm +49 -0
- package/ios/events/TrueSheetLifecycleEvents.h +42 -0
- package/ios/events/TrueSheetLifecycleEvents.mm +79 -0
- package/ios/events/TrueSheetStateEvents.h +35 -0
- package/ios/events/TrueSheetStateEvents.mm +49 -0
- package/ios/tvos/TrueSheetStubs.mm +166 -0
- package/ios/{events/OnMountEvent.h → utils/BlurUtil.h} +5 -7
- package/ios/utils/BlurUtil.mm +69 -0
- package/ios/utils/GestureUtil.h +7 -0
- package/ios/utils/GestureUtil.mm +12 -0
- package/ios/utils/PlatformUtil.h +15 -0
- package/ios/utils/UIView+FirstResponder.h +15 -0
- package/ios/utils/UIView+FirstResponder.mm +26 -0
- package/ios/utils/UIView+ScrollEdgeInteraction.h +26 -0
- package/ios/utils/UIView+ScrollEdgeInteraction.mm +84 -0
- package/ios/utils/WindowUtil.mm +17 -1
- package/lib/module/TrueSheet.js +349 -74
- package/lib/module/TrueSheet.js.map +1 -1
- package/lib/module/TrueSheet.web.js +1270 -0
- package/lib/module/TrueSheet.web.js.map +1 -0
- package/lib/module/TrueSheetOverlay.js +30 -0
- package/lib/module/TrueSheetOverlay.js.map +1 -0
- package/lib/module/TrueSheetOverlay.web.js +35 -0
- package/lib/module/TrueSheetOverlay.web.js.map +1 -0
- package/lib/module/TrueSheetPeek.js +15 -0
- package/lib/module/TrueSheetPeek.js.map +1 -0
- package/lib/module/TrueSheetPeek.web.js +55 -0
- package/lib/module/TrueSheetPeek.web.js.map +1 -0
- package/lib/module/TrueSheetProvider.js +28 -0
- package/lib/module/TrueSheetProvider.js.map +1 -0
- package/lib/module/TrueSheetProvider.web.js +157 -0
- package/lib/module/TrueSheetProvider.web.js.map +1 -0
- package/lib/module/fabric/TrueSheetContainerViewNativeComponent.ts +1 -1
- package/lib/module/fabric/TrueSheetContentViewNativeComponent.ts +5 -1
- package/lib/module/fabric/TrueSheetFooterViewNativeComponent.ts +10 -2
- package/lib/module/fabric/TrueSheetHeaderViewNativeComponent.ts +8 -0
- package/lib/module/fabric/TrueSheetOverlayViewNativeComponent.ts +12 -0
- package/lib/module/fabric/TrueSheetPeekViewNativeComponent.ts +8 -0
- package/lib/module/fabric/TrueSheetViewNativeComponent.ts +110 -18
- package/lib/module/index.js +4 -3
- package/lib/module/index.js.map +1 -1
- package/lib/module/mocks/index.js +103 -0
- package/lib/module/mocks/index.js.map +1 -0
- package/lib/module/mocks/navigation.js +95 -0
- package/lib/module/mocks/navigation.js.map +1 -0
- package/lib/module/mocks/navigationExpoRouter.js +21 -0
- package/lib/module/mocks/navigationExpoRouter.js.map +1 -0
- package/lib/module/mocks/reanimated.js +91 -0
- package/lib/module/mocks/reanimated.js.map +1 -0
- package/lib/module/navigation/TrueSheetNavigatorContent.js +73 -0
- package/lib/module/navigation/TrueSheetNavigatorContent.js.map +1 -0
- package/lib/module/navigation/actions.js +50 -0
- package/lib/module/navigation/actions.js.map +1 -0
- package/lib/module/navigation/base-types.js +2 -0
- package/lib/module/navigation/base-types.js.map +1 -0
- package/lib/module/navigation/createTrueSheetRouter.js +157 -0
- package/lib/module/navigation/createTrueSheetRouter.js.map +1 -0
- package/lib/module/navigation/expo-router/base-types.js +2 -0
- package/lib/module/navigation/expo-router/base-types.js.map +1 -0
- package/lib/module/navigation/expo-router/index.js +50 -0
- package/lib/module/navigation/expo-router/index.js.map +1 -0
- package/lib/module/navigation/expo-router/types.js +4 -0
- package/lib/module/navigation/expo-router/types.js.map +1 -0
- package/lib/module/navigation/index.js +47 -0
- package/lib/module/navigation/index.js.map +1 -0
- package/lib/module/navigation/navigator.js +10 -0
- package/lib/module/navigation/navigator.js.map +1 -0
- package/lib/module/navigation/screen/ReanimatedTrueSheetScreen.js +56 -0
- package/lib/module/navigation/screen/ReanimatedTrueSheetScreen.js.map +1 -0
- package/lib/module/navigation/screen/TrueSheetScreen.js +49 -0
- package/lib/module/navigation/screen/TrueSheetScreen.js.map +1 -0
- package/lib/module/navigation/screen/index.js +5 -0
- package/lib/module/navigation/screen/index.js.map +1 -0
- package/lib/module/navigation/screen/types.js +4 -0
- package/lib/module/navigation/screen/types.js.map +1 -0
- package/lib/module/navigation/screen/useSheetScreenState.js +69 -0
- package/lib/module/navigation/screen/useSheetScreenState.js.map +1 -0
- package/lib/module/navigation/types.js +4 -0
- package/lib/module/navigation/types.js.map +1 -0
- package/lib/module/navigation/useTrueSheetNavigation.js +24 -0
- package/lib/module/navigation/useTrueSheetNavigation.js.map +1 -0
- package/lib/module/reanimated/ReanimatedTrueSheet.js +15 -9
- package/lib/module/reanimated/ReanimatedTrueSheet.js.map +1 -1
- package/lib/module/reanimated/ReanimatedTrueSheet.web.js +81 -0
- package/lib/module/reanimated/ReanimatedTrueSheet.web.js.map +1 -0
- package/lib/module/reanimated/ReanimatedTrueSheetProvider.js +4 -2
- package/lib/module/reanimated/ReanimatedTrueSheetProvider.js.map +1 -1
- package/lib/module/reanimated/index.js +2 -2
- package/lib/module/reanimated/index.js.map +1 -1
- package/lib/module/reanimated/useReanimatedPositionChangeHandler.web.js +20 -0
- package/lib/module/reanimated/useReanimatedPositionChangeHandler.web.js.map +1 -0
- package/lib/module/specs/NativeTrueSheetModule.js.map +1 -1
- package/lib/module/web/constants.js +16 -0
- package/lib/module/web/constants.js.map +1 -0
- package/lib/module/web/dom.js +10 -0
- package/lib/module/web/dom.js.map +1 -0
- package/lib/module/web/vaul/README.md +9 -0
- package/lib/module/web/vaul/browser.js +30 -0
- package/lib/module/web/vaul/browser.js.map +1 -0
- package/lib/module/web/vaul/constants.js +19 -0
- package/lib/module/web/vaul/constants.js.map +1 -0
- package/lib/module/web/vaul/context.js +59 -0
- package/lib/module/web/vaul/context.js.map +1 -0
- package/lib/module/web/vaul/helpers.js +99 -0
- package/lib/module/web/vaul/helpers.js.map +1 -0
- package/lib/module/web/vaul/index.js +1342 -0
- package/lib/module/web/vaul/index.js.map +1 -0
- package/lib/module/web/vaul/style.css +287 -0
- package/lib/module/web/vaul/style.css.d.js +2 -0
- package/lib/module/web/vaul/style.css.d.js.map +1 -0
- package/lib/module/web/vaul/types.js +2 -0
- package/lib/module/web/vaul/types.js.map +1 -0
- package/lib/module/web/vaul/use-composed-refs.js +34 -0
- package/lib/module/web/vaul/use-composed-refs.js.map +1 -0
- package/lib/module/web/vaul/use-controllable-state.js +54 -0
- package/lib/module/web/vaul/use-controllable-state.js.map +1 -0
- package/lib/module/web/vaul/use-position-fixed.js +123 -0
- package/lib/module/web/vaul/use-position-fixed.js.map +1 -0
- package/lib/module/web/vaul/use-prevent-scroll.js +258 -0
- package/lib/module/web/vaul/use-prevent-scroll.js.map +1 -0
- package/lib/module/web/vaul/use-scale-background.js +57 -0
- package/lib/module/web/vaul/use-scale-background.js.map +1 -0
- package/lib/module/web/vaul/use-snap-points.js +305 -0
- package/lib/module/web/vaul/use-snap-points.js.map +1 -0
- package/lib/typescript/src/TrueSheet.d.ts +57 -14
- package/lib/typescript/src/TrueSheet.d.ts.map +1 -1
- package/lib/typescript/src/TrueSheet.types.d.ts +535 -55
- package/lib/typescript/src/TrueSheet.types.d.ts.map +1 -1
- package/lib/typescript/src/TrueSheet.web.d.ts +5 -0
- package/lib/typescript/src/TrueSheet.web.d.ts.map +1 -0
- package/lib/typescript/src/TrueSheetOverlay.d.ts +8 -0
- package/lib/typescript/src/TrueSheetOverlay.d.ts.map +1 -0
- package/lib/typescript/src/TrueSheetOverlay.web.d.ts +8 -0
- package/lib/typescript/src/TrueSheetOverlay.web.d.ts.map +1 -0
- package/lib/typescript/src/TrueSheetPeek.d.ts +9 -0
- package/lib/typescript/src/TrueSheetPeek.d.ts.map +1 -0
- package/lib/typescript/src/TrueSheetPeek.web.d.ts +28 -0
- package/lib/typescript/src/TrueSheetPeek.web.d.ts.map +1 -0
- package/lib/typescript/src/TrueSheetProvider.d.ts +18 -0
- package/lib/typescript/src/TrueSheetProvider.d.ts.map +1 -0
- package/lib/typescript/src/TrueSheetProvider.web.d.ts +27 -0
- package/lib/typescript/src/TrueSheetProvider.web.d.ts.map +1 -0
- package/lib/typescript/src/fabric/TrueSheetContainerViewNativeComponent.d.ts.map +1 -1
- package/lib/typescript/src/fabric/TrueSheetContentViewNativeComponent.d.ts.map +1 -1
- package/lib/typescript/src/fabric/TrueSheetFooterViewNativeComponent.d.ts +2 -0
- package/lib/typescript/src/fabric/TrueSheetFooterViewNativeComponent.d.ts.map +1 -1
- package/lib/typescript/src/fabric/TrueSheetHeaderViewNativeComponent.d.ts +6 -0
- package/lib/typescript/src/fabric/TrueSheetHeaderViewNativeComponent.d.ts.map +1 -0
- package/lib/typescript/src/fabric/TrueSheetOverlayViewNativeComponent.d.ts +6 -0
- package/lib/typescript/src/fabric/TrueSheetOverlayViewNativeComponent.d.ts.map +1 -0
- package/lib/typescript/src/fabric/TrueSheetPeekViewNativeComponent.d.ts +6 -0
- package/lib/typescript/src/fabric/TrueSheetPeekViewNativeComponent.d.ts.map +1 -0
- package/lib/typescript/src/fabric/TrueSheetViewNativeComponent.d.ts +71 -16
- package/lib/typescript/src/fabric/TrueSheetViewNativeComponent.d.ts.map +1 -1
- package/lib/typescript/src/index.d.ts +3 -2
- package/lib/typescript/src/index.d.ts.map +1 -1
- package/lib/typescript/src/mocks/index.d.ts +47 -0
- package/lib/typescript/src/mocks/index.d.ts.map +1 -0
- package/lib/typescript/src/mocks/navigation.d.ts +70 -0
- package/lib/typescript/src/mocks/navigation.d.ts.map +1 -0
- package/lib/typescript/src/mocks/navigationExpoRouter.d.ts +22 -0
- package/lib/typescript/src/mocks/navigationExpoRouter.d.ts.map +1 -0
- package/lib/typescript/src/mocks/reanimated.d.ts +48 -0
- package/lib/typescript/src/mocks/reanimated.d.ts.map +1 -0
- package/lib/typescript/src/navigation/TrueSheetNavigatorContent.d.ts +5 -0
- package/lib/typescript/src/navigation/TrueSheetNavigatorContent.d.ts.map +1 -0
- package/lib/typescript/src/navigation/actions.d.ts +71 -0
- package/lib/typescript/src/navigation/actions.d.ts.map +1 -0
- package/lib/typescript/src/navigation/base-types.d.ts +9 -0
- package/lib/typescript/src/navigation/base-types.d.ts.map +1 -0
- package/lib/typescript/src/navigation/createTrueSheetRouter.d.ts +3 -0
- package/lib/typescript/src/navigation/createTrueSheetRouter.d.ts.map +1 -0
- package/lib/typescript/src/navigation/expo-router/base-types.d.ts +8 -0
- package/lib/typescript/src/navigation/expo-router/base-types.d.ts.map +1 -0
- package/lib/typescript/src/navigation/expo-router/index.d.ts +37 -0
- package/lib/typescript/src/navigation/expo-router/index.d.ts.map +1 -0
- package/lib/typescript/src/navigation/expo-router/types.d.ts +44 -0
- package/lib/typescript/src/navigation/expo-router/types.d.ts.map +1 -0
- package/lib/typescript/src/navigation/index.d.ts +45 -0
- package/lib/typescript/src/navigation/index.d.ts.map +1 -0
- package/lib/typescript/src/navigation/navigator.d.ts +7 -0
- package/lib/typescript/src/navigation/navigator.d.ts.map +1 -0
- package/lib/typescript/src/navigation/screen/ReanimatedTrueSheetScreen.d.ts +3 -0
- package/lib/typescript/src/navigation/screen/ReanimatedTrueSheetScreen.d.ts.map +1 -0
- package/lib/typescript/src/navigation/screen/TrueSheetScreen.d.ts +3 -0
- package/lib/typescript/src/navigation/screen/TrueSheetScreen.d.ts.map +1 -0
- package/lib/typescript/src/navigation/screen/index.d.ts +4 -0
- package/lib/typescript/src/navigation/screen/index.d.ts.map +1 -0
- package/lib/typescript/src/navigation/screen/types.d.ts +14 -0
- package/lib/typescript/src/navigation/screen/types.d.ts.map +1 -0
- package/lib/typescript/src/navigation/screen/useSheetScreenState.d.ts +34 -0
- package/lib/typescript/src/navigation/screen/useSheetScreenState.d.ts.map +1 -0
- package/lib/typescript/src/navigation/types.d.ts +213 -0
- package/lib/typescript/src/navigation/types.d.ts.map +1 -0
- package/lib/typescript/src/navigation/useTrueSheetNavigation.d.ts +23 -0
- package/lib/typescript/src/navigation/useTrueSheetNavigation.d.ts.map +1 -0
- package/lib/typescript/src/reanimated/ReanimatedTrueSheet.d.ts.map +1 -1
- package/lib/typescript/src/reanimated/ReanimatedTrueSheet.web.d.ts +41 -0
- package/lib/typescript/src/reanimated/ReanimatedTrueSheet.web.d.ts.map +1 -0
- package/lib/typescript/src/reanimated/ReanimatedTrueSheetProvider.d.ts +8 -2
- package/lib/typescript/src/reanimated/ReanimatedTrueSheetProvider.d.ts.map +1 -1
- package/lib/typescript/src/reanimated/useReanimatedPositionChangeHandler.web.d.ts +15 -0
- package/lib/typescript/src/reanimated/useReanimatedPositionChangeHandler.web.d.ts.map +1 -0
- package/lib/typescript/src/specs/NativeTrueSheetModule.d.ts +25 -3
- package/lib/typescript/src/specs/NativeTrueSheetModule.d.ts.map +1 -1
- package/lib/typescript/src/web/constants.d.ts +14 -0
- package/lib/typescript/src/web/constants.d.ts.map +1 -0
- package/lib/typescript/src/web/dom.d.ts +7 -0
- package/lib/typescript/src/web/dom.d.ts.map +1 -0
- package/lib/typescript/src/web/vaul/browser.d.ts +8 -0
- package/lib/typescript/src/web/vaul/browser.d.ts.map +1 -0
- package/lib/typescript/src/web/vaul/constants.d.ts +14 -0
- package/lib/typescript/src/web/vaul/constants.d.ts.map +1 -0
- package/lib/typescript/src/web/vaul/context.d.ts +54 -0
- package/lib/typescript/src/web/vaul/context.d.ts.map +1 -0
- package/lib/typescript/src/web/vaul/helpers.d.ts +17 -0
- package/lib/typescript/src/web/vaul/helpers.d.ts.map +1 -0
- package/lib/typescript/src/web/vaul/index.d.ts +234 -0
- package/lib/typescript/src/web/vaul/index.d.ts.map +1 -0
- package/lib/typescript/src/web/vaul/types.d.ts +7 -0
- package/lib/typescript/src/web/vaul/types.d.ts.map +1 -0
- package/lib/typescript/src/web/vaul/use-composed-refs.d.ts +14 -0
- package/lib/typescript/src/web/vaul/use-composed-refs.d.ts.map +1 -0
- package/lib/typescript/src/web/vaul/use-controllable-state.d.ts +9 -0
- package/lib/typescript/src/web/vaul/use-controllable-state.d.ts.map +1 -0
- package/lib/typescript/src/web/vaul/use-position-fixed.d.ts +19 -0
- package/lib/typescript/src/web/vaul/use-position-fixed.d.ts.map +1 -0
- package/lib/typescript/src/web/vaul/use-prevent-scroll.d.ts +18 -0
- package/lib/typescript/src/web/vaul/use-prevent-scroll.d.ts.map +1 -0
- package/lib/typescript/src/web/vaul/use-scale-background.d.ts +2 -0
- package/lib/typescript/src/web/vaul/use-scale-background.d.ts.map +1 -0
- package/lib/typescript/src/web/vaul/use-snap-points.d.ts +38 -0
- package/lib/typescript/src/web/vaul/use-snap-points.d.ts.map +1 -0
- package/package.json +104 -37
- package/react-native.config.js +10 -2
- package/src/TrueSheet.tsx +424 -70
- package/src/TrueSheet.types.ts +602 -72
- package/src/TrueSheet.web.tsx +1437 -0
- package/src/TrueSheetOverlay.tsx +24 -0
- package/src/TrueSheetOverlay.web.tsx +33 -0
- package/src/TrueSheetPeek.tsx +11 -0
- package/src/TrueSheetPeek.web.tsx +64 -0
- package/src/TrueSheetProvider.tsx +33 -0
- package/src/TrueSheetProvider.web.tsx +220 -0
- package/src/fabric/TrueSheetContainerViewNativeComponent.ts +1 -1
- package/src/fabric/TrueSheetContentViewNativeComponent.ts +5 -1
- package/src/fabric/TrueSheetFooterViewNativeComponent.ts +10 -2
- package/src/fabric/TrueSheetHeaderViewNativeComponent.ts +8 -0
- package/src/fabric/TrueSheetOverlayViewNativeComponent.ts +12 -0
- package/src/fabric/TrueSheetPeekViewNativeComponent.ts +8 -0
- package/src/fabric/TrueSheetViewNativeComponent.ts +110 -18
- package/src/index.ts +3 -2
- package/src/mocks/index.ts +96 -0
- package/src/mocks/navigation.ts +79 -0
- package/src/mocks/navigationExpoRouter.ts +41 -0
- package/src/mocks/reanimated.ts +100 -0
- package/src/navigation/TrueSheetNavigatorContent.tsx +106 -0
- package/src/navigation/actions.ts +78 -0
- package/src/navigation/base-types.ts +20 -0
- package/src/navigation/createTrueSheetRouter.ts +194 -0
- package/src/navigation/expo-router/base-types.ts +18 -0
- package/src/navigation/expo-router/index.ts +90 -0
- package/src/navigation/expo-router/types.ts +116 -0
- package/src/navigation/index.ts +80 -0
- package/src/navigation/navigator.ts +18 -0
- package/src/navigation/screen/ReanimatedTrueSheetScreen.tsx +61 -0
- package/src/navigation/screen/TrueSheetScreen.tsx +54 -0
- package/src/navigation/screen/index.ts +3 -0
- package/src/navigation/screen/types.ts +19 -0
- package/src/navigation/screen/useSheetScreenState.ts +102 -0
- package/src/navigation/types.ts +302 -0
- package/src/navigation/useTrueSheetNavigation.ts +26 -0
- package/src/reanimated/ReanimatedTrueSheet.tsx +12 -7
- package/src/reanimated/ReanimatedTrueSheet.web.tsx +75 -0
- package/src/reanimated/ReanimatedTrueSheetProvider.tsx +12 -8
- package/src/reanimated/useReanimatedPositionChangeHandler.web.ts +31 -0
- package/src/specs/NativeTrueSheetModule.ts +28 -3
- package/src/web/constants.ts +13 -0
- package/src/web/dom.ts +9 -0
- package/src/web/vaul/README.md +9 -0
- package/src/web/vaul/browser.ts +38 -0
- package/src/web/vaul/constants.ts +24 -0
- package/src/web/vaul/context.ts +102 -0
- package/src/web/vaul/helpers.ts +131 -0
- package/src/web/vaul/index.tsx +1785 -0
- package/src/web/vaul/style.css +287 -0
- package/src/web/vaul/style.css.d.ts +1 -0
- package/src/web/vaul/types.ts +7 -0
- package/src/web/vaul/use-composed-refs.ts +35 -0
- package/src/web/vaul/use-controllable-state.ts +66 -0
- package/src/web/vaul/use-position-fixed.ts +147 -0
- package/src/web/vaul/use-prevent-scroll.ts +309 -0
- package/src/web/vaul/use-scale-background.ts +64 -0
- package/src/web/vaul/use-snap-points.ts +455 -0
- package/android/src/main/java/com/lodev09/truesheet/events/DetentChangeEvent.kt +0 -26
- package/android/src/main/java/com/lodev09/truesheet/events/DidDismissEvent.kt +0 -20
- package/android/src/main/java/com/lodev09/truesheet/events/DidPresentEvent.kt +0 -26
- package/android/src/main/java/com/lodev09/truesheet/events/DragBeginEvent.kt +0 -26
- package/android/src/main/java/com/lodev09/truesheet/events/DragChangeEvent.kt +0 -26
- package/android/src/main/java/com/lodev09/truesheet/events/DragEndEvent.kt +0 -26
- package/android/src/main/java/com/lodev09/truesheet/events/MountEvent.kt +0 -20
- package/android/src/main/java/com/lodev09/truesheet/events/PositionChangeEvent.kt +0 -32
- package/android/src/main/java/com/lodev09/truesheet/events/SizeChangeEvent.kt +0 -27
- package/android/src/main/java/com/lodev09/truesheet/events/WillDismissEvent.kt +0 -20
- package/android/src/main/java/com/lodev09/truesheet/events/WillPresentEvent.kt +0 -26
- package/android/src/main/res/values/styles.xml +0 -8
- package/ios/events/OnDetentChangeEvent.h +0 -28
- package/ios/events/OnDetentChangeEvent.mm +0 -30
- package/ios/events/OnDidDismissEvent.h +0 -26
- package/ios/events/OnDidDismissEvent.mm +0 -25
- package/ios/events/OnDidPresentEvent.h +0 -28
- package/ios/events/OnDidPresentEvent.mm +0 -30
- package/ios/events/OnDragBeginEvent.h +0 -28
- package/ios/events/OnDragBeginEvent.mm +0 -30
- package/ios/events/OnDragChangeEvent.h +0 -28
- package/ios/events/OnDragChangeEvent.mm +0 -30
- package/ios/events/OnDragEndEvent.h +0 -28
- package/ios/events/OnDragEndEvent.mm +0 -30
- package/ios/events/OnMountEvent.mm +0 -25
- package/ios/events/OnPositionChangeEvent.mm +0 -32
- package/ios/events/OnSizeChangeEvent.h +0 -28
- package/ios/events/OnSizeChangeEvent.mm +0 -30
- package/ios/events/OnWillDismissEvent.mm +0 -25
- package/ios/events/OnWillPresentEvent.h +0 -28
- package/ios/events/OnWillPresentEvent.mm +0 -30
- package/ios/utils/LayoutUtil.h +0 -44
- package/ios/utils/LayoutUtil.mm +0 -50
- package/lib/module/TrueSheetGrabber.js +0 -51
- package/lib/module/TrueSheetGrabber.js.map +0 -1
- package/lib/typescript/src/TrueSheetGrabber.d.ts +0 -39
- package/lib/typescript/src/TrueSheetGrabber.d.ts.map +0 -1
- package/src/TrueSheetGrabber.tsx +0 -82
- package/src/__mocks__/index.js +0 -67
package/ios/TrueSheetView.mm
CHANGED
|
@@ -13,60 +13,84 @@
|
|
|
13
13
|
#import "TrueSheetContentView.h"
|
|
14
14
|
#import "TrueSheetFooterView.h"
|
|
15
15
|
#import "TrueSheetModule.h"
|
|
16
|
+
#import "TrueSheetOverlayView.h"
|
|
16
17
|
#import "TrueSheetViewController.h"
|
|
17
|
-
#import "
|
|
18
|
-
#import "events/
|
|
19
|
-
#import "events/
|
|
20
|
-
#import "events/
|
|
21
|
-
#import "events/
|
|
22
|
-
#import "events/OnDragEndEvent.h"
|
|
23
|
-
#import "events/OnMountEvent.h"
|
|
24
|
-
#import "events/OnPositionChangeEvent.h"
|
|
25
|
-
#import "events/OnSizeChangeEvent.h"
|
|
26
|
-
#import "events/OnWillDismissEvent.h"
|
|
27
|
-
#import "events/OnWillPresentEvent.h"
|
|
28
|
-
#import "utils/LayoutUtil.h"
|
|
18
|
+
#import "core/RNScreensEventObserver.h"
|
|
19
|
+
#import "events/TrueSheetDragEvents.h"
|
|
20
|
+
#import "events/TrueSheetFocusEvents.h"
|
|
21
|
+
#import "events/TrueSheetLifecycleEvents.h"
|
|
22
|
+
#import "events/TrueSheetStateEvents.h"
|
|
29
23
|
#import "utils/WindowUtil.h"
|
|
30
24
|
|
|
31
|
-
#import <react/renderer/components/TrueSheetSpec/ComponentDescriptors.h>
|
|
32
25
|
#import <react/renderer/components/TrueSheetSpec/EventEmitters.h>
|
|
33
26
|
#import <react/renderer/components/TrueSheetSpec/Props.h>
|
|
34
27
|
#import <react/renderer/components/TrueSheetSpec/RCTComponentViewHelpers.h>
|
|
28
|
+
#import <react/renderer/components/TrueSheetSpec/TrueSheetInsets.h>
|
|
29
|
+
#import <react/renderer/components/TrueSheetSpec/TrueSheetViewComponentDescriptor.h>
|
|
30
|
+
#import <react/renderer/components/TrueSheetSpec/TrueSheetViewShadowNode.h>
|
|
31
|
+
#import <react/renderer/components/TrueSheetSpec/TrueSheetViewState.h>
|
|
35
32
|
|
|
36
33
|
#import <React/RCTConversions.h>
|
|
37
34
|
#import <React/RCTFabricComponentsPlugins.h>
|
|
35
|
+
#import <React/RCTLog.h>
|
|
38
36
|
#import <React/RCTSurfaceTouchHandler.h>
|
|
39
37
|
#import <React/RCTUtils.h>
|
|
38
|
+
#import <react/renderer/core/State.h>
|
|
40
39
|
|
|
41
40
|
using namespace facebook::react;
|
|
42
41
|
|
|
43
|
-
@interface TrueSheetView () <TrueSheetViewControllerDelegate,
|
|
42
|
+
@interface TrueSheetView () <TrueSheetViewControllerDelegate,
|
|
43
|
+
TrueSheetContainerViewDelegate,
|
|
44
|
+
RNScreensEventObserverDelegate>
|
|
44
45
|
@end
|
|
45
46
|
|
|
46
47
|
@implementation TrueSheetView {
|
|
47
48
|
TrueSheetContainerView *_containerView;
|
|
48
49
|
TrueSheetViewController *_controller;
|
|
49
50
|
RCTSurfaceTouchHandler *_touchHandler;
|
|
51
|
+
TrueSheetViewShadowNode::ConcreteState::Shared _state;
|
|
52
|
+
UIView *_snapshotView;
|
|
53
|
+
CGSize _lastStateSize;
|
|
50
54
|
NSInteger _initialDetentIndex;
|
|
55
|
+
TrueSheetViewInsetAdjustment _insetAdjustment;
|
|
56
|
+
ScrollableOptions *_scrollableOptions;
|
|
57
|
+
NSInteger _scrollableHandle;
|
|
51
58
|
BOOL _initialDetentAnimated;
|
|
59
|
+
BOOL _isSheetUpdatePending;
|
|
60
|
+
BOOL _pendingLayoutUpdate;
|
|
61
|
+
BOOL _didInitiallyPresent;
|
|
62
|
+
BOOL _dismissedByNavigation;
|
|
63
|
+
BOOL _pendingNavigationRepresent;
|
|
64
|
+
BOOL _pendingMountEvent;
|
|
65
|
+
BOOL _pendingSizeChange;
|
|
66
|
+
BOOL _pendingPropsUpdate;
|
|
67
|
+
NSArray *_pendingDetents;
|
|
68
|
+
RNScreensEventObserver *_screensEventObserver;
|
|
52
69
|
}
|
|
53
70
|
|
|
71
|
+
#pragma mark - Initialization
|
|
72
|
+
|
|
54
73
|
- (instancetype)initWithFrame:(CGRect)frame {
|
|
55
74
|
if (self = [super initWithFrame:frame]) {
|
|
56
75
|
static const auto defaultProps = std::make_shared<const TrueSheetViewProps>();
|
|
57
76
|
_props = defaultProps;
|
|
58
77
|
|
|
59
|
-
|
|
78
|
+
self.hidden = YES;
|
|
79
|
+
self.userInteractionEnabled = NO;
|
|
80
|
+
|
|
60
81
|
_controller = [[TrueSheetViewController alloc] init];
|
|
61
82
|
_controller.delegate = self;
|
|
62
83
|
|
|
63
|
-
// Initialize touch handler - will be attached to container when mounted
|
|
64
84
|
_touchHandler = [[RCTSurfaceTouchHandler alloc] init];
|
|
65
|
-
|
|
66
85
|
_containerView = nil;
|
|
67
|
-
|
|
86
|
+
_snapshotView = nil;
|
|
87
|
+
_lastStateSize = CGSizeZero;
|
|
68
88
|
_initialDetentIndex = -1;
|
|
69
89
|
_initialDetentAnimated = YES;
|
|
90
|
+
_isSheetUpdatePending = NO;
|
|
91
|
+
|
|
92
|
+
_screensEventObserver = [[RNScreensEventObserver alloc] init];
|
|
93
|
+
_screensEventObserver.delegate = self;
|
|
70
94
|
}
|
|
71
95
|
return self;
|
|
72
96
|
}
|
|
@@ -74,29 +98,109 @@ using namespace facebook::react;
|
|
|
74
98
|
- (void)didMoveToWindow {
|
|
75
99
|
[super didMoveToWindow];
|
|
76
100
|
|
|
77
|
-
if (!self.window)
|
|
101
|
+
if (!self.window)
|
|
78
102
|
return;
|
|
79
|
-
}
|
|
80
103
|
|
|
81
|
-
// Register this view with the TurboModule when added to window
|
|
82
|
-
// This ensures the tag is properly set by the framework
|
|
83
104
|
if (self.tag > 0) {
|
|
84
105
|
[TrueSheetModule registerView:self withTag:@(self.tag)];
|
|
85
106
|
}
|
|
107
|
+
|
|
108
|
+
if (_pendingNavigationRepresent && !_controller.isPresented) {
|
|
109
|
+
_pendingNavigationRepresent = NO;
|
|
110
|
+
[self presentAtIndex:_controller.activeDetentIndex animated:YES completion:nil];
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
[self presentInitialIfNeeded];
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
// JS holds initialDetentIndex back one commit so effect-driven content (e.g. a
|
|
118
|
+
// navigation footer set via setOptions) commits together with it — by the time
|
|
119
|
+
// the prop lands the tree is final and the sheet presents at its final height.
|
|
120
|
+
// Called from didMoveToWindow (re-attach) and finalizeUpdates (the prop
|
|
121
|
+
// arriving after attach, which didMoveToWindow won't re-fire for).
|
|
122
|
+
- (void)presentInitialIfNeeded {
|
|
123
|
+
if (_initialDetentIndex < 0 || _didInitiallyPresent)
|
|
124
|
+
return;
|
|
125
|
+
|
|
126
|
+
UIViewController *vc = [self findPresentingViewController];
|
|
127
|
+
|
|
128
|
+
// Only present if the view controller is in the same window
|
|
129
|
+
if (!vc || vc.view.window != self.window) {
|
|
130
|
+
// Animate next time when sheet finally moves to the correct window
|
|
131
|
+
_initialDetentAnimated = YES;
|
|
132
|
+
return;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
// A sheet still animating out of the presenter (e.g. our own controller,
|
|
136
|
+
// recycled mid-dismissal) blocks presentation — retry once its transition ends.
|
|
137
|
+
UIViewController *dismissing = vc.presentedViewController;
|
|
138
|
+
if (dismissing && dismissing.isBeingDismissed) {
|
|
139
|
+
_initialDetentAnimated = YES;
|
|
140
|
+
|
|
141
|
+
__weak __typeof(self) weakSelf = self;
|
|
142
|
+
void (^retry)(void) = ^{
|
|
143
|
+
dispatch_async(dispatch_get_main_queue(), ^{
|
|
144
|
+
[weakSelf presentInitialIfNeeded];
|
|
145
|
+
});
|
|
146
|
+
};
|
|
147
|
+
|
|
148
|
+
id<UIViewControllerTransitionCoordinator> coordinator = dismissing.transitionCoordinator;
|
|
149
|
+
if (coordinator) {
|
|
150
|
+
[coordinator animateAlongsideTransition:nil
|
|
151
|
+
completion:^(id<UIViewControllerTransitionCoordinatorContext> context) {
|
|
152
|
+
retry();
|
|
153
|
+
}];
|
|
154
|
+
} else {
|
|
155
|
+
retry();
|
|
156
|
+
}
|
|
157
|
+
return;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
_didInitiallyPresent = YES;
|
|
161
|
+
|
|
162
|
+
// Deferred a runloop turn so sibling mounts from the current transaction
|
|
163
|
+
// (e.g. a footer committed alongside the prop) land before measuring.
|
|
164
|
+
__weak __typeof(self) weakSelf = self;
|
|
165
|
+
dispatch_async(dispatch_get_main_queue(), ^{
|
|
166
|
+
__typeof(self) strongSelf = weakSelf;
|
|
167
|
+
if (!strongSelf || strongSelf->_controller.isPresented || strongSelf->_controller.isBeingPresented)
|
|
168
|
+
return;
|
|
169
|
+
|
|
170
|
+
[strongSelf presentAtIndex:strongSelf->_initialDetentIndex
|
|
171
|
+
animated:strongSelf->_initialDetentAnimated
|
|
172
|
+
completion:^(BOOL success, NSError *_Nullable error) {
|
|
173
|
+
// Present can fail if the view detached during this turn —
|
|
174
|
+
// reset so the next attach/prop update retries.
|
|
175
|
+
if (!success) {
|
|
176
|
+
strongSelf->_didInitiallyPresent = NO;
|
|
177
|
+
}
|
|
178
|
+
}];
|
|
179
|
+
});
|
|
86
180
|
}
|
|
87
181
|
|
|
88
182
|
- (void)dealloc {
|
|
89
|
-
|
|
183
|
+
[_screensEventObserver stopObserving];
|
|
184
|
+
_screensEventObserver = nil;
|
|
185
|
+
|
|
90
186
|
if (_controller && _controller.presentingViewController) {
|
|
91
|
-
|
|
187
|
+
// Find the root presenting controller to dismiss the entire stack
|
|
188
|
+
UIViewController *root = _controller.presentingViewController;
|
|
189
|
+
while (root.presentingViewController != nil) {
|
|
190
|
+
root = root.presentingViewController;
|
|
191
|
+
}
|
|
192
|
+
[root dismissViewControllerAnimated:YES completion:nil];
|
|
92
193
|
}
|
|
93
194
|
|
|
94
|
-
|
|
195
|
+
_didInitiallyPresent = NO;
|
|
196
|
+
_dismissedByNavigation = NO;
|
|
197
|
+
_pendingNavigationRepresent = NO;
|
|
198
|
+
|
|
95
199
|
_controller.delegate = nil;
|
|
96
200
|
_controller = nil;
|
|
97
201
|
|
|
98
|
-
|
|
99
|
-
|
|
202
|
+
[_snapshotView removeFromSuperview];
|
|
203
|
+
_snapshotView = nil;
|
|
100
204
|
}
|
|
101
205
|
|
|
102
206
|
#pragma mark - RCTComponentViewProtocol
|
|
@@ -105,319 +209,775 @@ using namespace facebook::react;
|
|
|
105
209
|
return concreteComponentDescriptorProvider<TrueSheetViewComponentDescriptor>();
|
|
106
210
|
}
|
|
107
211
|
|
|
212
|
+
- (void)updateProps:(Props::Shared const &)props oldProps:(Props::Shared const &)oldProps {
|
|
213
|
+
[super updateProps:props oldProps:oldProps];
|
|
214
|
+
|
|
215
|
+
const auto &newProps = *std::static_pointer_cast<TrueSheetViewProps const>(props);
|
|
216
|
+
|
|
217
|
+
// Detents (-1 represents "auto")
|
|
218
|
+
NSMutableArray *detents = [NSMutableArray new];
|
|
219
|
+
for (const auto &detent : newProps.detents) {
|
|
220
|
+
[detents addObject:@(detent)];
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
if (oldProps) {
|
|
224
|
+
const auto &prevProps = *std::static_pointer_cast<TrueSheetViewProps const>(oldProps);
|
|
225
|
+
if (newProps.detents != prevProps.detents || newProps.insetAdjustment != prevProps.insetAdjustment) {
|
|
226
|
+
_pendingLayoutUpdate = YES;
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
if (_controller.isBeingPresented) {
|
|
231
|
+
_pendingDetents = detents;
|
|
232
|
+
} else {
|
|
233
|
+
_controller.detents = detents;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
// Background color
|
|
237
|
+
_controller.backgroundColor = RCTUIColorFromSharedColor(newProps.backgroundColor);
|
|
238
|
+
|
|
239
|
+
// Blur tint
|
|
240
|
+
_controller.backgroundBlur = newProps.backgroundBlur;
|
|
241
|
+
|
|
242
|
+
// Blur options
|
|
243
|
+
const auto &blurOpts = newProps.blurOptions;
|
|
244
|
+
_controller.blurIntensity = blurOpts.intensity >= 0 ? @(blurOpts.intensity) : nil;
|
|
245
|
+
_controller.blurInteraction = blurOpts.interaction;
|
|
246
|
+
|
|
247
|
+
// Corner radius
|
|
248
|
+
_controller.cornerRadius = newProps.cornerRadius < 0 ? nil : @(newProps.cornerRadius);
|
|
249
|
+
|
|
250
|
+
// Content height
|
|
251
|
+
_controller.maxContentHeight = newProps.maxContentHeight != 0.0 ? @(newProps.maxContentHeight) : nil;
|
|
252
|
+
|
|
253
|
+
// Content width
|
|
254
|
+
_controller.maxContentWidth = newProps.maxContentWidth != 0.0 ? @(newProps.maxContentWidth) : nil;
|
|
255
|
+
|
|
256
|
+
// Anchor
|
|
257
|
+
_controller.anchor = newProps.anchor;
|
|
258
|
+
|
|
259
|
+
_controller.grabber = newProps.grabber;
|
|
260
|
+
|
|
261
|
+
// Grabber options - check if any non-default values are set
|
|
262
|
+
const auto &grabberOpts = newProps.grabberOptions;
|
|
263
|
+
UIColor *grabberColor = RCTUIColorFromSharedColor(grabberOpts.color);
|
|
264
|
+
BOOL hasGrabberOptions = grabberOpts.width > 0 || grabberOpts.height > 0 || grabberOpts.topMargin > 0 ||
|
|
265
|
+
grabberOpts.cornerRadius >= 0 || grabberColor != nil || !grabberOpts.adaptive;
|
|
266
|
+
|
|
267
|
+
if (hasGrabberOptions) {
|
|
268
|
+
GrabberOptions *options = [[GrabberOptions alloc] init];
|
|
269
|
+
if (grabberOpts.width > 0)
|
|
270
|
+
options.width = @(grabberOpts.width);
|
|
271
|
+
if (grabberOpts.height > 0)
|
|
272
|
+
options.height = @(grabberOpts.height);
|
|
273
|
+
if (grabberOpts.topMargin > 0)
|
|
274
|
+
options.topMargin = @(grabberOpts.topMargin);
|
|
275
|
+
if (grabberOpts.cornerRadius >= 0)
|
|
276
|
+
options.cornerRadius = @(grabberOpts.cornerRadius);
|
|
277
|
+
if (grabberColor)
|
|
278
|
+
options.color = grabberColor;
|
|
279
|
+
options.adaptive = grabberOpts.adaptive;
|
|
280
|
+
_controller.grabberOptions = options;
|
|
281
|
+
} else {
|
|
282
|
+
_controller.grabberOptions = nil;
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
// Accessibility options - applied to the custom grabber
|
|
286
|
+
_controller.accessibilityOptions = newProps.accessibilityOptions;
|
|
287
|
+
|
|
288
|
+
_controller.presentation = newProps.presentation;
|
|
289
|
+
_controller.dismissible = newProps.dismissible;
|
|
290
|
+
_controller.draggable = newProps.draggable;
|
|
291
|
+
_controller.dimmed = newProps.dimmed;
|
|
292
|
+
|
|
293
|
+
if (newProps.dimmedDetentIndex >= 0) {
|
|
294
|
+
_controller.dimmedDetentIndex = @(newProps.dimmedDetentIndex);
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
_initialDetentIndex = newProps.initialDetentIndex;
|
|
298
|
+
_initialDetentAnimated = newProps.initialDetentAnimated;
|
|
299
|
+
|
|
300
|
+
_scrollableHandle = newProps.scrollableHandle;
|
|
301
|
+
|
|
302
|
+
const auto &scrollableOpts = newProps.scrollableOptions;
|
|
303
|
+
BOOL scrollingExpandsSheet = scrollableOpts.scrollingExpandsSheet;
|
|
304
|
+
BOOL contentInsetAdjustment = scrollableOpts.contentInsetAdjustmentBehavior;
|
|
305
|
+
auto topEdgeEffect = scrollableOpts.topScrollEdgeEffect;
|
|
306
|
+
auto bottomEdgeEffect = scrollableOpts.bottomScrollEdgeEffect;
|
|
307
|
+
BOOL hasScrollableOptions = scrollableOpts.keyboardScrollOffset > 0 || scrollableOpts.keyboardOffset != 0 ||
|
|
308
|
+
!scrollingExpandsSheet || !contentInsetAdjustment ||
|
|
309
|
+
topEdgeEffect != TrueSheetViewTopScrollEdgeEffect::Hidden ||
|
|
310
|
+
bottomEdgeEffect != TrueSheetViewBottomScrollEdgeEffect::Hidden;
|
|
311
|
+
|
|
312
|
+
if (hasScrollableOptions) {
|
|
313
|
+
ScrollableOptions *options = [[ScrollableOptions alloc] init];
|
|
314
|
+
options.contentInsetAdjustment = contentInsetAdjustment;
|
|
315
|
+
options.keyboardScrollOffset = scrollableOpts.keyboardScrollOffset;
|
|
316
|
+
options.keyboardOffset = scrollableOpts.keyboardOffset;
|
|
317
|
+
options.scrollingExpandsSheet = scrollingExpandsSheet;
|
|
318
|
+
options.topScrollEdgeEffect = topEdgeEffect;
|
|
319
|
+
options.bottomScrollEdgeEffect = bottomEdgeEffect;
|
|
320
|
+
_scrollableOptions = options;
|
|
321
|
+
} else {
|
|
322
|
+
_scrollableOptions = nil;
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
_controller.scrollingExpandsSheet = scrollingExpandsSheet;
|
|
326
|
+
|
|
327
|
+
_controller.absoluteHeader = newProps.headerOptions.position == TrueSheetViewPosition::Absolute;
|
|
328
|
+
_controller.absoluteFooter = newProps.footerOptions.footerPosition == TrueSheetViewFooterPosition::Absolute;
|
|
329
|
+
|
|
330
|
+
CGFloat footerKeyboardOffset = newProps.footerOptions.keyboardOffset;
|
|
331
|
+
if (_controller.footerKeyboardOffset != footerKeyboardOffset) {
|
|
332
|
+
_controller.footerKeyboardOffset = footerKeyboardOffset;
|
|
333
|
+
[_containerView updateFooterKeyboardOffset];
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
_insetAdjustment = newProps.insetAdjustment;
|
|
337
|
+
_controller.insetAdjustment = _insetAdjustment;
|
|
338
|
+
|
|
339
|
+
[self setupScrollable];
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
- (void)updateState:(const State::Shared &)state oldState:(const State::Shared &)oldState {
|
|
343
|
+
_state = std::static_pointer_cast<TrueSheetViewShadowNode::ConcreteState const>(state);
|
|
344
|
+
|
|
345
|
+
if (_controller && !_controller.isStackedBehindChild) {
|
|
346
|
+
CGSize size = _controller.view.frame.size;
|
|
347
|
+
if (size.width < 1 || size.height < 1) {
|
|
348
|
+
// Pre-present the controller has no layout yet. Seed with screen
|
|
349
|
+
// dimensions so content (e.g. a FlatList viewport) can lay out and
|
|
350
|
+
// measure before the sheet presents (parity with Android).
|
|
351
|
+
UIWindow *window = [WindowUtil keyWindow];
|
|
352
|
+
size = window ? window.bounds.size : UIScreen.mainScreen.bounds.size;
|
|
353
|
+
}
|
|
354
|
+
[self viewControllerDidChangeSize:size];
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
/**
|
|
359
|
+
* Updates Fabric state with container dimensions for Yoga layout.
|
|
360
|
+
*/
|
|
361
|
+
- (void)updateStateWithSize:(CGSize)size {
|
|
362
|
+
if (!_state)
|
|
363
|
+
return;
|
|
364
|
+
|
|
365
|
+
if (fabs(size.width - _lastStateSize.width) < 0.5 && fabs(size.height - _lastStateSize.height) < 0.5)
|
|
366
|
+
return;
|
|
367
|
+
|
|
368
|
+
_lastStateSize = size;
|
|
369
|
+
|
|
370
|
+
auto stateData = _state->getData();
|
|
371
|
+
stateData.containerWidth = static_cast<float>(size.width);
|
|
372
|
+
stateData.containerHeight = static_cast<float>(size.height);
|
|
373
|
+
|
|
374
|
+
// RN 0.82+ processes immediate state updates in the same layout pass, so Yoga
|
|
375
|
+
// resizes the container synchronously with the sheet (e.g. inside UIKit's
|
|
376
|
+
// animation block during detent transitions).
|
|
377
|
+
_state->updateState(std::move(stateData), facebook::react::EventQueue::UpdateMode::unstable_Immediate);
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
- (void)finalizeUpdates:(RNComponentViewUpdateMask)updateMask {
|
|
381
|
+
[super finalizeUpdates:updateMask];
|
|
382
|
+
|
|
383
|
+
// Emit pending mount event now that eventEmitter is available
|
|
384
|
+
if (_pendingMountEvent && (updateMask & RNComponentViewUpdateMaskEventEmitter)) {
|
|
385
|
+
_pendingMountEvent = NO;
|
|
386
|
+
[TrueSheetLifecycleEvents emitMount:_eventEmitter];
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
if (!(updateMask & RNComponentViewUpdateMaskProps) || !_controller)
|
|
390
|
+
return;
|
|
391
|
+
|
|
392
|
+
[self setupScrollable];
|
|
393
|
+
|
|
394
|
+
if (_controller.isPresented) {
|
|
395
|
+
[self applySheetPropsUpdate];
|
|
396
|
+
} else if (_controller.isBeingPresented) {
|
|
397
|
+
_pendingPropsUpdate = YES;
|
|
398
|
+
} else if (_initialDetentIndex >= 0) {
|
|
399
|
+
_pendingLayoutUpdate = NO;
|
|
400
|
+
if (self.window) {
|
|
401
|
+
[self presentInitialIfNeeded];
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
- (void)prepareForRecycle {
|
|
407
|
+
[super prepareForRecycle];
|
|
408
|
+
|
|
409
|
+
// Pooled mid-dismissal: the next mount can reuse this host — and its
|
|
410
|
+
// controller — while the previous sheet is still animating out. Detach until
|
|
411
|
+
// that transition ends so its tail (didBlur, didDismiss, position) can't reach
|
|
412
|
+
// the new mount, then hand the controller back and let auto-present retry.
|
|
413
|
+
if (_controller.isBeingDismissed) {
|
|
414
|
+
_controller.delegate = nil;
|
|
415
|
+
|
|
416
|
+
__weak __typeof(self) weakSelf = self;
|
|
417
|
+
void (^reattach)(void) = ^{
|
|
418
|
+
dispatch_async(dispatch_get_main_queue(), ^{
|
|
419
|
+
__typeof(self) strongSelf = weakSelf;
|
|
420
|
+
if (!strongSelf)
|
|
421
|
+
return;
|
|
422
|
+
|
|
423
|
+
strongSelf->_controller.delegate = strongSelf;
|
|
424
|
+
strongSelf->_controller.activeDetentIndex = -1;
|
|
425
|
+
if (strongSelf.window) {
|
|
426
|
+
[strongSelf presentInitialIfNeeded];
|
|
427
|
+
}
|
|
428
|
+
});
|
|
429
|
+
};
|
|
430
|
+
|
|
431
|
+
id<UIViewControllerTransitionCoordinator> coordinator = _controller.transitionCoordinator;
|
|
432
|
+
if (coordinator) {
|
|
433
|
+
[coordinator animateAlongsideTransition:nil
|
|
434
|
+
completion:^(id<UIViewControllerTransitionCoordinatorContext> context) {
|
|
435
|
+
reattach();
|
|
436
|
+
}];
|
|
437
|
+
} else {
|
|
438
|
+
reattach();
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
_lastStateSize = CGSizeZero;
|
|
443
|
+
_didInitiallyPresent = NO;
|
|
444
|
+
_dismissedByNavigation = NO;
|
|
445
|
+
_pendingNavigationRepresent = NO;
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
#pragma mark - Child Component Mounting
|
|
449
|
+
|
|
450
|
+
- (void)cleanupContainerView {
|
|
451
|
+
if (_containerView == nil)
|
|
452
|
+
return;
|
|
453
|
+
|
|
454
|
+
_containerView.delegate = nil;
|
|
455
|
+
[_touchHandler detachFromView:_containerView];
|
|
456
|
+
[_containerView removeFromSuperview];
|
|
457
|
+
|
|
458
|
+
_containerView = nil;
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
- (void)mountChildComponentView:(UIView<RCTComponentViewProtocol> *)childComponentView index:(NSInteger)index {
|
|
462
|
+
if (![childComponentView isKindOfClass:[TrueSheetContainerView class]])
|
|
463
|
+
return;
|
|
464
|
+
|
|
465
|
+
if (_containerView != nil && _containerView != childComponentView) {
|
|
466
|
+
RCTLogWarn(@"TrueSheet: Sheet can only have one container component.");
|
|
467
|
+
[self cleanupContainerView];
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
if (_snapshotView) {
|
|
471
|
+
[_snapshotView removeFromSuperview];
|
|
472
|
+
_snapshotView = nil;
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
_containerView = (TrueSheetContainerView *)childComponentView;
|
|
476
|
+
_containerView.delegate = self;
|
|
477
|
+
|
|
478
|
+
[_touchHandler attachToView:_containerView];
|
|
479
|
+
[_controller.view addSubview:_containerView];
|
|
480
|
+
[_controller.view bringSubviewToFront:_containerView];
|
|
481
|
+
_controller.accessibilityContentView = _containerView;
|
|
482
|
+
[_controller setupAccessibilityContainer];
|
|
483
|
+
|
|
484
|
+
CGFloat contentHeight = [_containerView contentHeight];
|
|
485
|
+
if (contentHeight > 0) {
|
|
486
|
+
_controller.contentHeight = @(contentHeight);
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
CGFloat headerHeight = [_containerView headerHeight];
|
|
490
|
+
if (headerHeight > 0) {
|
|
491
|
+
_controller.headerHeight = @(headerHeight);
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
if ([_containerView footerHeight] > 0) {
|
|
495
|
+
[self syncFooterMetrics];
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
CGFloat peekContentHeight = [_containerView peekContentHeight];
|
|
499
|
+
if (peekContentHeight > 0) {
|
|
500
|
+
_controller.peekContentHeight = @(peekContentHeight);
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
if (_eventEmitter) {
|
|
504
|
+
[TrueSheetLifecycleEvents emitMount:_eventEmitter];
|
|
505
|
+
} else {
|
|
506
|
+
_pendingMountEvent = YES;
|
|
507
|
+
}
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
- (void)unmountChildComponentView:(UIView<RCTComponentViewProtocol> *)childComponentView index:(NSInteger)index {
|
|
511
|
+
if (![childComponentView isKindOfClass:[TrueSheetContainerView class]])
|
|
512
|
+
return;
|
|
513
|
+
|
|
514
|
+
if (_containerView == nil || _containerView != childComponentView)
|
|
515
|
+
return;
|
|
516
|
+
|
|
517
|
+
if (_controller.isPresented) {
|
|
518
|
+
UIView *superView = _containerView.superview;
|
|
519
|
+
UIView *snapshot = [_containerView snapshotViewAfterScreenUpdates:NO];
|
|
520
|
+
if (snapshot) {
|
|
521
|
+
snapshot.frame = _containerView.frame;
|
|
522
|
+
[superView insertSubview:snapshot belowSubview:_containerView];
|
|
523
|
+
_snapshotView = snapshot;
|
|
524
|
+
}
|
|
525
|
+
}
|
|
526
|
+
|
|
527
|
+
[self cleanupContainerView];
|
|
528
|
+
}
|
|
529
|
+
|
|
108
530
|
#pragma mark - TurboModule Methods
|
|
109
531
|
|
|
110
532
|
- (void)presentAtIndex:(NSInteger)index
|
|
111
533
|
animated:(BOOL)animated
|
|
112
534
|
completion:(nullable TrueSheetCompletionBlock)completion {
|
|
113
|
-
if (_controller.isPresented) {
|
|
114
|
-
|
|
115
|
-
[self->_controller setupActiveDetentWithIndex:index];
|
|
116
|
-
}];
|
|
117
|
-
|
|
535
|
+
if (_controller.isBeingPresented || _controller.isPresented) {
|
|
536
|
+
RCTLogWarn(@"TrueSheet: sheet is already presented. Use resize() to change detent.");
|
|
118
537
|
if (completion) {
|
|
119
538
|
completion(YES, nil);
|
|
120
539
|
}
|
|
121
540
|
return;
|
|
122
541
|
}
|
|
123
542
|
|
|
124
|
-
|
|
543
|
+
// Reset navigation dismiss flag when presenting (handles view recycling edge cases)
|
|
544
|
+
_dismissedByNavigation = NO;
|
|
125
545
|
|
|
546
|
+
UIViewController *presentingViewController = [self findPresentingViewController];
|
|
126
547
|
if (!presentingViewController) {
|
|
127
548
|
NSError *error = [NSError errorWithDomain:@"com.lodev09.TrueSheet"
|
|
128
549
|
code:1001
|
|
129
550
|
userInfo:@{NSLocalizedDescriptionKey : @"No presenting view controller found"}];
|
|
130
|
-
|
|
131
551
|
if (completion) {
|
|
132
552
|
completion(NO, error);
|
|
133
553
|
}
|
|
134
554
|
return;
|
|
135
555
|
}
|
|
136
556
|
|
|
137
|
-
|
|
557
|
+
[_controller setupAnchorViewInView:presentingViewController.view];
|
|
558
|
+
[_controller setupSheetSizing];
|
|
138
559
|
[_controller setupSheetProps];
|
|
139
|
-
[_controller setupSheetDetents];
|
|
140
560
|
|
|
141
|
-
//
|
|
561
|
+
// Detect before measuring so a first-time detection doesn't shift sizes mid-animation.
|
|
562
|
+
[self setupScrollable];
|
|
563
|
+
|
|
564
|
+
// Measure synchronously so the presentation starts at the right height —
|
|
565
|
+
// async size reports would otherwise land mid-animation and force a
|
|
566
|
+
// detent retarget that snaps the presentation stack.
|
|
567
|
+
if (_containerView) {
|
|
568
|
+
_controller.contentHeight = @([_containerView contentHeight]);
|
|
569
|
+
_controller.headerHeight = @([_containerView headerHeight]);
|
|
570
|
+
[self syncFooterMetrics];
|
|
571
|
+
_controller.peekContentHeight = @([_containerView peekContentHeight]);
|
|
572
|
+
}
|
|
573
|
+
_pendingSizeChange = NO;
|
|
574
|
+
|
|
575
|
+
[self refreshFooterBottomInset];
|
|
576
|
+
[_controller setupSheetDetents];
|
|
142
577
|
[_controller setupActiveDetentWithIndex:index];
|
|
143
578
|
|
|
144
|
-
|
|
145
|
-
[
|
|
579
|
+
[_screensEventObserver capturePresenterScreenFromView:self];
|
|
580
|
+
[_screensEventObserver startObservingWithState:_state.get()->getData()];
|
|
581
|
+
|
|
582
|
+
UIWindow *window = presentingViewController.view.window;
|
|
583
|
+
[presentingViewController presentViewController:_controller
|
|
146
584
|
animated:animated
|
|
147
585
|
completion:^{
|
|
148
|
-
|
|
586
|
+
[TrueSheetOverlayView bringOverlaysToFrontInWindow:window];
|
|
149
587
|
if (completion) {
|
|
150
588
|
completion(YES, nil);
|
|
151
589
|
}
|
|
152
590
|
}];
|
|
591
|
+
|
|
592
|
+
// Presenting adds the sheet's transition view on top of the window once the
|
|
593
|
+
// transition starts — re-front overlays alongside it so the first frame is
|
|
594
|
+
// already ordered (and again on completion in case the transition was queued)
|
|
595
|
+
id<UIViewControllerTransitionCoordinator> coordinator = _controller.transitionCoordinator;
|
|
596
|
+
if (coordinator) {
|
|
597
|
+
[coordinator
|
|
598
|
+
animateAlongsideTransition:^(id<UIViewControllerTransitionCoordinatorContext> context) {
|
|
599
|
+
[TrueSheetOverlayView bringOverlaysToFrontInWindow:window];
|
|
600
|
+
}
|
|
601
|
+
completion:nil];
|
|
602
|
+
} else {
|
|
603
|
+
[TrueSheetOverlayView bringOverlaysToFrontInWindow:window];
|
|
604
|
+
}
|
|
153
605
|
}
|
|
154
606
|
|
|
155
|
-
- (void)
|
|
607
|
+
- (void)resizeToIndex:(NSInteger)index completion:(nullable TrueSheetCompletionBlock)completion {
|
|
156
608
|
if (!_controller.isPresented) {
|
|
609
|
+
RCTLogWarn(@"TrueSheet: Cannot resize. Sheet is not presented.");
|
|
157
610
|
if (completion) {
|
|
158
611
|
completion(YES, nil);
|
|
159
612
|
}
|
|
160
613
|
return;
|
|
161
614
|
}
|
|
162
615
|
|
|
163
|
-
[_controller
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
completion(YES, nil);
|
|
167
|
-
}
|
|
168
|
-
}];
|
|
169
|
-
}
|
|
616
|
+
[_controller.sheetPresentationController animateChanges:^{
|
|
617
|
+
[self->_controller resizeToDetentIndex:index];
|
|
618
|
+
}];
|
|
170
619
|
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
[_controller.sheetPresentationController animateChanges:^{
|
|
174
|
-
[self->_controller setupActiveDetentWithIndex:index];
|
|
175
|
-
}];
|
|
620
|
+
if (completion) {
|
|
621
|
+
completion(YES, nil);
|
|
176
622
|
}
|
|
177
623
|
}
|
|
178
624
|
|
|
179
|
-
- (
|
|
180
|
-
|
|
625
|
+
- (TrueSheetViewController *)viewController {
|
|
626
|
+
return _controller;
|
|
627
|
+
}
|
|
181
628
|
|
|
182
|
-
|
|
629
|
+
- (void)emitDismissedPosition {
|
|
630
|
+
[TrueSheetStateEvents emitPositionChange:_eventEmitter
|
|
631
|
+
index:-1
|
|
632
|
+
position:_controller.screenHeight
|
|
633
|
+
detent:0
|
|
634
|
+
realtime:NO];
|
|
635
|
+
}
|
|
183
636
|
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
637
|
+
- (void)dismissAnimated:(BOOL)animated completion:(nullable TrueSheetCompletionBlock)completion {
|
|
638
|
+
if (_controller.isBeingDismissed || !_controller.isPresented) {
|
|
639
|
+
RCTLogWarn(@"TrueSheet: sheet is already dismissed. No need to dismiss it again.");
|
|
640
|
+
|
|
641
|
+
if (completion) {
|
|
642
|
+
completion(YES, nil);
|
|
643
|
+
}
|
|
644
|
+
return;
|
|
188
645
|
}
|
|
189
646
|
|
|
190
|
-
|
|
647
|
+
// Dismiss from the presenting view controller to dismiss this sheet and all its children
|
|
648
|
+
UIViewController *presenter = _controller.presentingViewController;
|
|
649
|
+
[presenter dismissViewControllerAnimated:animated
|
|
650
|
+
completion:^{
|
|
651
|
+
if (completion) {
|
|
652
|
+
completion(YES, nil);
|
|
653
|
+
}
|
|
654
|
+
}];
|
|
655
|
+
}
|
|
191
656
|
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
657
|
+
- (void)dismissStackAnimated:(BOOL)animated completion:(nullable TrueSheetCompletionBlock)completion {
|
|
658
|
+
if (_controller.isBeingDismissed || !_controller.isPresented) {
|
|
659
|
+
RCTLogWarn(@"TrueSheet: sheet is already dismissed. No need to dismiss it again.");
|
|
195
660
|
|
|
196
|
-
|
|
197
|
-
|
|
661
|
+
if (completion) {
|
|
662
|
+
completion(YES, nil);
|
|
663
|
+
}
|
|
664
|
+
return;
|
|
665
|
+
}
|
|
198
666
|
|
|
199
|
-
//
|
|
200
|
-
if (
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
667
|
+
// Only dismiss presented children, not this sheet itself
|
|
668
|
+
if (!_controller.presentedViewController) {
|
|
669
|
+
if (completion) {
|
|
670
|
+
completion(YES, nil);
|
|
671
|
+
}
|
|
672
|
+
return;
|
|
204
673
|
}
|
|
205
674
|
|
|
206
|
-
//
|
|
207
|
-
|
|
208
|
-
|
|
675
|
+
// Calling dismiss on _controller dismisses all VCs presented on top of it, but keeps _controller presented
|
|
676
|
+
[_controller dismissViewControllerAnimated:animated
|
|
677
|
+
completion:^{
|
|
678
|
+
if (completion) {
|
|
679
|
+
completion(YES, nil);
|
|
680
|
+
}
|
|
681
|
+
}];
|
|
682
|
+
}
|
|
683
|
+
|
|
684
|
+
#pragma mark - TrueSheetContainerViewDelegate
|
|
685
|
+
|
|
686
|
+
/**
|
|
687
|
+
* Debounced sheet update to handle rapid content/header size changes.
|
|
688
|
+
*/
|
|
689
|
+
- (void)setupSheetDetentsForSizeChange {
|
|
690
|
+
// Keep the footer's absorbed inset in sync with the latest measured heights
|
|
691
|
+
// even before presenting, so the sheet presents at its final size.
|
|
692
|
+
[self refreshFooterBottomInset];
|
|
693
|
+
|
|
694
|
+
// Retargeting the in-flight presentation makes UIKit snap the whole stack
|
|
695
|
+
// (including the sheet behind) instead of animating. Defer to didPresent —
|
|
696
|
+
// presentAtIndex measured synchronously, so this is usually a no-op.
|
|
697
|
+
if (_controller.isBeingPresented) {
|
|
698
|
+
_pendingSizeChange = YES;
|
|
699
|
+
return;
|
|
209
700
|
}
|
|
210
701
|
|
|
211
|
-
//
|
|
212
|
-
|
|
702
|
+
// Not presented: presentAtIndex measures at present time.
|
|
703
|
+
// Dismissing: the sheet is going away — touching detents perturbs the
|
|
704
|
+
// presentation stack, visibly glitching the sheet behind.
|
|
705
|
+
if (!_controller.isPresented || _controller.isBeingDismissed)
|
|
706
|
+
return;
|
|
213
707
|
|
|
214
|
-
|
|
215
|
-
|
|
708
|
+
if (_isSheetUpdatePending)
|
|
709
|
+
return;
|
|
216
710
|
|
|
217
|
-
|
|
218
|
-
_controller.dimmed = newProps.dimmed;
|
|
711
|
+
_isSheetUpdatePending = YES;
|
|
219
712
|
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
713
|
+
dispatch_async(dispatch_get_main_queue(), ^{
|
|
714
|
+
self->_isSheetUpdatePending = NO;
|
|
715
|
+
if (!self->_containerView || self->_controller.isBeingDismissed)
|
|
716
|
+
return;
|
|
224
717
|
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
718
|
+
// Refresh here (not just on peek size events) since the peek's offset
|
|
719
|
+
// within the content can change without its own size changing.
|
|
720
|
+
self->_controller.peekContentHeight = @([self->_containerView peekContentHeight]);
|
|
721
|
+
[self refreshFooterBottomInset];
|
|
722
|
+
[self->_controller setupSheetDetentsForSizeChange];
|
|
723
|
+
});
|
|
228
724
|
}
|
|
229
725
|
|
|
230
|
-
- (void)
|
|
231
|
-
|
|
726
|
+
- (void)containerViewContentDidChangeSize:(CGSize)newSize {
|
|
727
|
+
_controller.contentHeight = @(newSize.height);
|
|
728
|
+
[self setupSheetDetentsForSizeChange];
|
|
729
|
+
}
|
|
232
730
|
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
if (_controller.isPresented) {
|
|
237
|
-
[_controller.sheetPresentationController animateChanges:^{
|
|
238
|
-
[self->_controller setupSheetDetents];
|
|
239
|
-
[self->_controller applyActiveDetent];
|
|
240
|
-
}];
|
|
241
|
-
} else {
|
|
242
|
-
// Handle initial presentation
|
|
243
|
-
if (_initialDetentIndex >= 0 && !_controller.isPresented) {
|
|
244
|
-
[self presentAtIndex:_initialDetentIndex animated:_initialDetentAnimated completion:nil];
|
|
245
|
-
}
|
|
246
|
-
}
|
|
247
|
-
}
|
|
731
|
+
- (void)containerViewHeaderDidChangeSize:(CGSize)newSize {
|
|
732
|
+
_controller.headerHeight = @(newSize.height);
|
|
733
|
+
[self setupSheetDetentsForSizeChange];
|
|
248
734
|
}
|
|
249
735
|
|
|
250
|
-
- (void)
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
return;
|
|
256
|
-
}
|
|
736
|
+
- (void)containerViewFooterDidChangeSize:(CGSize)newSize {
|
|
737
|
+
[self syncFooterMetrics];
|
|
738
|
+
[self setupSheetDetentsForSizeChange];
|
|
739
|
+
[_controller setupAccessibilityContainer];
|
|
740
|
+
}
|
|
257
741
|
|
|
258
|
-
|
|
742
|
+
- (void)containerViewPeekDidChangeSize:(CGSize)newSize {
|
|
743
|
+
[self setupSheetDetentsForSizeChange];
|
|
744
|
+
}
|
|
259
745
|
|
|
260
|
-
|
|
261
|
-
|
|
746
|
+
// When the ScrollView changes (e.g. conditional remount), re-detect the new ScrollView.
|
|
747
|
+
- (void)containerViewScrollViewDidChange {
|
|
748
|
+
[self setupScrollable];
|
|
749
|
+
}
|
|
262
750
|
|
|
263
|
-
|
|
264
|
-
[_touchHandler attachToView:_containerView];
|
|
751
|
+
#pragma mark - TrueSheetViewControllerDelegate
|
|
265
752
|
|
|
266
|
-
|
|
267
|
-
|
|
753
|
+
- (void)viewControllerWillPresentAtIndex:(NSInteger)index position:(CGFloat)position detent:(CGFloat)detent {
|
|
754
|
+
_controller.activeDetentIndex = index;
|
|
755
|
+
[TrueSheetLifecycleEvents emitWillPresent:_eventEmitter index:index position:position detent:detent];
|
|
756
|
+
}
|
|
268
757
|
|
|
269
|
-
|
|
270
|
-
|
|
758
|
+
- (void)viewControllerDidPresentAtIndex:(NSInteger)index position:(CGFloat)position detent:(CGFloat)detent {
|
|
759
|
+
[_containerView setupKeyboardObserverWithViewController:_controller];
|
|
760
|
+
[TrueSheetLifecycleEvents emitDidPresent:_eventEmitter index:index position:position detent:detent];
|
|
271
761
|
|
|
272
|
-
|
|
273
|
-
|
|
762
|
+
if (_pendingPropsUpdate) {
|
|
763
|
+
_pendingPropsUpdate = NO;
|
|
764
|
+
[self applySheetPropsUpdate];
|
|
765
|
+
}
|
|
274
766
|
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
767
|
+
if (_pendingSizeChange) {
|
|
768
|
+
_pendingSizeChange = NO;
|
|
769
|
+
[self setupSheetDetentsForSizeChange];
|
|
770
|
+
}
|
|
771
|
+
}
|
|
280
772
|
|
|
281
|
-
|
|
282
|
-
|
|
773
|
+
- (void)viewControllerDidDrag:(UIGestureRecognizerState)state
|
|
774
|
+
index:(NSInteger)index
|
|
775
|
+
position:(CGFloat)position
|
|
776
|
+
detent:(CGFloat)detent {
|
|
777
|
+
switch (state) {
|
|
778
|
+
case UIGestureRecognizerStateBegan:
|
|
779
|
+
[TrueSheetDragEvents emitDragBegin:_eventEmitter index:index position:position detent:detent];
|
|
780
|
+
break;
|
|
781
|
+
case UIGestureRecognizerStateChanged:
|
|
782
|
+
[TrueSheetDragEvents emitDragChange:_eventEmitter index:index position:position detent:detent];
|
|
783
|
+
break;
|
|
784
|
+
case UIGestureRecognizerStateEnded:
|
|
785
|
+
case UIGestureRecognizerStateCancelled:
|
|
786
|
+
[TrueSheetDragEvents emitDragEnd:_eventEmitter index:index position:position detent:detent];
|
|
787
|
+
break;
|
|
788
|
+
default:
|
|
789
|
+
break;
|
|
283
790
|
}
|
|
284
791
|
}
|
|
285
792
|
|
|
286
|
-
- (void)
|
|
287
|
-
if (
|
|
288
|
-
|
|
793
|
+
- (void)viewControllerWillDismiss {
|
|
794
|
+
if (!_dismissedByNavigation) {
|
|
795
|
+
[TrueSheetLifecycleEvents emitWillDismiss:_eventEmitter];
|
|
796
|
+
}
|
|
797
|
+
}
|
|
289
798
|
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
}
|
|
799
|
+
- (void)viewControllerDidAttemptDismiss {
|
|
800
|
+
[TrueSheetLifecycleEvents emitDismissAttempt:_eventEmitter];
|
|
801
|
+
}
|
|
294
802
|
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
803
|
+
- (void)viewControllerDidDismiss {
|
|
804
|
+
[_containerView cleanupKeyboardObserver];
|
|
805
|
+
if (!_dismissedByNavigation) {
|
|
806
|
+
_dismissedByNavigation = NO;
|
|
807
|
+
_pendingNavigationRepresent = NO;
|
|
298
808
|
|
|
299
|
-
|
|
809
|
+
_controller.activeDetentIndex = -1;
|
|
810
|
+
[TrueSheetLifecycleEvents emitDidDismiss:_eventEmitter];
|
|
300
811
|
}
|
|
301
812
|
}
|
|
302
813
|
|
|
303
|
-
- (void)
|
|
304
|
-
|
|
305
|
-
|
|
814
|
+
- (void)viewControllerDidChangeDetent:(NSInteger)index position:(CGFloat)position detent:(CGFloat)detent {
|
|
815
|
+
if (_controller.activeDetentIndex != index) {
|
|
816
|
+
_controller.activeDetentIndex = index;
|
|
817
|
+
}
|
|
818
|
+
[TrueSheetStateEvents emitDetentChange:_eventEmitter index:index position:position detent:detent];
|
|
819
|
+
}
|
|
306
820
|
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
821
|
+
- (void)viewControllerDidChangePosition:(CGFloat)index
|
|
822
|
+
position:(CGFloat)position
|
|
823
|
+
detent:(CGFloat)detent
|
|
824
|
+
realtime:(BOOL)realtime {
|
|
825
|
+
[TrueSheetStateEvents emitPositionChange:_eventEmitter index:index position:position detent:detent realtime:realtime];
|
|
310
826
|
}
|
|
311
827
|
|
|
312
|
-
|
|
828
|
+
- (void)viewControllerDidChangeSize:(CGSize)size {
|
|
829
|
+
[self updateStateWithSize:size];
|
|
830
|
+
}
|
|
313
831
|
|
|
314
|
-
- (void)
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
CGFloat contentHeight = containerHeight > 0 ? MIN(newSize.height, containerHeight) : newSize.height;
|
|
832
|
+
- (void)viewControllerSafeAreaInsetsDidChange {
|
|
833
|
+
[self refreshFooterBottomInset];
|
|
834
|
+
}
|
|
318
835
|
|
|
319
|
-
|
|
836
|
+
- (void)viewControllerWillFocus {
|
|
837
|
+
[TrueSheetFocusEvents emitWillFocus:_eventEmitter];
|
|
838
|
+
}
|
|
320
839
|
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
// Controller viewDidLayoutSubviews will handle position notification.
|
|
325
|
-
_controller.layoutTransitioning = YES;
|
|
840
|
+
- (void)viewControllerDidFocus {
|
|
841
|
+
[TrueSheetFocusEvents emitDidFocus:_eventEmitter];
|
|
842
|
+
}
|
|
326
843
|
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
}];
|
|
330
|
-
}
|
|
844
|
+
- (void)viewControllerWillBlur {
|
|
845
|
+
[TrueSheetFocusEvents emitWillBlur:_eventEmitter];
|
|
331
846
|
}
|
|
332
847
|
|
|
333
|
-
|
|
848
|
+
- (void)viewControllerDidBlur {
|
|
849
|
+
[TrueSheetFocusEvents emitDidBlur:_eventEmitter];
|
|
850
|
+
}
|
|
334
851
|
|
|
335
|
-
-
|
|
336
|
-
NSInteger index = [_controller currentDetentIndex];
|
|
337
|
-
CGFloat position = _controller.currentPosition;
|
|
852
|
+
#pragma mark - RNScreensEventObserverDelegate
|
|
338
853
|
|
|
339
|
-
|
|
854
|
+
- (void)presenterScreenWillDisappear {
|
|
855
|
+
if (_controller.isPresented && !_controller.isBeingDismissed) {
|
|
856
|
+
_dismissedByNavigation = YES;
|
|
857
|
+
[self dismissAnimated:YES completion:nil];
|
|
858
|
+
}
|
|
859
|
+
}
|
|
340
860
|
|
|
341
|
-
|
|
861
|
+
- (void)presenterScreenWillAppear {
|
|
862
|
+
if (_dismissedByNavigation && !_controller.isPresented && !_controller.isBeingPresented) {
|
|
863
|
+
_dismissedByNavigation = NO;
|
|
342
864
|
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
865
|
+
if (self.window) {
|
|
866
|
+
[self presentAtIndex:_controller.activeDetentIndex animated:YES completion:nil];
|
|
867
|
+
} else {
|
|
868
|
+
_pendingNavigationRepresent = YES;
|
|
869
|
+
}
|
|
870
|
+
}
|
|
346
871
|
}
|
|
347
872
|
|
|
348
|
-
- (void)
|
|
349
|
-
|
|
350
|
-
|
|
873
|
+
- (void)presenterInteractiveDismissDidBegin {
|
|
874
|
+
[_controller beginInteractiveDismiss];
|
|
875
|
+
}
|
|
351
876
|
|
|
352
|
-
|
|
877
|
+
- (void)presenterInteractiveDismissDidUpdate:(CGFloat)progress {
|
|
878
|
+
[_controller updateInteractiveDismiss:progress];
|
|
353
879
|
}
|
|
354
880
|
|
|
355
|
-
- (void)
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
881
|
+
- (void)presenterInteractiveDismissDidEnd:(BOOL)cancelled duration:(NSTimeInterval)duration {
|
|
882
|
+
if (cancelled) {
|
|
883
|
+
[_controller cancelInteractiveDismissWithDuration:duration];
|
|
884
|
+
return;
|
|
885
|
+
}
|
|
360
886
|
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
887
|
+
_dismissedByNavigation = YES;
|
|
888
|
+
__weak __typeof(self) weakSelf = self;
|
|
889
|
+
[_controller finishInteractiveDismissWithDuration:duration
|
|
890
|
+
completion:^{
|
|
891
|
+
[weakSelf dismissAnimated:NO completion:nil];
|
|
892
|
+
}];
|
|
893
|
+
}
|
|
364
894
|
|
|
365
|
-
|
|
366
|
-
case UIGestureRecognizerStateCancelled:
|
|
367
|
-
[OnDragEndEvent emit:_eventEmitter index:index position:position];
|
|
368
|
-
break;
|
|
895
|
+
#pragma mark - Private Helpers
|
|
369
896
|
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
897
|
+
- (void)setupScrollable {
|
|
898
|
+
if (!_containerView)
|
|
899
|
+
return;
|
|
900
|
+
|
|
901
|
+
_containerView.scrollableOptions = _scrollableOptions;
|
|
902
|
+
_containerView.scrollableHandle = _scrollableHandle;
|
|
903
|
+
_containerView.contentInsetAdjustment = (_scrollableOptions ? _scrollableOptions.contentInsetAdjustment : YES) &&
|
|
904
|
+
_insetAdjustment == TrueSheetViewInsetAdjustment::Automatic;
|
|
905
|
+
[self refreshFooterBottomInset];
|
|
906
|
+
[_containerView setupScrollable];
|
|
373
907
|
}
|
|
374
908
|
|
|
375
|
-
|
|
376
|
-
|
|
909
|
+
// footerHeight and appliedFooterBottomInset must stay paired — detent math
|
|
910
|
+
// subtracts exactly the inset baked into the measured footer height (see
|
|
911
|
+
// autoDetentBottomInset/peekDetentBottomInset).
|
|
912
|
+
- (void)syncFooterMetrics {
|
|
913
|
+
_controller.footerHeight = @([_containerView footerHeight]);
|
|
914
|
+
_controller.appliedFooterBottomInset = [_containerView footerAppliedBottomInset];
|
|
377
915
|
}
|
|
378
916
|
|
|
379
|
-
|
|
380
|
-
|
|
917
|
+
// Recomputes the inset the footer absorbs and pushes it down. The inset
|
|
918
|
+
// depends on measured heights and detents (see maxNaturalDetentHeight), so
|
|
919
|
+
// this runs on size and detent changes — not just prop updates.
|
|
920
|
+
- (void)refreshFooterBottomInset {
|
|
921
|
+
if (!_containerView)
|
|
922
|
+
return;
|
|
381
923
|
|
|
382
|
-
|
|
924
|
+
// appliedFooterBottomInset is NOT set here — it tracks what's actually
|
|
925
|
+
// baked into the footer's measured height (reported with its layout), not
|
|
926
|
+
// what was just pushed. Setting it at push time desyncs the pair and lets
|
|
927
|
+
// a seeded inset read as natural content height (see maxNaturalDetentHeight).
|
|
928
|
+
CGFloat inset = _controller.footerBottomInset;
|
|
929
|
+
_containerView.footerBottomInset = inset;
|
|
930
|
+
|
|
931
|
+
// Publish the inset so a footer set later (e.g. navigation setOptions) is
|
|
932
|
+
// padded on its very first layout instead of resizing the sheet twice.
|
|
933
|
+
if (_insetAdjustment == TrueSheetViewInsetAdjustment::Automatic) {
|
|
934
|
+
TrueSheetInsets::setBottomSafeArea(inset);
|
|
935
|
+
}
|
|
383
936
|
}
|
|
384
937
|
|
|
385
|
-
- (void)
|
|
386
|
-
|
|
387
|
-
|
|
938
|
+
- (void)applySheetPropsUpdate {
|
|
939
|
+
BOOL pendingLayoutUpdate = _pendingLayoutUpdate;
|
|
940
|
+
_pendingLayoutUpdate = NO;
|
|
941
|
+
|
|
942
|
+
if (_pendingDetents) {
|
|
943
|
+
_controller.detents = _pendingDetents;
|
|
944
|
+
_pendingDetents = nil;
|
|
945
|
+
[self refreshFooterBottomInset];
|
|
388
946
|
}
|
|
389
947
|
|
|
390
|
-
|
|
391
|
-
|
|
948
|
+
UIView *presenterView = _controller.presentingViewController.view;
|
|
949
|
+
[_controller setupAnchorViewInView:presenterView];
|
|
392
950
|
|
|
393
|
-
|
|
394
|
-
[OnPositionChangeEvent emit:_eventEmitter index:index position:position transitioning:transitioning];
|
|
395
|
-
}
|
|
951
|
+
[_controller setupSheetSizing];
|
|
396
952
|
|
|
397
|
-
|
|
398
|
-
|
|
953
|
+
[_controller.sheetPresentationController animateChanges:^{
|
|
954
|
+
[self->_controller setupSheetProps];
|
|
955
|
+
if (pendingLayoutUpdate) {
|
|
956
|
+
[self->_controller setupSheetDetentsForDetentsChange];
|
|
957
|
+
} else {
|
|
958
|
+
[self->_controller setupSheetDetents];
|
|
959
|
+
}
|
|
960
|
+
[self->_controller applyActiveDetent];
|
|
961
|
+
}];
|
|
962
|
+
[_controller setupDraggable];
|
|
399
963
|
}
|
|
400
964
|
|
|
401
|
-
#pragma mark - Private Helpers
|
|
402
|
-
|
|
403
965
|
- (UIViewController *)findPresentingViewController {
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
if (!keyWindow) {
|
|
966
|
+
if (!self.window)
|
|
407
967
|
return nil;
|
|
408
|
-
}
|
|
409
968
|
|
|
410
|
-
UIViewController *rootViewController =
|
|
969
|
+
UIViewController *rootViewController = self.window.rootViewController;
|
|
970
|
+
if (!rootViewController)
|
|
971
|
+
return nil;
|
|
411
972
|
|
|
412
|
-
// Find
|
|
973
|
+
// Find topmost presented view controller that is not being dismissed
|
|
413
974
|
while (rootViewController.presentedViewController) {
|
|
414
975
|
UIViewController *presented = rootViewController.presentedViewController;
|
|
415
976
|
|
|
416
|
-
// Skip
|
|
417
|
-
if (
|
|
977
|
+
// Skip any view controller that is being dismissed
|
|
978
|
+
if (presented.isBeingDismissed) {
|
|
418
979
|
break;
|
|
419
980
|
}
|
|
420
|
-
|
|
421
981
|
rootViewController = presented;
|
|
422
982
|
}
|
|
423
983
|
|