diff --git a/README.md b/README.md index fa39a8b..3845685 100644 --- a/README.md +++ b/README.md @@ -31,7 +31,7 @@ npm i @lodev09/react-native-true-sheet ## Usage -```ts +```tsx import { TrueSheet } from "@lodev09/react-native-true-sheet" // ... @@ -78,7 +78,7 @@ Extends `ViewProps` ## Methods -```ts +```tsx const sheet = useRef(null) const resize = () => { @@ -108,7 +108,7 @@ return ( ## Events -```ts +```tsx const handleSizeChange = (info: SizeInfo) => { console.log(info) } @@ -130,7 +130,7 @@ return ( ### `SheetSize` -```ts +```tsx // ... @@ -166,7 +166,7 @@ Grabber props to be used for android grabber or handle. Blur tint that is mapped into native values in iOS. -```ts +```tsx // ... @@ -200,7 +200,7 @@ Blur tint that is mapped into native values in iOS. `Object` that comes with some events. -```ts +```tsx { index: 1, value: 69 @@ -216,25 +216,37 @@ Blur tint that is mapped into native values in iOS. When using `jest`, simply mock the entire package. -```ts +```tsx jest.mock('@lodev09/react-native-true-sheet') ``` ## Troubleshooting +### Handling `ScrollView` on **Android** + +On Android, `nestedScrollEnabled` needs to be enabled so that scrolling works when the sheet is expanded to its `maxHeight`. + +```tsx + + + // ... + + +``` + ### Using `react-native-gesture-handler` on **Android** On Android, RNGH does not work by default because modals are not located under React Native Root view in native hierarchy. To fix that, components need to be wrapped with `GestureHandlerRootView`. Example: -```ts +```tsx import { GestureHandlerRootView } from 'react-native-gesture-handler' ``` -```ts +```tsx return ( - + // ... ) @@ -245,7 +257,7 @@ return ( On iOS, navigating to a [React Navigation](https://reactnavigation.org) screen from within the Sheet can cause issues. To resolve this, dismiss the sheet before navigating! Example: -```ts +```tsx const sheet = useRef(null) const navigate = async () => { diff --git a/android/src/main/java/com/lodev09/truesheet/TrueSheetBehavior.kt b/android/src/main/java/com/lodev09/truesheet/TrueSheetBehavior.kt deleted file mode 100644 index ff652e6..0000000 --- a/android/src/main/java/com/lodev09/truesheet/TrueSheetBehavior.kt +++ /dev/null @@ -1,230 +0,0 @@ -package com.lodev09.truesheet - -import android.view.MotionEvent -import android.view.ViewGroup -import android.widget.ScrollView -import androidx.coordinatorlayout.widget.CoordinatorLayout -import com.facebook.react.bridge.ReactContext -import com.google.android.material.bottomsheet.BottomSheetBehavior -import com.lodev09.truesheet.core.Utils - -data class SizeInfo(val index: Int, val value: Float) - -class TrueSheetBehavior(private val reactContext: ReactContext) : BottomSheetBehavior() { - var maxScreenHeight: Int = 0 - var maxSheetHeight: Int? = null - - var contentView: ViewGroup? = null - var footerView: ViewGroup? = null - - var sizes: Array = arrayOf("medium", "large") - - override fun onInterceptTouchEvent(parent: CoordinatorLayout, child: ViewGroup, event: MotionEvent): Boolean { - contentView?.let { - val isDownEvent = (event.actionMasked == MotionEvent.ACTION_DOWN) - val expanded = state == STATE_EXPANDED - - if (isDownEvent && expanded) { - for (i in 0 until it.childCount) { - val contentChild = it.getChildAt(i) - val scrolled = (contentChild is ScrollView && contentChild.scrollY > 0) - - if (!scrolled) continue - if (isInsideSheet(contentChild as ScrollView, event)) { - return false - } - } - } - } - - return super.onInterceptTouchEvent(parent, child, event) - } - - private fun isInsideSheet(scrollView: ScrollView, event: MotionEvent): Boolean { - val x = event.x - val y = event.y - - val position = IntArray(2) - scrollView.getLocationOnScreen(position) - - val nestedX = position[0] - val nestedY = position[1] - - val boundRight = nestedX + scrollView.width - val boundBottom = nestedY + scrollView.height - - return (x > nestedX && x < boundRight && y > nestedY && y < boundBottom) || - event.action == MotionEvent.ACTION_CANCEL - } - - /** - * Get the height value based on the size config value. - */ - private fun getSizeHeight(size: Any, contentHeight: Int): Int { - val height = - when (size) { - is Double -> Utils.toPixel(size) - - is Int -> Utils.toPixel(size.toDouble()) - - is String -> { - when (size) { - "auto" -> contentHeight - - "large" -> maxScreenHeight - - "medium" -> (maxScreenHeight * 0.50).toInt() - - "small" -> (maxScreenHeight * 0.25).toInt() - - else -> { - if (size.endsWith('%')) { - val percent = size.trim('%').toDoubleOrNull() - if (percent == null) { - 0 - } else { - ((percent / 100) * maxScreenHeight).toInt() - } - } else { - val fixedHeight = size.toDoubleOrNull() - if (fixedHeight == null) { - 0 - } else { - Utils.toPixel(fixedHeight) - } - } - } - } - } - - else -> (maxScreenHeight * 0.5).toInt() - } - - return minOf(height, maxSheetHeight ?: maxScreenHeight) - } - - /** - * Determines the state based on the given size index. - */ - fun getStateForSizeIndex(index: Int) = - when (sizes.size) { - 1 -> STATE_EXPANDED - - 2 -> { - when (index) { - 0 -> STATE_COLLAPSED - 1 -> STATE_EXPANDED - else -> STATE_HIDDEN - } - } - - 3 -> { - when (index) { - 0 -> STATE_COLLAPSED - 1 -> STATE_HALF_EXPANDED - 2 -> STATE_EXPANDED - else -> STATE_HIDDEN - } - } - - else -> STATE_HIDDEN - } - - /** - * Configure the sheet based on size preferences. - */ - fun configure() { - // Update the usable sheet height - maxScreenHeight = Utils.screenHeight(reactContext) - - var contentHeight = 0 - - contentView?.let { contentHeight = it.height } - footerView?.let { contentHeight += it.height } - - // Configure sheet sizes - apply { - skipCollapsed = false - isFitToContents = true - - // m3 max width 640dp - maxWidth = Utils.toPixel(640.0) - - when (sizes.size) { - 1 -> { - maxHeight = getSizeHeight(sizes[0], contentHeight) - peekHeight = maxHeight - skipCollapsed = true - } - - 2 -> { - peekHeight = getSizeHeight(sizes[0], contentHeight) - maxHeight = getSizeHeight(sizes[1], contentHeight) - } - - 3 -> { - // Enables half expanded - isFitToContents = false - - peekHeight = getSizeHeight(sizes[0], contentHeight) - halfExpandedRatio = getSizeHeight(sizes[1], contentHeight).toFloat() / maxScreenHeight.toFloat() - maxHeight = getSizeHeight(sizes[2], contentHeight) - } - } - } - } - - /** - * Get the SizeInfo data by state. - */ - fun getSizeInfoForState(state: Int): SizeInfo? = - when (sizes.size) { - 1 -> { - when (state) { - STATE_EXPANDED -> SizeInfo(0, Utils.toDIP(maxHeight)) - else -> null - } - } - - 2 -> { - when (state) { - STATE_COLLAPSED -> SizeInfo(0, Utils.toDIP(peekHeight)) - STATE_EXPANDED -> SizeInfo(1, Utils.toDIP(maxHeight)) - else -> null - } - } - - 3 -> { - when (state) { - STATE_COLLAPSED -> SizeInfo(0, Utils.toDIP(peekHeight)) - - STATE_HALF_EXPANDED -> { - val height = halfExpandedRatio * maxScreenHeight - SizeInfo(1, Utils.toDIP(height.toInt())) - } - - STATE_EXPANDED -> SizeInfo(2, Utils.toDIP(maxHeight)) - - else -> null - } - } - - else -> null - } - - /** - * Get SizeInfo data for given size index. - */ - fun getSizeInfoForIndex(index: Int) = getSizeInfoForState(getStateForSizeIndex(index)) ?: SizeInfo(0, 0f) - - /** - * Set the state based on the given size index. - */ - fun setStateForSizeIndex(index: Int) { - state = getStateForSizeIndex(index) - } - - companion object { - const val TAG = "TrueSheetView" - } -} diff --git a/android/src/main/java/com/lodev09/truesheet/TrueSheetDialog.kt b/android/src/main/java/com/lodev09/truesheet/TrueSheetDialog.kt index 74e2c59..9b3b76c 100644 --- a/android/src/main/java/com/lodev09/truesheet/TrueSheetDialog.kt +++ b/android/src/main/java/com/lodev09/truesheet/TrueSheetDialog.kt @@ -3,38 +3,34 @@ package com.lodev09.truesheet import android.graphics.Color import android.view.ViewGroup import android.view.WindowManager -import android.widget.LinearLayout -import androidx.coordinatorlayout.widget.CoordinatorLayout import com.facebook.react.uimanager.ThemedReactContext +import com.google.android.material.bottomsheet.BottomSheetBehavior import com.google.android.material.bottomsheet.BottomSheetDialog import com.lodev09.truesheet.core.KeyboardManager -import com.lodev09.truesheet.core.RootViewGroup +import com.lodev09.truesheet.core.RootSheetView import com.lodev09.truesheet.core.Utils -class TrueSheetDialog( - private val reactContext: ThemedReactContext, - private val behavior: TrueSheetBehavior, - private val rootViewGroup: RootViewGroup -) : BottomSheetDialog(reactContext) { +data class SizeInfo(val index: Int, val value: Float) + +class TrueSheetDialog(private val reactContext: ThemedReactContext, private val rootSheetView: RootSheetView) : + BottomSheetDialog(reactContext) { private var keyboardManager = KeyboardManager(reactContext) - var sheetView: ViewGroup + var maxScreenHeight: Int = 0 + var maxSheetHeight: Int? = null - init { - LinearLayout(reactContext).apply { - addView(rootViewGroup) - setContentView(this) + var contentView: ViewGroup? = null + var footerView: ViewGroup? = null - sheetView = parent as ViewGroup + var sizes: Array = arrayOf("medium", "large") - // Set to transparent background to support corner radius - sheetView.setBackgroundColor(Color.TRANSPARENT) + var sheetView: ViewGroup - // Assign our main BottomSheetBehavior - val sheetViewParams = sheetView.layoutParams as CoordinatorLayout.LayoutParams - sheetViewParams.behavior = behavior - } + init { + setContentView(rootSheetView) + sheetView = rootSheetView.parent as ViewGroup + sheetView.setBackgroundColor(Color.TRANSPARENT) // Setup window params to adjust layout based on Keyboard state. window?.apply { @@ -47,15 +43,95 @@ class TrueSheetDialog( fun show(sizeIndex: Int) { if (isShowing) { - behavior.setStateForSizeIndex(sizeIndex) + setStateForSizeIndex(sizeIndex) } else { - behavior.configure() - behavior.setStateForSizeIndex(sizeIndex) + configure() + setStateForSizeIndex(sizeIndex) this.show() } } + /** + * Set the state based on the given size index. + */ + private fun setStateForSizeIndex(index: Int) { + behavior.state = getStateForSizeIndex(index) + } + + /** + * Get the height value based on the size config value. + */ + private fun getSizeHeight(size: Any, contentHeight: Int): Int { + val height = + when (size) { + is Double -> Utils.toPixel(size) + + is Int -> Utils.toPixel(size.toDouble()) + + is String -> { + when (size) { + "auto" -> contentHeight + + "large" -> maxScreenHeight + + "medium" -> (maxScreenHeight * 0.50).toInt() + + "small" -> (maxScreenHeight * 0.25).toInt() + + else -> { + if (size.endsWith('%')) { + val percent = size.trim('%').toDoubleOrNull() + if (percent == null) { + 0 + } else { + ((percent / 100) * maxScreenHeight).toInt() + } + } else { + val fixedHeight = size.toDoubleOrNull() + if (fixedHeight == null) { + 0 + } else { + Utils.toPixel(fixedHeight) + } + } + } + } + } + + else -> (maxScreenHeight * 0.5).toInt() + } + + return minOf(height, maxSheetHeight ?: maxScreenHeight) + } + + /** + * Determines the state based on the given size index. + */ + private fun getStateForSizeIndex(index: Int) = + when (sizes.size) { + 1 -> BottomSheetBehavior.STATE_EXPANDED + + 2 -> { + when (index) { + 0 -> BottomSheetBehavior.STATE_COLLAPSED + 1 -> BottomSheetBehavior.STATE_EXPANDED + else -> BottomSheetBehavior.STATE_HIDDEN + } + } + + 3 -> { + when (index) { + 0 -> BottomSheetBehavior.STATE_COLLAPSED + 1 -> BottomSheetBehavior.STATE_HALF_EXPANDED + 2 -> BottomSheetBehavior.STATE_EXPANDED + else -> BottomSheetBehavior.STATE_HIDDEN + } + } + + else -> BottomSheetBehavior.STATE_HIDDEN + } + /** * Handle keyboard state changes and adjust maxScreenHeight (sheet max height) accordingly. * Also update footer's Y position. @@ -63,13 +139,13 @@ class TrueSheetDialog( fun registerKeyboardManager() { keyboardManager.registerKeyboardListener(object : KeyboardManager.OnKeyboardListener { override fun onKeyboardStateChange(isVisible: Boolean, visibleHeight: Int?) { - when (isVisible) { - true -> behavior.maxScreenHeight = visibleHeight ?: 0 - else -> behavior.maxScreenHeight = Utils.screenHeight(reactContext) + maxScreenHeight = when (isVisible) { + true -> visibleHeight ?: 0 + else -> Utils.screenHeight(reactContext) } - behavior.footerView?.apply { - y = (behavior.maxScreenHeight - (sheetView.top ?: 0) - height).toFloat() + footerView?.apply { + y = (maxScreenHeight - (sheetView.top ?: 0) - height).toFloat() } } }) @@ -82,6 +158,93 @@ class TrueSheetDialog( keyboardManager.unregisterKeyboardListener() } + /** + * Configure the sheet based on size preferences. + */ + fun configure() { + // Update the usable sheet height + maxScreenHeight = Utils.screenHeight(reactContext) + + var contentHeight = 0 + + contentView?.let { contentHeight = it.height } + footerView?.let { contentHeight += it.height } + + // Configure sheet sizes + behavior.apply { + skipCollapsed = false + isFitToContents = true + + // m3 max width 640dp + maxWidth = Utils.toPixel(640.0) + + when (sizes.size) { + 1 -> { + maxHeight = getSizeHeight(sizes[0], contentHeight) + peekHeight = maxHeight + skipCollapsed = true + } + + 2 -> { + peekHeight = getSizeHeight(sizes[0], contentHeight) + maxHeight = getSizeHeight(sizes[1], contentHeight) + } + + 3 -> { + // Enables half expanded + isFitToContents = false + + peekHeight = getSizeHeight(sizes[0], contentHeight) + halfExpandedRatio = getSizeHeight(sizes[1], contentHeight).toFloat() / maxScreenHeight.toFloat() + maxHeight = getSizeHeight(sizes[2], contentHeight) + } + } + } + } + + /** + * Get the SizeInfo data by state. + */ + fun getSizeInfoForState(state: Int): SizeInfo? = + when (sizes.size) { + 1 -> { + when (state) { + BottomSheetBehavior.STATE_EXPANDED -> SizeInfo(0, Utils.toDIP(behavior.maxHeight)) + else -> null + } + } + + 2 -> { + when (state) { + BottomSheetBehavior.STATE_COLLAPSED -> SizeInfo(0, Utils.toDIP(behavior.peekHeight)) + BottomSheetBehavior.STATE_EXPANDED -> SizeInfo(1, Utils.toDIP(behavior.maxHeight)) + else -> null + } + } + + 3 -> { + when (state) { + BottomSheetBehavior.STATE_COLLAPSED -> SizeInfo(0, Utils.toDIP(behavior.peekHeight)) + + BottomSheetBehavior.STATE_HALF_EXPANDED -> { + val height = behavior.halfExpandedRatio * maxScreenHeight + SizeInfo(1, Utils.toDIP(height.toInt())) + } + + BottomSheetBehavior.STATE_EXPANDED -> SizeInfo(2, Utils.toDIP(behavior.maxHeight)) + + else -> null + } + } + + else -> null + } + + /** + * Get SizeInfo data for given size index. + */ + fun getSizeInfoForIndex(index: Int) = getSizeInfoForState(getStateForSizeIndex(index)) ?: SizeInfo(0, 0f) + companion object { const val TAG = "TrueSheetView" } diff --git a/android/src/main/java/com/lodev09/truesheet/TrueSheetView.kt b/android/src/main/java/com/lodev09/truesheet/TrueSheetView.kt index ed3a270..99ae71e 100644 --- a/android/src/main/java/com/lodev09/truesheet/TrueSheetView.kt +++ b/android/src/main/java/com/lodev09/truesheet/TrueSheetView.kt @@ -1,6 +1,7 @@ package com.lodev09.truesheet import android.content.Context +import android.util.Log import android.view.View import android.view.ViewGroup import android.view.ViewStructure @@ -13,7 +14,7 @@ import com.facebook.react.uimanager.events.EventDispatcher import com.google.android.material.bottomsheet.BottomSheetBehavior import com.lodev09.truesheet.core.DismissEvent import com.lodev09.truesheet.core.PresentEvent -import com.lodev09.truesheet.core.RootViewGroup +import com.lodev09.truesheet.core.RootSheetView import com.lodev09.truesheet.core.SizeChangeEvent class TrueSheetView(context: Context) : @@ -47,15 +48,10 @@ class TrueSheetView(context: Context) : */ private val sheetDialog: TrueSheetDialog - /** - * The custom BottomSheetDialogBehavior instance. - */ - private val sheetBehavior: TrueSheetBehavior - /** * React root view placeholder. */ - private val sheetRootView: RootViewGroup + private val rootSheetView: RootSheetView /** * 1st child of the container view. @@ -71,11 +67,10 @@ class TrueSheetView(context: Context) : reactContext.addLifecycleEventListener(this) eventDispatcher = UIManagerHelper.getEventDispatcherForReactTag(reactContext, id) - sheetRootView = RootViewGroup(context) - sheetRootView.eventDispatcher = eventDispatcher + rootSheetView = RootSheetView(context) + rootSheetView.eventDispatcher = eventDispatcher - sheetBehavior = TrueSheetBehavior(reactContext) - sheetDialog = TrueSheetDialog(reactContext, sheetBehavior, sheetRootView) + sheetDialog = TrueSheetDialog(reactContext, rootSheetView) // Configure Sheet Dialog sheetDialog.apply { @@ -86,7 +81,7 @@ class TrueSheetView(context: Context) : // Initialize footer y footerView?.apply { UiThreadUtil.runOnUiThread { - y = (sheetBehavior.maxScreenHeight - sheetView.top - height).toFloat() + y = (sheetDialog.maxScreenHeight - sheetView.top - height).toFloat() } } @@ -96,11 +91,12 @@ class TrueSheetView(context: Context) : } // dispatch onPresent event - eventDispatcher?.dispatchEvent(PresentEvent(surfaceId, id, sheetBehavior.getSizeInfoForIndex(activeIndex))) + eventDispatcher?.dispatchEvent(PresentEvent(surfaceId, id, sheetDialog.getSizeInfoForIndex(activeIndex))) } // Setup listener when the dialog has been dismissed. setOnDismissListener { + Log.d(TAG, "dismissed") unregisterKeyboardManager() dismissPromise?.let { promise -> promise() @@ -113,8 +109,8 @@ class TrueSheetView(context: Context) : } // Configure sheet behavior events - sheetBehavior.apply { - addBottomSheetCallback( + sheetDialog.apply { + behavior.addBottomSheetCallback( object : BottomSheetBehavior.BottomSheetCallback() { override fun onSlide(sheetView: View, slideOffset: Float) { footerView?.let { @@ -128,24 +124,18 @@ class TrueSheetView(context: Context) : } override fun onStateChanged(view: View, newState: Int) { - when (newState) { - BottomSheetBehavior.STATE_HIDDEN -> sheetDialog.dismiss() - - else -> { - val sizeInfo = getSizeInfoForState(newState) - if (sizeInfo != null && sizeInfo.index != activeIndex) { - // Invoke promise when sheet resized programmatically - presentPromise?.let { promise -> - promise() - presentPromise = null - } - - activeIndex = sizeInfo.index - - // dispatch onSizeChange event - eventDispatcher?.dispatchEvent(SizeChangeEvent(surfaceId, id, sizeInfo)) - } + val sizeInfo = getSizeInfoForState(newState) + if (sizeInfo != null && sizeInfo.index != activeIndex) { + // Invoke promise when sheet resized programmatically + presentPromise?.let { promise -> + promise() + presentPromise = null } + + activeIndex = sizeInfo.index + + // dispatch onSizeChange event + eventDispatcher?.dispatchEvent(SizeChangeEvent(surfaceId, id, sizeInfo)) } } } @@ -154,7 +144,7 @@ class TrueSheetView(context: Context) : } override fun dispatchProvideStructure(structure: ViewStructure) { - sheetRootView.dispatchProvideStructure(structure) + rootSheetView.dispatchProvideStructure(structure) } override fun onLayout( @@ -181,29 +171,29 @@ class TrueSheetView(context: Context) : contentView = it.getChildAt(0) as ViewGroup footerView = it.getChildAt(1) as ViewGroup - sheetBehavior.contentView = contentView - sheetBehavior.footerView = footerView + sheetDialog.contentView = contentView + sheetDialog.footerView = footerView // rootView's first child is the Container View - sheetRootView.addView(it, index) + rootSheetView.addView(it, index) } } override fun getChildCount(): Int { // This method may be called by the parent constructor // before rootView is initialized. - return sheetRootView.childCount + return rootSheetView.childCount } - override fun getChildAt(index: Int): View = sheetRootView.getChildAt(index) + override fun getChildAt(index: Int): View = rootSheetView.getChildAt(index) override fun removeView(child: View) { - sheetRootView.removeView(child) + rootSheetView.removeView(child) } override fun removeViewAt(index: Int) { val child = getChildAt(index) - sheetRootView.removeView(child) + rootSheetView.removeView(child) } override fun addChildrenForAccessibility(outChildren: ArrayList) { @@ -232,18 +222,18 @@ class TrueSheetView(context: Context) : } fun setMaxHeight(height: Int) { - sheetBehavior.maxSheetHeight = height - sheetBehavior.configure() + sheetDialog.maxSheetHeight = height + sheetDialog.configure() } fun setDismissible(dismissible: Boolean) { - sheetBehavior.isHideable = dismissible + sheetDialog.behavior.isHideable = dismissible sheetDialog.setCancelable(dismissible) } fun setSizes(newSizes: Array) { - sheetBehavior.sizes = newSizes - sheetBehavior.configure() + sheetDialog.sizes = newSizes + sheetDialog.configure() } /** diff --git a/android/src/main/java/com/lodev09/truesheet/core/RootViewGroup.kt b/android/src/main/java/com/lodev09/truesheet/core/RootSheetView.kt similarity index 94% rename from android/src/main/java/com/lodev09/truesheet/core/RootViewGroup.kt rename to android/src/main/java/com/lodev09/truesheet/core/RootSheetView.kt index d9e21db..1bda573 100644 --- a/android/src/main/java/com/lodev09/truesheet/core/RootViewGroup.kt +++ b/android/src/main/java/com/lodev09/truesheet/core/RootSheetView.kt @@ -15,8 +15,8 @@ import com.facebook.react.uimanager.events.EventDispatcher import com.facebook.react.views.view.ReactViewGroup /** - * RootViewGroup is the ViewGroup which contains all the children of a Modal. It gets all - * child information forwarded from ReactModalHostView and uses that to create children. It is + * RootSheetView is the ViewGroup which contains all the children of a Modal. It gets all + * child information forwarded from TrueSheetView and uses that to create children. It is * also responsible for acting as a RootView and handling touch events. It does this the same way * as ReactRootView. * @@ -26,7 +26,7 @@ import com.facebook.react.views.view.ReactViewGroup * styleHeight on the LayoutShadowNode to be the window size. This is done through the * UIManagerModule, and will then cause the children to layout as if they can fill the window. */ -class RootViewGroup(context: Context?) : +class RootSheetView(context: Context?) : ReactViewGroup(context), RootView { private var hasAdjustedSize = false @@ -34,7 +34,6 @@ class RootViewGroup(context: Context?) : private var viewHeight = 0 private val mJSTouchDispatcher = JSTouchDispatcher(this) - private var mJSPointerDispatcher: JSPointerDispatcher? = null var eventDispatcher: EventDispatcher? = null @@ -134,8 +133,4 @@ class RootViewGroup(context: Context?) : // No-op - override in order to still receive events to onInterceptTouchEvent // even when some other view disallow that } - - companion object { - const val TAG = "TrueSheetView" - } } diff --git a/example/package.json b/example/package.json index 2b2828c..97d2acf 100644 --- a/example/package.json +++ b/example/package.json @@ -14,7 +14,7 @@ }, "dependencies": { "@react-native/virtualized-lists": "0.75.0-main", - "expo": "~50.0.15", + "expo": "~50.0.17", "react": "18.2.0", "react-native": "0.73.6", "react-native-gesture-handler": "~2.14.0", diff --git a/example/src/sheets/FlatListSheet.tsx b/example/src/sheets/FlatListSheet.tsx index 498c395..4f91bcd 100644 --- a/example/src/sheets/FlatListSheet.tsx +++ b/example/src/sheets/FlatListSheet.tsx @@ -24,6 +24,7 @@ export const FlatListSheet = forwardRef((props: FlatListSheetProps, ref: Ref ref={flatListRef} + nestedScrollEnabled data={times(50, (i) => i)} contentContainerStyle={$content} indicatorStyle="black" diff --git a/example/src/sheets/PromptSheet.tsx b/example/src/sheets/PromptSheet.tsx index cc81b1f..8441fa1 100644 --- a/example/src/sheets/PromptSheet.tsx +++ b/example/src/sheets/PromptSheet.tsx @@ -31,6 +31,7 @@ export const PromptSheet = forwardRef((props: PromptSheetProps, ref: Ref} {...props} > - + {times(25, (i) => ( ))} diff --git a/yarn.lock b/yarn.lock index 9ddca16..2ba04f2 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2112,14 +2112,14 @@ __metadata: languageName: node linkType: hard -"@expo/cli@npm:0.17.8": - version: 0.17.8 - resolution: "@expo/cli@npm:0.17.8" +"@expo/cli@npm:0.17.10": + version: 0.17.10 + resolution: "@expo/cli@npm:0.17.10" dependencies: "@babel/runtime": "npm:^7.20.0" "@expo/code-signing-certificates": "npm:0.0.5" "@expo/config": "npm:~8.5.0" - "@expo/config-plugins": "npm:~7.8.0" + "@expo/config-plugins": "npm:~7.9.0" "@expo/devcert": "npm:^1.0.0" "@expo/env": "npm:~0.2.2" "@expo/image-utils": "npm:^0.4.0" @@ -2128,7 +2128,7 @@ __metadata: "@expo/osascript": "npm:^2.0.31" "@expo/package-manager": "npm:^1.1.1" "@expo/plist": "npm:^0.1.0" - "@expo/prebuild-config": "npm:6.7.4" + "@expo/prebuild-config": "npm:6.8.1" "@expo/rudder-sdk-node": "npm:1.1.1" "@expo/spawn-async": "npm:1.5.0" "@expo/xcpretty": "npm:^4.3.0" @@ -2194,7 +2194,7 @@ __metadata: ws: "npm:^8.12.1" bin: expo-internal: build/bin/cli - checksum: 10c0/2f5acb9c7ee31e51c278deba81f0ec99d7fb3d82cda454da3ee60f2eca9725da2562f757e83f2c5eb39620dfbdf88b2fdcefd78b26a38a46591a90dd77fe9da1 + checksum: 10c0/672173599031346dfd107c7ee66c5ca82a737978fb450ae00e7920f8f56fd0ceee0e9c9c7fefd59fe60a5bff30702ab190539b1418429ba569a3e6e35bd30dc3 languageName: node linkType: hard @@ -2208,7 +2208,32 @@ __metadata: languageName: node linkType: hard -"@expo/config-plugins@npm:7.8.4, @expo/config-plugins@npm:~7.8.0, @expo/config-plugins@npm:~7.8.2": +"@expo/config-plugins@npm:7.9.1, @expo/config-plugins@npm:~7.9.0": + version: 7.9.1 + resolution: "@expo/config-plugins@npm:7.9.1" + dependencies: + "@expo/config-types": "npm:^50.0.0-alpha.1" + "@expo/fingerprint": "npm:^0.6.0" + "@expo/json-file": "npm:~8.3.0" + "@expo/plist": "npm:^0.1.0" + "@expo/sdk-runtime-versions": "npm:^1.0.0" + "@react-native/normalize-color": "npm:^2.0.0" + chalk: "npm:^4.1.2" + debug: "npm:^4.3.1" + find-up: "npm:~5.0.0" + getenv: "npm:^1.0.0" + glob: "npm:7.1.6" + resolve-from: "npm:^5.0.0" + semver: "npm:^7.5.3" + slash: "npm:^3.0.0" + slugify: "npm:^1.6.6" + xcode: "npm:^3.0.1" + xml2js: "npm:0.6.0" + checksum: 10c0/790db5fe8c932c43e455fb661b98381310dfdeb5dbd460d0fb662f458351ab2d43dc9af0fa5f2e8a1e55ccf5bf3d8e4f2824896ac8223d675c9c8c73d7064aa7 + languageName: node + linkType: hard + +"@expo/config-plugins@npm:~7.8.2": version: 7.8.4 resolution: "@expo/config-plugins@npm:7.8.4" dependencies: @@ -2240,7 +2265,26 @@ __metadata: languageName: node linkType: hard -"@expo/config@npm:8.5.4, @expo/config@npm:~8.5.0": +"@expo/config@npm:8.5.6": + version: 8.5.6 + resolution: "@expo/config@npm:8.5.6" + dependencies: + "@babel/code-frame": "npm:~7.10.4" + "@expo/config-plugins": "npm:~7.9.0" + "@expo/config-types": "npm:^50.0.0" + "@expo/json-file": "npm:^8.2.37" + getenv: "npm:^1.0.0" + glob: "npm:7.1.6" + require-from-string: "npm:^2.0.2" + resolve-from: "npm:^5.0.0" + semver: "npm:7.5.3" + slugify: "npm:^1.3.4" + sucrase: "npm:3.34.0" + checksum: 10c0/425a645b68294cd2345e85183cb4cfef29f3488b79879ce066669236347fe6cb7f2816cfe1311c919c2f9b64ebf2633a2ab4069804b2ceb0f6446bfb298fac97 + languageName: node + linkType: hard + +"@expo/config@npm:~8.5.0": version: 8.5.4 resolution: "@expo/config@npm:8.5.4" dependencies: @@ -2339,7 +2383,37 @@ __metadata: languageName: node linkType: hard -"@expo/metro-config@npm:0.17.6, @expo/metro-config@npm:~0.17.0": +"@expo/metro-config@npm:0.17.7": + version: 0.17.7 + resolution: "@expo/metro-config@npm:0.17.7" + dependencies: + "@babel/core": "npm:^7.20.0" + "@babel/generator": "npm:^7.20.5" + "@babel/parser": "npm:^7.20.0" + "@babel/types": "npm:^7.20.0" + "@expo/config": "npm:~8.5.0" + "@expo/env": "npm:~0.2.2" + "@expo/json-file": "npm:~8.3.0" + "@expo/spawn-async": "npm:^1.7.2" + babel-preset-fbjs: "npm:^3.4.0" + chalk: "npm:^4.1.0" + debug: "npm:^4.3.2" + find-yarn-workspace-root: "npm:~2.0.0" + fs-extra: "npm:^9.1.0" + getenv: "npm:^1.0.0" + glob: "npm:^7.2.3" + jsc-safe-url: "npm:^0.2.4" + lightningcss: "npm:~1.19.0" + postcss: "npm:~8.4.32" + resolve-from: "npm:^5.0.0" + sucrase: "npm:3.34.0" + peerDependencies: + "@react-native/babel-preset": "*" + checksum: 10c0/d5be7bb48ade684a09fffeabdb15d063d77ec97456ad93ae198de03e70a3e3882b7af2e6bd2d7e4ad3dce2fa20a4e152f78a7ab5f671a0766d972335b2f806dd + languageName: node + linkType: hard + +"@expo/metro-config@npm:~0.17.0": version: 0.17.6 resolution: "@expo/metro-config@npm:0.17.6" dependencies: @@ -2410,12 +2484,12 @@ __metadata: languageName: node linkType: hard -"@expo/prebuild-config@npm:6.7.4": - version: 6.7.4 - resolution: "@expo/prebuild-config@npm:6.7.4" +"@expo/prebuild-config@npm:6.8.1": + version: 6.8.1 + resolution: "@expo/prebuild-config@npm:6.8.1" dependencies: "@expo/config": "npm:~8.5.0" - "@expo/config-plugins": "npm:~7.8.0" + "@expo/config-plugins": "npm:~7.9.0" "@expo/config-types": "npm:^50.0.0-alpha.1" "@expo/image-utils": "npm:^0.4.0" "@expo/json-file": "npm:^8.2.37" @@ -2426,7 +2500,7 @@ __metadata: xml2js: "npm:0.6.0" peerDependencies: expo-modules-autolinking: ">=0.8.1" - checksum: 10c0/1bae37cfafe83ac821b0157c14347f7b3f3741d3b11e4b86b861e410c9af57a5d9e53507acf8cf2e3d7e6518b9e6111e759a7ef10006e09d38d8815cdad02cf3 + checksum: 10c0/b52c8bca39bbf5754d3ac6022534e54ec70ccd3be0b03b3ef9b4a7d8bf475669c0ea94ab3e061bc45b099ef47927efcc4637937b2fa77b9fc46e37eb23332a13 languageName: node linkType: hard @@ -4873,9 +4947,9 @@ __metadata: languageName: node linkType: hard -"babel-preset-expo@npm:~10.0.1": - version: 10.0.1 - resolution: "babel-preset-expo@npm:10.0.1" +"babel-preset-expo@npm:~10.0.2": + version: 10.0.2 + resolution: "babel-preset-expo@npm:10.0.2" dependencies: "@babel/plugin-proposal-decorators": "npm:^7.12.9" "@babel/plugin-transform-export-namespace-from": "npm:^7.22.11" @@ -4886,7 +4960,7 @@ __metadata: "@react-native/babel-preset": "npm:^0.73.18" babel-plugin-react-native-web: "npm:~0.18.10" react-refresh: "npm:0.14.0" - checksum: 10c0/03be00e70cdba22540352d260ec80683a9ca75cea304cc693bbc961645ec3af2d5a4a4b2f5dd5f525523e407eb044481cb56b02bb276a1c504c4d78ffe8f0359 + checksum: 10c0/398dae1ea9317ee00e6ecfc47052bd0305e59ea97acc3b32b764c903820afc6650de926ad12dfd9af57a2aad23d951bfa95f109c66741d33c237ce3e1eb3102b languageName: node linkType: hard @@ -7405,7 +7479,7 @@ __metadata: languageName: node linkType: hard -"expo-file-system@npm:~16.0.0, expo-file-system@npm:~16.0.8": +"expo-file-system@npm:~16.0.0": version: 16.0.8 resolution: "expo-file-system@npm:16.0.8" peerDependencies: @@ -7414,6 +7488,15 @@ __metadata: languageName: node linkType: hard +"expo-file-system@npm:~16.0.9": + version: 16.0.9 + resolution: "expo-file-system@npm:16.0.9" + peerDependencies: + expo: "*" + checksum: 10c0/e43c5ab226ac607b6d01389078012f96e1a0bf44474c20f71dfedd0d6052781837c602bb57b4f534d2dd3e87bdaa754fd73daa8f4f8a78e08ba67e17bba084e5 + languageName: node + linkType: hard + "expo-font@npm:~11.10.3": version: 11.10.3 resolution: "expo-font@npm:11.10.3" @@ -7459,19 +7542,19 @@ __metadata: languageName: node linkType: hard -"expo@npm:~50.0.15": - version: 50.0.15 - resolution: "expo@npm:50.0.15" +"expo@npm:~50.0.17": + version: 50.0.17 + resolution: "expo@npm:50.0.17" dependencies: "@babel/runtime": "npm:^7.20.0" - "@expo/cli": "npm:0.17.8" - "@expo/config": "npm:8.5.4" - "@expo/config-plugins": "npm:7.8.4" - "@expo/metro-config": "npm:0.17.6" + "@expo/cli": "npm:0.17.10" + "@expo/config": "npm:8.5.6" + "@expo/config-plugins": "npm:7.9.1" + "@expo/metro-config": "npm:0.17.7" "@expo/vector-icons": "npm:^14.0.0" - babel-preset-expo: "npm:~10.0.1" + babel-preset-expo: "npm:~10.0.2" expo-asset: "npm:~9.0.2" - expo-file-system: "npm:~16.0.8" + expo-file-system: "npm:~16.0.9" expo-font: "npm:~11.10.3" expo-keep-awake: "npm:~12.8.2" expo-modules-autolinking: "npm:1.10.3" @@ -7480,7 +7563,7 @@ __metadata: whatwg-url-without-unicode: "npm:8.0.0-3" bin: expo: bin/cli - checksum: 10c0/9c24ab0512c1c287c377677f10bec2ecf2b23283706bb7418a2493f529d0f4dc1b2900944b9c2d746180ca0195e1df067dedc4c3a6845a3100206a5e9347d5ec + checksum: 10c0/9348f5526a50a1a4f5f15884517dac8919b88c31facbed70e9bb019dc779d4897833c4f897a385dd73a70dc05032b37cfbde7265979c25bbfb6f3758c6ddd7a3 languageName: node linkType: hard @@ -14528,7 +14611,7 @@ __metadata: "@react-native/metro-config": "npm:0.73.5" "@react-native/virtualized-lists": "npm:0.75.0-main" babel-plugin-module-resolver: "npm:^5.0.0" - expo: "npm:~50.0.15" + expo: "npm:~50.0.17" react: "npm:18.2.0" react-native: "npm:0.73.6" react-native-gesture-handler: "npm:~2.14.0"