@lodev09/react-native-true-sheet 4.0.0-beta.0 → 4.0.0-beta.1
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 +42 -31
- package/RNTrueSheet.podspec +10 -2
- package/android/build.gradle +2 -1
- package/android/src/main/java/com/lodev09/truesheet/TrueSheetContainerView.kt +174 -49
- package/android/src/main/java/com/lodev09/truesheet/TrueSheetContainerViewManager.kt +7 -0
- package/android/src/main/java/com/lodev09/truesheet/TrueSheetContentView.kt +371 -18
- package/android/src/main/java/com/lodev09/truesheet/TrueSheetContentViewManager.kt +14 -0
- package/android/src/main/java/com/lodev09/truesheet/TrueSheetFooterView.kt +150 -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/TrueSheetPackage.kt +5 -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 +45 -0
- package/android/src/main/java/com/lodev09/truesheet/TrueSheetView.kt +526 -231
- package/android/src/main/java/com/lodev09/truesheet/TrueSheetViewController.kt +1217 -603
- package/android/src/main/java/com/lodev09/truesheet/TrueSheetViewManager.kt +136 -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 +303 -0
- package/android/src/main/java/com/lodev09/truesheet/core/TrueSheetDetentCalculator.kt +277 -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/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 +112 -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/ViewUtils.kt +30 -0
- package/android/src/main/jni/CMakeLists.txt +63 -0
- package/android/src/main/jni/TrueSheetSpec.h +19 -0
- package/android/src/main/jni/TrueSheetStateUpdater.cpp +96 -0
- package/common/cpp/react/renderer/components/TrueSheetSpec/TrueSheetContentViewComponentDescriptor.h +24 -0
- package/common/cpp/react/renderer/components/TrueSheetSpec/TrueSheetContentViewShadowNode.cpp +43 -0
- package/common/cpp/react/renderer/components/TrueSheetSpec/TrueSheetContentViewShadowNode.h +28 -0
- package/common/cpp/react/renderer/components/TrueSheetSpec/TrueSheetContentViewState.cpp +11 -0
- package/common/cpp/react/renderer/components/TrueSheetSpec/TrueSheetContentViewState.h +37 -0
- package/common/cpp/react/renderer/components/TrueSheetSpec/TrueSheetFooterViewComponentDescriptor.h +24 -0
- package/common/cpp/react/renderer/components/TrueSheetSpec/TrueSheetFooterViewShadowNode.cpp +56 -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/TrueSheetViewComponentDescriptor.h +28 -0
- package/common/cpp/react/renderer/components/TrueSheetSpec/TrueSheetViewShadowNode.cpp +61 -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 +81 -6
- package/ios/TrueSheetContainerView.mm +275 -21
- package/ios/TrueSheetContentView.h +38 -1
- package/ios/TrueSheetContentView.mm +413 -43
- package/ios/TrueSheetFooterView.h +27 -2
- package/ios/TrueSheetFooterView.mm +141 -35
- package/ios/{events/OnDidDismissEvent.h → TrueSheetHeaderView.h} +10 -7
- package/ios/TrueSheetHeaderView.mm +64 -0
- package/ios/TrueSheetModule.mm +92 -5
- package/ios/TrueSheetPeekView.h +32 -0
- package/ios/TrueSheetPeekView.mm +99 -0
- package/ios/TrueSheetView.h +7 -15
- package/ios/TrueSheetView.mm +633 -215
- package/ios/TrueSheetViewController.h +84 -16
- package/ios/TrueSheetViewController.mm +1136 -333
- 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 +178 -0
- package/ios/core/TrueSheetKeyboardObserver.h +39 -0
- package/ios/core/TrueSheetKeyboardObserver.mm +112 -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 +40 -0
- package/ios/events/TrueSheetLifecycleEvents.mm +71 -0
- package/ios/events/TrueSheetStateEvents.h +35 -0
- package/ios/events/TrueSheetStateEvents.mm +49 -0
- package/ios/tvos/TrueSheetStubs.mm +154 -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/{events/OnWillDismissEvent.h → utils/UIView+ScrollEdgeInteraction.h} +6 -7
- package/ios/utils/UIView+ScrollEdgeInteraction.mm +62 -0
- package/ios/utils/WindowUtil.mm +17 -1
- package/lib/module/TrueSheet.js +224 -64
- package/lib/module/TrueSheet.js.map +1 -1
- package/lib/module/TrueSheet.web.js +1201 -0
- package/lib/module/TrueSheet.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/TrueSheetPeekViewNativeComponent.ts +8 -0
- package/lib/module/fabric/TrueSheetViewNativeComponent.ts +105 -18
- package/lib/module/index.js +3 -3
- package/lib/module/index.js.map +1 -1
- package/lib/module/mocks/index.js +93 -0
- package/lib/module/mocks/index.js.map +1 -0
- package/lib/module/mocks/navigation.js +85 -0
- package/lib/module/mocks/navigation.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/TrueSheetRouter.js +170 -0
- package/lib/module/navigation/TrueSheetRouter.js.map +1 -0
- package/lib/module/navigation/TrueSheetView.js +71 -0
- package/lib/module/navigation/TrueSheetView.js.map +1 -0
- package/lib/module/navigation/createTrueSheetNavigator.js +63 -0
- package/lib/module/navigation/createTrueSheetNavigator.js.map +1 -0
- package/lib/module/navigation/index.js +6 -0
- package/lib/module/navigation/index.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 +68 -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/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 +15 -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 +93 -0
- package/lib/module/web/vaul/helpers.js.map +1 -0
- package/lib/module/web/vaul/index.js +1309 -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 +51 -14
- package/lib/typescript/src/TrueSheet.d.ts.map +1 -1
- package/lib/typescript/src/TrueSheet.types.d.ts +463 -54
- 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/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/TrueSheetPeekViewNativeComponent.d.ts +6 -0
- package/lib/typescript/src/fabric/TrueSheetPeekViewNativeComponent.d.ts.map +1 -0
- package/lib/typescript/src/fabric/TrueSheetViewNativeComponent.d.ts +67 -16
- package/lib/typescript/src/fabric/TrueSheetViewNativeComponent.d.ts.map +1 -1
- package/lib/typescript/src/index.d.ts +2 -2
- package/lib/typescript/src/index.d.ts.map +1 -1
- package/lib/typescript/src/mocks/index.d.ts +43 -0
- package/lib/typescript/src/mocks/index.d.ts.map +1 -0
- package/lib/typescript/src/mocks/navigation.d.ts +66 -0
- package/lib/typescript/src/mocks/navigation.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/TrueSheetRouter.d.ts +57 -0
- package/lib/typescript/src/navigation/TrueSheetRouter.d.ts.map +1 -0
- package/lib/typescript/src/navigation/TrueSheetView.d.ts +10 -0
- package/lib/typescript/src/navigation/TrueSheetView.d.ts.map +1 -0
- package/lib/typescript/src/navigation/createTrueSheetNavigator.d.ts +35 -0
- package/lib/typescript/src/navigation/createTrueSheetNavigator.d.ts.map +1 -0
- package/lib/typescript/src/navigation/index.d.ts +6 -0
- package/lib/typescript/src/navigation/index.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 +15 -0
- package/lib/typescript/src/navigation/screen/types.d.ts.map +1 -0
- package/lib/typescript/src/navigation/screen/useSheetScreenState.d.ts +35 -0
- package/lib/typescript/src/navigation/screen/useSheetScreenState.d.ts.map +1 -0
- package/lib/typescript/src/navigation/types.d.ts +153 -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/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 +13 -0
- package/lib/typescript/src/web/vaul/constants.d.ts.map +1 -0
- package/lib/typescript/src/web/vaul/context.d.ts +53 -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 +228 -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 +78 -34
- package/react-native.config.js +9 -2
- package/src/TrueSheet.tsx +276 -60
- package/src/TrueSheet.types.ts +525 -71
- package/src/TrueSheet.web.tsx +1366 -0
- package/src/TrueSheetPeek.tsx +11 -0
- package/src/TrueSheetPeek.web.tsx +63 -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/TrueSheetPeekViewNativeComponent.ts +8 -0
- package/src/fabric/TrueSheetViewNativeComponent.ts +105 -18
- package/src/index.ts +2 -2
- package/src/mocks/index.ts +89 -0
- package/src/mocks/navigation.ts +72 -0
- package/src/mocks/reanimated.ts +101 -0
- package/src/navigation/TrueSheetRouter.ts +234 -0
- package/src/navigation/TrueSheetView.tsx +99 -0
- package/src/navigation/createTrueSheetNavigator.tsx +93 -0
- package/src/navigation/index.ts +14 -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 +21 -0
- package/src/navigation/screen/useSheetScreenState.ts +107 -0
- package/src/navigation/types.ts +219 -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/vaul/README.md +9 -0
- package/src/web/vaul/browser.ts +38 -0
- package/src/web/vaul/constants.ts +20 -0
- package/src/web/vaul/context.ts +101 -0
- package/src/web/vaul/helpers.ts +124 -0
- package/src/web/vaul/index.tsx +1740 -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.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
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
package com.lodev09.truesheet
|
|
2
2
|
|
|
3
|
-
import android.graphics.Color
|
|
4
3
|
import android.view.WindowManager
|
|
5
4
|
import com.facebook.react.bridge.ReadableArray
|
|
5
|
+
import com.facebook.react.bridge.ReadableMap
|
|
6
6
|
import com.facebook.react.module.annotations.ReactModule
|
|
7
7
|
import com.facebook.react.uimanager.PixelUtil.dpToPx
|
|
8
|
+
import com.facebook.react.uimanager.ReactStylesDiffMap
|
|
9
|
+
import com.facebook.react.uimanager.StateWrapper
|
|
8
10
|
import com.facebook.react.uimanager.ThemedReactContext
|
|
9
11
|
import com.facebook.react.uimanager.UIManagerHelper
|
|
10
12
|
import com.facebook.react.uimanager.ViewGroupManager
|
|
@@ -12,6 +14,8 @@ import com.facebook.react.uimanager.ViewManagerDelegate
|
|
|
12
14
|
import com.facebook.react.uimanager.annotations.ReactProp
|
|
13
15
|
import com.facebook.react.viewmanagers.TrueSheetViewManagerDelegate
|
|
14
16
|
import com.facebook.react.viewmanagers.TrueSheetViewManagerInterface
|
|
17
|
+
import com.lodev09.truesheet.core.AccessibilityOptions
|
|
18
|
+
import com.lodev09.truesheet.core.GrabberOptions
|
|
15
19
|
import com.lodev09.truesheet.events.*
|
|
16
20
|
|
|
17
21
|
/**
|
|
@@ -36,7 +40,7 @@ class TrueSheetViewManager :
|
|
|
36
40
|
|
|
37
41
|
override fun onAfterUpdateTransaction(view: TrueSheetView) {
|
|
38
42
|
super.onAfterUpdateTransaction(view)
|
|
39
|
-
view.
|
|
43
|
+
view.finalizeUpdates()
|
|
40
44
|
}
|
|
41
45
|
|
|
42
46
|
override fun addEventEmitters(reactContext: ThemedReactContext, view: TrueSheetView) {
|
|
@@ -44,6 +48,11 @@ class TrueSheetViewManager :
|
|
|
44
48
|
view.eventDispatcher = dispatcher
|
|
45
49
|
}
|
|
46
50
|
|
|
51
|
+
override fun updateState(view: TrueSheetView, props: ReactStylesDiffMap?, stateWrapper: StateWrapper?): Any? {
|
|
52
|
+
view.stateWrapper = stateWrapper
|
|
53
|
+
return null
|
|
54
|
+
}
|
|
55
|
+
|
|
47
56
|
override fun getDelegate(): ViewManagerDelegate<TrueSheetView> = delegate
|
|
48
57
|
|
|
49
58
|
/**
|
|
@@ -62,7 +71,11 @@ class TrueSheetViewManager :
|
|
|
62
71
|
DragChangeEvent.EVENT_NAME to hashMapOf("registrationName" to DragChangeEvent.REGISTRATION_NAME),
|
|
63
72
|
DragEndEvent.EVENT_NAME to hashMapOf("registrationName" to DragEndEvent.REGISTRATION_NAME),
|
|
64
73
|
PositionChangeEvent.EVENT_NAME to hashMapOf("registrationName" to PositionChangeEvent.REGISTRATION_NAME),
|
|
65
|
-
|
|
74
|
+
WillFocusEvent.EVENT_NAME to hashMapOf("registrationName" to WillFocusEvent.REGISTRATION_NAME),
|
|
75
|
+
FocusEvent.EVENT_NAME to hashMapOf("registrationName" to FocusEvent.REGISTRATION_NAME),
|
|
76
|
+
WillBlurEvent.EVENT_NAME to hashMapOf("registrationName" to WillBlurEvent.REGISTRATION_NAME),
|
|
77
|
+
BlurEvent.EVENT_NAME to hashMapOf("registrationName" to BlurEvent.REGISTRATION_NAME),
|
|
78
|
+
VisibilityChangeEvent.EVENT_NAME to hashMapOf("registrationName" to VisibilityChangeEvent.REGISTRATION_NAME)
|
|
66
79
|
)
|
|
67
80
|
|
|
68
81
|
// ==================== Props ====================
|
|
@@ -85,16 +98,14 @@ class TrueSheetViewManager :
|
|
|
85
98
|
view.setDetents(detents)
|
|
86
99
|
}
|
|
87
100
|
|
|
88
|
-
@ReactProp(name = "
|
|
89
|
-
override fun
|
|
101
|
+
@ReactProp(name = "backgroundColor", customType = "Color")
|
|
102
|
+
override fun setBackgroundColor(view: TrueSheetView, color: Int?) {
|
|
90
103
|
view.setSheetBackgroundColor(color)
|
|
91
104
|
}
|
|
92
105
|
|
|
93
106
|
@ReactProp(name = "cornerRadius", defaultDouble = -1.0)
|
|
94
107
|
override fun setCornerRadius(view: TrueSheetView, radius: Double) {
|
|
95
|
-
|
|
96
|
-
view.setCornerRadius(radius.dpToPx())
|
|
97
|
-
}
|
|
108
|
+
view.setCornerRadius(radius.dpToPx())
|
|
98
109
|
}
|
|
99
110
|
|
|
100
111
|
@ReactProp(name = "grabber", defaultBoolean = true)
|
|
@@ -102,19 +113,67 @@ class TrueSheetViewManager :
|
|
|
102
113
|
view.setGrabber(grabber)
|
|
103
114
|
}
|
|
104
115
|
|
|
116
|
+
@ReactProp(name = "grabberOptions")
|
|
117
|
+
override fun setGrabberOptions(view: TrueSheetView, options: ReadableMap?) {
|
|
118
|
+
if (options == null) {
|
|
119
|
+
view.setGrabberOptions(null)
|
|
120
|
+
return
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
val grabberOptions = GrabberOptions(
|
|
124
|
+
width = if (options.hasKey("width")) options.getDouble("width").toFloat() else null,
|
|
125
|
+
height = if (options.hasKey("height")) options.getDouble("height").toFloat() else null,
|
|
126
|
+
topMargin = if (options.hasKey("topMargin")) options.getDouble("topMargin").toFloat() else null,
|
|
127
|
+
cornerRadius = if (options.hasKey("cornerRadius") &&
|
|
128
|
+
options.getDouble("cornerRadius") >= 0
|
|
129
|
+
) {
|
|
130
|
+
options.getDouble("cornerRadius").toFloat()
|
|
131
|
+
} else {
|
|
132
|
+
null
|
|
133
|
+
},
|
|
134
|
+
color = if (options.hasKey("color") && !options.isNull("color")) options.getInt("color") else null,
|
|
135
|
+
adaptive = if (options.hasKey("adaptive")) options.getBoolean("adaptive") else true
|
|
136
|
+
)
|
|
137
|
+
view.setGrabberOptions(grabberOptions)
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
@ReactProp(name = "accessibilityOptions")
|
|
141
|
+
override fun setAccessibilityOptions(view: TrueSheetView, options: ReadableMap?) {
|
|
142
|
+
if (options == null) {
|
|
143
|
+
view.setAccessibilityOptions(null)
|
|
144
|
+
return
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
val accessibilityOptions = AccessibilityOptions(
|
|
148
|
+
grabberLabel = if (options.hasKey("grabberLabel")) options.getString("grabberLabel") else null,
|
|
149
|
+
expandedValue = if (options.hasKey("expandedValue")) options.getString("expandedValue") else null,
|
|
150
|
+
collapsedValue = if (options.hasKey("collapsedValue")) options.getString("collapsedValue") else null,
|
|
151
|
+
detentValue = if (options.hasKey("detentValue")) options.getString("detentValue") else null,
|
|
152
|
+
expandActionLabel = if (options.hasKey("expandActionLabel")) options.getString("expandActionLabel") else null,
|
|
153
|
+
collapseActionLabel = if (options.hasKey("collapseActionLabel")) options.getString("collapseActionLabel") else null,
|
|
154
|
+
paneTitle = if (options.hasKey("paneTitle")) options.getString("paneTitle") else null
|
|
155
|
+
)
|
|
156
|
+
view.setAccessibilityOptions(accessibilityOptions)
|
|
157
|
+
}
|
|
158
|
+
|
|
105
159
|
@ReactProp(name = "dismissible", defaultBoolean = true)
|
|
106
160
|
override fun setDismissible(view: TrueSheetView, dismissible: Boolean) {
|
|
107
161
|
view.setDismissible(dismissible)
|
|
108
162
|
}
|
|
109
163
|
|
|
164
|
+
@ReactProp(name = "draggable", defaultBoolean = true)
|
|
165
|
+
override fun setDraggable(view: TrueSheetView, draggable: Boolean) {
|
|
166
|
+
view.setDraggable(draggable)
|
|
167
|
+
}
|
|
168
|
+
|
|
110
169
|
@ReactProp(name = "dimmed", defaultBoolean = true)
|
|
111
170
|
override fun setDimmed(view: TrueSheetView, dimmed: Boolean) {
|
|
112
171
|
view.setDimmed(dimmed)
|
|
113
172
|
}
|
|
114
173
|
|
|
115
|
-
@ReactProp(name = "
|
|
116
|
-
override fun
|
|
117
|
-
view.
|
|
174
|
+
@ReactProp(name = "dimmedDetentIndex", defaultInt = 0)
|
|
175
|
+
override fun setDimmedDetentIndex(view: TrueSheetView, index: Int) {
|
|
176
|
+
view.setDimmedDetentIndex(index)
|
|
118
177
|
}
|
|
119
178
|
|
|
120
179
|
@ReactProp(name = "initialDetentIndex", defaultInt = -1)
|
|
@@ -127,31 +186,79 @@ class TrueSheetViewManager :
|
|
|
127
186
|
view.initialDetentAnimated = animate
|
|
128
187
|
}
|
|
129
188
|
|
|
130
|
-
@ReactProp(name = "
|
|
131
|
-
override fun
|
|
132
|
-
if (height > 0)
|
|
133
|
-
view.setMaxHeight(height.dpToPx().toInt())
|
|
134
|
-
}
|
|
189
|
+
@ReactProp(name = "maxContentHeight", defaultDouble = 0.0)
|
|
190
|
+
override fun setMaxContentHeight(view: TrueSheetView, height: Double) {
|
|
191
|
+
view.setMaxContentHeight(if (height > 0) height.dpToPx().toInt() else null)
|
|
135
192
|
}
|
|
136
193
|
|
|
137
|
-
@ReactProp(name = "
|
|
138
|
-
override fun
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
194
|
+
@ReactProp(name = "maxContentWidth", defaultDouble = 0.0)
|
|
195
|
+
override fun setMaxContentWidth(view: TrueSheetView, width: Double) {
|
|
196
|
+
view.setMaxContentWidth(if (width > 0) width.dpToPx().toInt() else null)
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
@ReactProp(name = "anchor")
|
|
200
|
+
override fun setAnchor(view: TrueSheetView, anchor: String?) {
|
|
201
|
+
view.setAnchor(anchor)
|
|
144
202
|
}
|
|
145
203
|
|
|
146
|
-
@ReactProp(name = "
|
|
147
|
-
override fun
|
|
204
|
+
@ReactProp(name = "anchorOffset", defaultDouble = 0.0)
|
|
205
|
+
override fun setAnchorOffset(view: TrueSheetView, offset: Double) {
|
|
206
|
+
view.setAnchorOffset(if (offset > 0) offset.dpToPx().toInt() else 0)
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
@ReactProp(name = "backgroundBlur")
|
|
210
|
+
override fun setBackgroundBlur(view: TrueSheetView, tint: String?) {
|
|
211
|
+
// iOS-specific prop - no-op on Android
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
@ReactProp(name = "blurOptions")
|
|
215
|
+
override fun setBlurOptions(view: TrueSheetView, options: ReadableMap?) {
|
|
148
216
|
// iOS-specific prop - no-op on Android
|
|
149
|
-
view.setBlurTint(tint)
|
|
150
217
|
}
|
|
151
218
|
|
|
152
|
-
@ReactProp(name = "
|
|
153
|
-
override fun
|
|
154
|
-
view.
|
|
219
|
+
@ReactProp(name = "insetAdjustment")
|
|
220
|
+
override fun setInsetAdjustment(view: TrueSheetView, insetAdjustment: String?) {
|
|
221
|
+
view.setInsetAdjustment(insetAdjustment ?: "automatic")
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
@ReactProp(name = "presentation")
|
|
225
|
+
override fun setPresentation(view: TrueSheetView, value: String?) {
|
|
226
|
+
// iOS/web-specific prop - no-op on Android
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
@ReactProp(name = "elevation", defaultDouble = -1.0)
|
|
230
|
+
override fun setElevation(view: TrueSheetView, elevation: Double) {
|
|
231
|
+
view.setSheetElevation(elevation.toFloat())
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
@ReactProp(name = "scrollableOptions")
|
|
235
|
+
override fun setScrollableOptions(view: TrueSheetView, options: ReadableMap?) {
|
|
236
|
+
if (options == null) {
|
|
237
|
+
view.setScrollableOptions(null)
|
|
238
|
+
return
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
val scrollableOptions = ScrollableOptions(
|
|
242
|
+
keyboardScrollOffset = if (options.hasKey("keyboardScrollOffset")) options.getDouble("keyboardScrollOffset").toFloat() else 0f,
|
|
243
|
+
scrollingExpandsSheet = if (options.hasKey("scrollingExpandsSheet")) options.getBoolean("scrollingExpandsSheet") else true
|
|
244
|
+
)
|
|
245
|
+
view.setScrollableOptions(scrollableOptions)
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
@ReactProp(name = "headerOptions")
|
|
249
|
+
override fun setHeaderOptions(view: TrueSheetView, options: ReadableMap?) {
|
|
250
|
+
val position = if (options != null && options.hasKey("position")) options.getString("position") else null
|
|
251
|
+
view.setAbsoluteHeader(position == "absolute")
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
@ReactProp(name = "footerOptions")
|
|
255
|
+
override fun setFooterOptions(view: TrueSheetView, options: ReadableMap?) {
|
|
256
|
+
val position = if (options != null && options.hasKey("footerPosition")) options.getString("footerPosition") else null
|
|
257
|
+
view.setAbsoluteFooter(position == "absolute")
|
|
258
|
+
|
|
259
|
+
val keyboardOffset =
|
|
260
|
+
if (options != null && options.hasKey("keyboardOffset")) options.getDouble("keyboardOffset").toFloat() else 0f
|
|
261
|
+
view.setFooterKeyboardOffset(keyboardOffset)
|
|
155
262
|
}
|
|
156
263
|
|
|
157
264
|
companion object {
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
package com.lodev09.truesheet.core
|
|
2
|
+
|
|
3
|
+
import android.view.View
|
|
4
|
+
import com.facebook.react.uimanager.events.Event
|
|
5
|
+
import com.facebook.react.uimanager.events.EventDispatcher
|
|
6
|
+
import com.facebook.react.uimanager.events.EventDispatcherListener
|
|
7
|
+
|
|
8
|
+
private const val RN_SCREENS_VIEW_CLASS = "com.swmansion.rnscreens.Screen"
|
|
9
|
+
|
|
10
|
+
interface RNScreensEventObserverDelegate {
|
|
11
|
+
fun presenterScreenWillDisappear()
|
|
12
|
+
fun presenterScreenWillAppear()
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Observes react-native-screens lifecycle events via EventDispatcherListener.
|
|
17
|
+
* Detects when the presenting screen unmounts while sheet is presented.
|
|
18
|
+
*/
|
|
19
|
+
class RNScreensEventObserver : EventDispatcherListener {
|
|
20
|
+
var delegate: RNScreensEventObserverDelegate? = null
|
|
21
|
+
|
|
22
|
+
private var eventDispatcher: EventDispatcher? = null
|
|
23
|
+
var presenterScreenTag: Int = 0
|
|
24
|
+
|
|
25
|
+
fun startObserving(dispatcher: EventDispatcher?) {
|
|
26
|
+
if (eventDispatcher != null || dispatcher == null) return
|
|
27
|
+
|
|
28
|
+
eventDispatcher = dispatcher
|
|
29
|
+
dispatcher.addListener(this)
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
fun stopObserving() {
|
|
33
|
+
eventDispatcher?.removeListener(this)
|
|
34
|
+
eventDispatcher = null
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
fun capturePresenterScreenFromView(view: View?) {
|
|
38
|
+
presenterScreenTag = 0
|
|
39
|
+
|
|
40
|
+
var current: View? = view
|
|
41
|
+
while (current != null) {
|
|
42
|
+
if (isScreenView(current)) {
|
|
43
|
+
presenterScreenTag = current.id
|
|
44
|
+
break
|
|
45
|
+
}
|
|
46
|
+
current = (current.parent as? View)
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
override fun onEventDispatch(event: Event<*>) {
|
|
51
|
+
// Only process events for the presenter screen
|
|
52
|
+
if (presenterScreenTag == 0 || event.viewTag != presenterScreenTag) return
|
|
53
|
+
|
|
54
|
+
when (event.eventName) {
|
|
55
|
+
"topWillDisappear" -> delegate?.presenterScreenWillDisappear()
|
|
56
|
+
"topWillAppear" -> delegate?.presenterScreenWillAppear()
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
companion object {
|
|
61
|
+
private fun isScreenView(view: View): Boolean = view.javaClass.name == RN_SCREENS_VIEW_CLASS
|
|
62
|
+
}
|
|
63
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
package com.lodev09.truesheet.core
|
|
2
|
+
|
|
3
|
+
import android.view.View
|
|
4
|
+
import androidx.coordinatorlayout.widget.CoordinatorLayout
|
|
5
|
+
import com.google.android.material.bottomsheet.BottomSheetBehavior
|
|
6
|
+
|
|
7
|
+
class TrueSheetBottomSheetBehavior<V : View> : BottomSheetBehavior<V>() {
|
|
8
|
+
var scrollingExpandsSheet: Boolean = true
|
|
9
|
+
|
|
10
|
+
override fun onNestedPreScroll(
|
|
11
|
+
coordinatorLayout: CoordinatorLayout,
|
|
12
|
+
child: V,
|
|
13
|
+
target: View,
|
|
14
|
+
dx: Int,
|
|
15
|
+
dy: Int,
|
|
16
|
+
consumed: IntArray,
|
|
17
|
+
type: Int
|
|
18
|
+
) {
|
|
19
|
+
// dy > 0 = user swiping up = sheet expanding
|
|
20
|
+
// Block expansion from scroll, but allow if sheet is already being dragged
|
|
21
|
+
if (!scrollingExpandsSheet && dy > 0 && state != STATE_DRAGGING) return
|
|
22
|
+
super.onNestedPreScroll(coordinatorLayout, child, target, dx, dy, consumed, type)
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
override fun onNestedPreFling(
|
|
26
|
+
coordinatorLayout: CoordinatorLayout,
|
|
27
|
+
child: V,
|
|
28
|
+
target: View,
|
|
29
|
+
velocityX: Float,
|
|
30
|
+
velocityY: Float
|
|
31
|
+
): Boolean {
|
|
32
|
+
// Don't consume flings — let the ScrollView decelerate naturally
|
|
33
|
+
if (!scrollingExpandsSheet) return false
|
|
34
|
+
return super.onNestedPreFling(coordinatorLayout, child, target, velocityX, velocityY)
|
|
35
|
+
}
|
|
36
|
+
}
|
|
@@ -0,0 +1,255 @@
|
|
|
1
|
+
package com.lodev09.truesheet.core
|
|
2
|
+
|
|
3
|
+
import android.annotation.SuppressLint
|
|
4
|
+
import android.content.res.Configuration
|
|
5
|
+
import android.graphics.Color
|
|
6
|
+
import android.graphics.Outline
|
|
7
|
+
import android.graphics.Rect
|
|
8
|
+
import android.graphics.drawable.ShapeDrawable
|
|
9
|
+
import android.graphics.drawable.shapes.RoundRectShape
|
|
10
|
+
import android.view.GestureDetector
|
|
11
|
+
import android.view.Gravity
|
|
12
|
+
import android.view.MotionEvent
|
|
13
|
+
import android.view.View
|
|
14
|
+
import android.view.ViewOutlineProvider
|
|
15
|
+
import android.widget.FrameLayout
|
|
16
|
+
import androidx.coordinatorlayout.widget.CoordinatorLayout
|
|
17
|
+
import androidx.core.view.ViewCompat
|
|
18
|
+
import com.facebook.react.uimanager.PixelUtil.dpToPx
|
|
19
|
+
import com.facebook.react.uimanager.ThemedReactContext
|
|
20
|
+
import com.google.android.material.bottomsheet.BottomSheetBehavior
|
|
21
|
+
import com.lodev09.truesheet.TrueSheetAnchor
|
|
22
|
+
import com.lodev09.truesheet.utils.ScreenUtils
|
|
23
|
+
|
|
24
|
+
interface TrueSheetBottomSheetViewDelegate {
|
|
25
|
+
val isTopmostSheet: Boolean
|
|
26
|
+
val sheetCornerRadius: Float
|
|
27
|
+
val sheetElevation: Float
|
|
28
|
+
val sheetBackgroundColor: Int?
|
|
29
|
+
val maxContentWidth: Int?
|
|
30
|
+
val anchor: TrueSheetAnchor
|
|
31
|
+
val anchorOffset: Int
|
|
32
|
+
val grabber: Boolean
|
|
33
|
+
val grabberOptions: GrabberOptions?
|
|
34
|
+
val accessibilityOptions: AccessibilityOptions?
|
|
35
|
+
val draggable: Boolean
|
|
36
|
+
fun bottomSheetViewDidTapGrabber()
|
|
37
|
+
fun bottomSheetViewDidAccessibilityIncrement()
|
|
38
|
+
fun bottomSheetViewDidAccessibilityDecrement()
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* The bottom sheet view that holds the content.
|
|
43
|
+
* This view has BottomSheetBehavior attached via CoordinatorLayout.LayoutParams.
|
|
44
|
+
*
|
|
45
|
+
* Touch dispatching to React Native is handled by TrueSheetViewController,
|
|
46
|
+
* which is the actual RootView containing the React content.
|
|
47
|
+
*/
|
|
48
|
+
@SuppressLint("ViewConstructor")
|
|
49
|
+
class TrueSheetBottomSheetView(private val reactContext: ThemedReactContext) : FrameLayout(reactContext) {
|
|
50
|
+
|
|
51
|
+
companion object {
|
|
52
|
+
private const val GRABBER_TAG = "TrueSheetGrabber"
|
|
53
|
+
private const val DEFAULT_CORNER_RADIUS = 16f // dp
|
|
54
|
+
private const val DEFAULT_MAX_WIDTH = 640 // dp
|
|
55
|
+
private const val DEFAULT_ELEVATION = 4f // dp
|
|
56
|
+
|
|
57
|
+
// M3 baseline surfaceContainerLow
|
|
58
|
+
private val COLOR_SURFACE_CONTAINER_LOW_LIGHT = Color.parseColor("#F7F2FA")
|
|
59
|
+
private val COLOR_SURFACE_CONTAINER_LOW_DARK = Color.parseColor("#1D1B20")
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// =============================================================================
|
|
63
|
+
// MARK: - Properties
|
|
64
|
+
// =============================================================================
|
|
65
|
+
|
|
66
|
+
var delegate: TrueSheetBottomSheetViewDelegate? = null
|
|
67
|
+
|
|
68
|
+
// Behavior reference (set after adding to CoordinatorLayout)
|
|
69
|
+
@Suppress("UNCHECKED_CAST")
|
|
70
|
+
val behavior: TrueSheetBottomSheetBehavior<TrueSheetBottomSheetView>?
|
|
71
|
+
get() = (layoutParams as? CoordinatorLayout.LayoutParams)
|
|
72
|
+
?.behavior as? TrueSheetBottomSheetBehavior<TrueSheetBottomSheetView>
|
|
73
|
+
|
|
74
|
+
// =============================================================================
|
|
75
|
+
// MARK: - Initialization
|
|
76
|
+
// =============================================================================
|
|
77
|
+
|
|
78
|
+
init {
|
|
79
|
+
// Allow content to extend beyond bounds (for footer positioning)
|
|
80
|
+
clipChildren = false
|
|
81
|
+
clipToPadding = false
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
override fun setTranslationY(translationY: Float) {
|
|
85
|
+
// This prevents keyboard inset animations from resetting parent sheet translation
|
|
86
|
+
if (translationY == 0f && this.translationY != 0f) {
|
|
87
|
+
return
|
|
88
|
+
}
|
|
89
|
+
super.setTranslationY(translationY)
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// =============================================================================
|
|
93
|
+
// MARK: - Layout
|
|
94
|
+
// =============================================================================
|
|
95
|
+
|
|
96
|
+
private fun resolveAnchor(): Pair<Int, Int> {
|
|
97
|
+
val anchor = if (ScreenUtils.isPortraitPhone(reactContext)) null else delegate?.anchor
|
|
98
|
+
val gravity = when (anchor) {
|
|
99
|
+
TrueSheetAnchor.LEFT -> Gravity.START
|
|
100
|
+
TrueSheetAnchor.RIGHT -> Gravity.END
|
|
101
|
+
else -> Gravity.CENTER_HORIZONTAL
|
|
102
|
+
} or Gravity.BOTTOM
|
|
103
|
+
val margin = if (anchor == TrueSheetAnchor.LEFT || anchor == TrueSheetAnchor.RIGHT) delegate?.anchorOffset ?: 0 else 0
|
|
104
|
+
return Pair(gravity, margin)
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Creates layout params with BottomSheetBehavior attached.
|
|
109
|
+
*/
|
|
110
|
+
fun createLayoutParams(): CoordinatorLayout.LayoutParams {
|
|
111
|
+
val applyMaxWidth = delegate?.maxContentWidth != null && !ScreenUtils.isPortraitPhone(reactContext)
|
|
112
|
+
val effectiveMaxWidth = if (applyMaxWidth) delegate!!.maxContentWidth!! else DEFAULT_MAX_WIDTH.dpToPx().toInt()
|
|
113
|
+
val behavior = TrueSheetBottomSheetBehavior<TrueSheetBottomSheetView>().apply {
|
|
114
|
+
isHideable = true
|
|
115
|
+
maxWidth = effectiveMaxWidth
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
val (gravity, margin) = resolveAnchor()
|
|
119
|
+
|
|
120
|
+
return CoordinatorLayout.LayoutParams(
|
|
121
|
+
CoordinatorLayout.LayoutParams.MATCH_PARENT,
|
|
122
|
+
CoordinatorLayout.LayoutParams.MATCH_PARENT
|
|
123
|
+
).apply {
|
|
124
|
+
this.behavior = behavior
|
|
125
|
+
this.gravity = gravity
|
|
126
|
+
this.marginStart = margin
|
|
127
|
+
this.marginEnd = margin
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
fun updateGravity() {
|
|
132
|
+
val params = layoutParams as? CoordinatorLayout.LayoutParams ?: return
|
|
133
|
+
val (gravity, margin) = resolveAnchor()
|
|
134
|
+
|
|
135
|
+
if (params.gravity == gravity && params.marginStart == margin) return
|
|
136
|
+
|
|
137
|
+
params.gravity = gravity
|
|
138
|
+
params.marginStart = margin
|
|
139
|
+
params.marginEnd = margin
|
|
140
|
+
layoutParams = params
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
// =============================================================================
|
|
144
|
+
// MARK: - Background & Styling
|
|
145
|
+
// =============================================================================
|
|
146
|
+
|
|
147
|
+
fun setupBackground() {
|
|
148
|
+
val radius = delegate?.sheetCornerRadius ?: DEFAULT_CORNER_RADIUS.dpToPx()
|
|
149
|
+
val effectiveRadius = if (radius < 0) DEFAULT_CORNER_RADIUS.dpToPx() else radius
|
|
150
|
+
|
|
151
|
+
val outerRadii = floatArrayOf(
|
|
152
|
+
effectiveRadius,
|
|
153
|
+
effectiveRadius, // top-left
|
|
154
|
+
effectiveRadius,
|
|
155
|
+
effectiveRadius, // top-right
|
|
156
|
+
0f,
|
|
157
|
+
0f, // bottom-right
|
|
158
|
+
0f,
|
|
159
|
+
0f // bottom-left
|
|
160
|
+
)
|
|
161
|
+
|
|
162
|
+
val color = delegate?.sheetBackgroundColor ?: getDefaultBackgroundColor()
|
|
163
|
+
|
|
164
|
+
background = ShapeDrawable(RoundRectShape(outerRadii, null, null)).apply {
|
|
165
|
+
paint.color = color
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
outlineProvider = object : ViewOutlineProvider() {
|
|
169
|
+
override fun getOutline(view: View, outline: Outline) {
|
|
170
|
+
outline.setRoundRect(0, 0, view.width, view.height, effectiveRadius)
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
clipToOutline = true
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
private fun getDefaultBackgroundColor(): Int {
|
|
177
|
+
val isNight = (
|
|
178
|
+
reactContext.resources.configuration.uiMode and
|
|
179
|
+
Configuration.UI_MODE_NIGHT_MASK
|
|
180
|
+
) == Configuration.UI_MODE_NIGHT_YES
|
|
181
|
+
return if (isNight) COLOR_SURFACE_CONTAINER_LOW_DARK else COLOR_SURFACE_CONTAINER_LOW_LIGHT
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
fun setupElevation() {
|
|
185
|
+
val value = delegate?.sheetElevation ?: DEFAULT_ELEVATION
|
|
186
|
+
val effectiveElevation = if (value < 0) DEFAULT_ELEVATION else value
|
|
187
|
+
elevation = effectiveElevation.dpToPx()
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
// =============================================================================
|
|
191
|
+
// MARK: - Grabber
|
|
192
|
+
// =============================================================================
|
|
193
|
+
|
|
194
|
+
fun setupGrabber() {
|
|
195
|
+
findViewWithTag<View>(GRABBER_TAG)?.let { removeView(it) }
|
|
196
|
+
|
|
197
|
+
// Content view is the controller, added before the grabber (delegate is the controller)
|
|
198
|
+
val contentView = delegate as? View
|
|
199
|
+
|
|
200
|
+
val isEnabled = delegate?.grabber ?: true
|
|
201
|
+
val isDraggable = delegate?.draggable ?: true
|
|
202
|
+
if (!isEnabled || !isDraggable) {
|
|
203
|
+
contentView?.accessibilityTraversalAfter = View.NO_ID
|
|
204
|
+
return
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
val grabberView = TrueSheetGrabberView(reactContext, delegate?.grabberOptions, delegate?.accessibilityOptions).apply {
|
|
208
|
+
tag = GRABBER_TAG
|
|
209
|
+
id = View.generateViewId()
|
|
210
|
+
onAccessibilityIncrement = { delegate?.bottomSheetViewDidAccessibilityIncrement() }
|
|
211
|
+
onAccessibilityDecrement = { delegate?.bottomSheetViewDidAccessibilityDecrement() }
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
addView(grabberView)
|
|
215
|
+
|
|
216
|
+
// Grabber is added after content for z-ordering, but should be announced first
|
|
217
|
+
contentView?.accessibilityTraversalAfter = grabberView.id
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
fun updateGrabberAccessibilityValue(index: Int, detentCount: Int) {
|
|
221
|
+
findViewWithTag<TrueSheetGrabberView>(GRABBER_TAG)?.updateAccessibilityValue(index, detentCount)
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
fun setupAccessibility() {
|
|
225
|
+
ViewCompat.setAccessibilityPaneTitle(this, delegate?.accessibilityOptions?.paneTitle ?: "Bottom sheet")
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
// =============================================================================
|
|
229
|
+
// MARK: - Grabber Tap Detection
|
|
230
|
+
// =============================================================================
|
|
231
|
+
|
|
232
|
+
private val grabberTapDetector = GestureDetector(
|
|
233
|
+
context,
|
|
234
|
+
object : GestureDetector.SimpleOnGestureListener() {
|
|
235
|
+
override fun onSingleTapUp(e: MotionEvent): Boolean {
|
|
236
|
+
delegate?.bottomSheetViewDidTapGrabber()
|
|
237
|
+
return true
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
)
|
|
241
|
+
|
|
242
|
+
override fun dispatchTouchEvent(ev: MotionEvent): Boolean {
|
|
243
|
+
val grabber = findViewWithTag<View>(GRABBER_TAG)
|
|
244
|
+
if (grabber != null) {
|
|
245
|
+
val rect = Rect()
|
|
246
|
+
grabber.getHitRect(rect)
|
|
247
|
+
if (rect.contains(ev.x.toInt(), ev.y.toInt())) {
|
|
248
|
+
if (grabberTapDetector.onTouchEvent(ev)) {
|
|
249
|
+
return true
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
return super.dispatchTouchEvent(ev)
|
|
254
|
+
}
|
|
255
|
+
}
|