From 2b1cbda47ee5252cf8e5958dfa3131b393a21fe4 Mon Sep 17 00:00:00 2001 From: Stanley Ugwu Date: Fri, 1 Dec 2023 10:27:24 +0100 Subject: [PATCH 1/7] =?UTF-8?q?=F0=9F=90=9E=20fix:=20fix=20typescript=20im?= =?UTF-8?q?port=20intellisense=20bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Import Intellisense for `` uses deep component path `@devvie/bottom-sheet/lib/typescript/components/bottomSheet` instead of `@devvie/bottom-sheet` --- src/index.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/index.ts b/src/index.ts index f119885..5aef4fb 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,9 +1,9 @@ +import BottomSheet from './components/bottomSheet'; export { default as AnimatedTouchableBackdropMask } from './components/animatedTouchableBackdropMask'; -export { default } from './components/bottomSheet'; - export { ANIMATIONS, CUSTOM_BACKDROP_POSITIONS, type BottomSheetMethods, } from './types.d'; export type { BottomSheetProps } from './components/bottomSheet/types.d'; +export default BottomSheet; \ No newline at end of file From 523b325460c9316dc1df736955f13615809fe34d Mon Sep 17 00:00:00 2001 From: Stanley Ugwu Date: Fri, 8 Dec 2023 08:45:15 +0100 Subject: [PATCH 2/7] =?UTF-8?q?=F0=9F=90=9E=20fix(docs):=20retype=20`style?= =?UTF-8?q?`=20prop=20comment?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 3 +++ src/components/bottomSheet/index.tsx | 7 +------ src/components/bottomSheet/types.d.ts | 3 ++- 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/.gitignore b/.gitignore index baefc76..b9e3c3e 100644 --- a/.gitignore +++ b/.gitignore @@ -69,3 +69,6 @@ android/keystores/debug.keystore # generated by bob lib/ + +# user files +backlog.md diff --git a/src/components/bottomSheet/index.tsx b/src/components/bottomSheet/index.tsx index 0378081..a859198 100644 --- a/src/components/bottomSheet/index.tsx +++ b/src/components/bottomSheet/index.tsx @@ -436,12 +436,7 @@ const BottomSheet = forwardRef( ref={contentWrapperRef} key={'BottomSheetContentContainer'} onLayout={extractNativeTag} - /** - * Merge external style and transform property carefully and orderly with - * internal styles and animated transform properties - * to apply external styles and transform properties and avoid - * internal styles and transform properties override - */ + /* Merge external and internal styles carefully and orderly */ style={[ !modal ? materialStyles.contentContainerShadow : false, materialStyles.contentContainer, diff --git a/src/components/bottomSheet/types.d.ts b/src/components/bottomSheet/types.d.ts index a0ca3de..1f0803e 100644 --- a/src/components/bottomSheet/types.d.ts +++ b/src/components/bottomSheet/types.d.ts @@ -42,7 +42,8 @@ interface BottomSheetProps { /** * Extra styles to apply to bottom sheet (the `View` that wraps its children). * - * `Note:` style properties `height`, `maxHeight`, `minHeight` and translation along y-axis i.e `transform:[{translateY:...}]` will be ignored. + * `Note:` style properties `height`, `maxHeight`, `minHeight` will be ignored. + * If you want to set sheet's height, pass the `height` prop instead. * @type {Omit} */ style?: Omit; From a0cf509e460af1d52eeed117908125e0a686cef1 Mon Sep 17 00:00:00 2001 From: Stanley Ugwu Date: Fri, 8 Dec 2023 09:19:50 +0100 Subject: [PATCH 3/7] =?UTF-8?q?=F0=9F=90=9E=20fix(type):=20fix=20style=20a?= =?UTF-8?q?rray=20typescript=20issue?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit passing an array to `style` prop causes typescript to complain because the `style` prop wasn't typed correctly. This commit fixes that. --- src/components/bottomSheet/types.d.ts | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/components/bottomSheet/types.d.ts b/src/components/bottomSheet/types.d.ts index 1f0803e..3615425 100644 --- a/src/components/bottomSheet/types.d.ts +++ b/src/components/bottomSheet/types.d.ts @@ -1,4 +1,10 @@ -import { Animated, OpaqueColorValue, ViewProps, ViewStyle } from 'react-native'; +import { + Animated, + OpaqueColorValue, + ViewProps, + ViewStyle, + type StyleProp, +} from 'react-native'; import { ANIMATIONS, CUSTOM_BACKDROP_POSITIONS, @@ -46,7 +52,7 @@ interface BottomSheetProps { * If you want to set sheet's height, pass the `height` prop instead. * @type {Omit} */ - style?: Omit; + style?: StyleProp>; /** * Height of the bottom sheet's overall container, this will be the height of From 5cbfc0281918565f36a3a602a29c8e440f504444 Mon Sep 17 00:00:00 2001 From: Stanley Ugwu Date: Wed, 3 Jan 2024 22:35:27 +0100 Subject: [PATCH 4/7] =?UTF-8?q?=F0=9F=90=9E=20fix(android):=20fix=20back?= =?UTF-8?q?=20press=20handling=20issue=20for=20`android=5FcloseOnBackPress?= =?UTF-8?q?`=20prop?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When `android_closeOnBackPress` is true, all pre-registered back press event listeners in the app is prevented from being called and `closeSheet` function is constantly closed even when sheet is closed. When it's false, it doesn't prevent sheet from being closed by back press. Fixes #9 --- src/components/bottomSheet/index.tsx | 6 ++++- src/components/bottomSheet/types.d.ts | 8 ++++++- .../useHandleAndroidBackButtonClose/index.ts | 22 ++++++++++--------- .../types.d.ts | 4 +++- 4 files changed, 27 insertions(+), 13 deletions(-) diff --git a/src/components/bottomSheet/index.tsx b/src/components/bottomSheet/index.tsx index a859198..dc35a0b 100644 --- a/src/components/bottomSheet/index.tsx +++ b/src/components/bottomSheet/index.tsx @@ -386,7 +386,11 @@ const BottomSheet = forwardRef( /** * Handles hardware back button press for android */ - useHandleAndroidBackButtonClose(android_closeOnBackPress, closeBottomSheet); + useHandleAndroidBackButtonClose( + android_closeOnBackPress, + closeBottomSheet, + sheetOpen + ); // Children const ChildNodes = diff --git a/src/components/bottomSheet/types.d.ts b/src/components/bottomSheet/types.d.ts index 3615425..8467e8a 100644 --- a/src/components/bottomSheet/types.d.ts +++ b/src/components/bottomSheet/types.d.ts @@ -289,7 +289,13 @@ interface BottomSheetProps { customEasingFunction?: AnimationEasingFunction; /** - * Determines whether sheet will close when device back button is pressed. + * Determines whether sheet will close or not when device back button is pressed, on Android. + * + * __In a typical app screen (where back button takes user to the previous screen):__ \ + * _If `true` and sheet is open, the user has to press the back button twice to exit the screen. + * The first press closes the sheet and the second exits the screen.\ + * If `false` and sheet is open, the user has to close the sheet through another means like backdrop press + * and then press the back button after that to exit the screen_ * * `Note:` Only applies for Android * diff --git a/src/hooks/useHandleAndroidBackButtonClose/index.ts b/src/hooks/useHandleAndroidBackButtonClose/index.ts index 9fa5e20..6f4ac81 100644 --- a/src/hooks/useHandleAndroidBackButtonClose/index.ts +++ b/src/hooks/useHandleAndroidBackButtonClose/index.ts @@ -3,30 +3,32 @@ import { BackHandler, type NativeEventSubscription } from 'react-native'; import type { UseHandleAndroidBackButtonClose } from './types.d'; /** - * Handles closing sheet for android hardware back button press event + * Handles closing sheet when back button is pressed on + * android and sheet is opened * * @param {boolean} shouldClose Whether to close sheet when back button is pressed * @param {boolean} closeSheet Function to call to close the sheet + * @param {boolean} sheetOpen Determines the visibility of the sheet */ const useHandleAndroidBackButtonClose: UseHandleAndroidBackButtonClose = ( shouldClose = true, - closeSheet + closeSheet, + sheetOpen = false ) => { const handler = useRef(); useEffect(() => { - if (shouldClose) { - handler.current = BackHandler.addEventListener( - 'hardwareBackPress', - () => { + handler.current = BackHandler.addEventListener('hardwareBackPress', () => { + if (sheetOpen) { + if (shouldClose) { closeSheet?.(); - return true; } - ); - } + return true; // prevent back press event bubbling as long as sheet is open + } else return false; // when sheet is closed allow bubbling + }); return () => { handler.current?.remove?.(); }; - }, [shouldClose, closeSheet]); + }, [shouldClose, closeSheet, sheetOpen]); }; export default useHandleAndroidBackButtonClose; diff --git a/src/hooks/useHandleAndroidBackButtonClose/types.d.ts b/src/hooks/useHandleAndroidBackButtonClose/types.d.ts index bd51051..ac15549 100644 --- a/src/hooks/useHandleAndroidBackButtonClose/types.d.ts +++ b/src/hooks/useHandleAndroidBackButtonClose/types.d.ts @@ -7,5 +7,7 @@ export type UseHandleAndroidBackButtonClose = ( /** Whether to close sheet when back button is pressed*/ shouldClose: boolean, /** Function to call to close the sheet */ - closeSheet: () => void + closeSheet: () => void, + /** Determines the sheet's visibility state */ + sheetOpen: boolean ) => HookReturn; From 18a7642255e43ed67481fd4671c3acdd0f60b861 Mon Sep 17 00:00:00 2001 From: Stanley Ugwu Date: Fri, 5 Jan 2024 01:10:48 +0100 Subject: [PATCH 5/7] =?UTF-8?q?=F0=9F=90=9E=20fix:=20make=20padding=20styl?= =?UTF-8?q?es=20applied=20via=20`style`=20prop=20not=20affect=20drag=20han?= =?UTF-8?q?dle=20component?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit setting padding properties (`padding`, `paddingLeft`, `paddingVetical`, etc) in the `style` prop causes the drag handle to move position in response to the paddings. This commit fixes that and also fixes a critical issue where padding styles also caused the sheet to have extruded height making it visible even when closed --- src/components/bottomSheet/index.tsx | 22 +++++++++++-- src/components/bottomSheet/types.d.ts | 17 +++++----- src/utils/separatePaddingStyles.ts | 46 +++++++++++++++++++++++++++ 3 files changed, 74 insertions(+), 11 deletions(-) create mode 100644 src/utils/separatePaddingStyles.ts diff --git a/src/components/bottomSheet/index.tsx b/src/components/bottomSheet/index.tsx index dc35a0b..75eaca9 100644 --- a/src/components/bottomSheet/index.tsx +++ b/src/components/bottomSheet/index.tsx @@ -40,6 +40,7 @@ import { type BOTTOMSHEET, } from './types.d'; import useHandleAndroidBackButtonClose from '../../hooks/useHandleAndroidBackButtonClose'; +import separatePaddingStyles from '../../utils/separatePaddingStyles'; /** * Main bottom sheet component @@ -104,6 +105,16 @@ const BottomSheet = forwardRef( /** cached _nativeTag property of content container */ const cachedContentWrapperNativeTag = useRef(undefined); + // here we separate all padding that may be applied via contentContainerStyle prop, + // these paddings will be applied to the `View` diretly wrapping `ChildNodes` in content container. + // All these is so that paddings applied to sheet doesn't affect the drag handle + // TODO: find better way to memoize `separatePaddingStyles` function return value to avoid + // redundant re-runs + const sepStyles = useMemo( + () => separatePaddingStyles(contentContainerStyle), + [contentContainerStyle] + ); + // Animation utility const Animators = useMemo( () => ({ @@ -444,7 +455,8 @@ const BottomSheet = forwardRef( style={[ !modal ? materialStyles.contentContainerShadow : false, materialStyles.contentContainer, - contentContainerStyle, + // we apply styles other than padding here + sepStyles?.otherStyles, { height: _animatedHeight, minHeight: _animatedHeight, @@ -454,7 +466,13 @@ const BottomSheet = forwardRef( {...panHandlersFor('contentwrapper')} > - {ChildNodes} + + + {ChildNodes} + diff --git a/src/components/bottomSheet/types.d.ts b/src/components/bottomSheet/types.d.ts index 8467e8a..98e7a68 100644 --- a/src/components/bottomSheet/types.d.ts +++ b/src/components/bottomSheet/types.d.ts @@ -1,10 +1,4 @@ -import { - Animated, - OpaqueColorValue, - ViewProps, - ViewStyle, - type StyleProp, -} from 'react-native'; +import { Animated, OpaqueColorValue, ViewProps, ViewStyle } from 'react-native'; import { ANIMATIONS, CUSTOM_BACKDROP_POSITIONS, @@ -12,6 +6,11 @@ import { } from '../../types.d'; import React from 'react'; +export type SheetStyleProp = Omit< + ViewStyle, + 'height' | 'minHeight' | 'maxHeight' +>; + // short hand for toValue key of Animator methods type ToValue = Animated.TimingAnimationConfig['toValue']; @@ -50,9 +49,9 @@ interface BottomSheetProps { * * `Note:` style properties `height`, `maxHeight`, `minHeight` will be ignored. * If you want to set sheet's height, pass the `height` prop instead. - * @type {Omit} + * @type {SheetStyleProp} */ - style?: StyleProp>; + style?: SheetStyleProp; /** * Height of the bottom sheet's overall container, this will be the height of diff --git a/src/utils/separatePaddingStyles.ts b/src/utils/separatePaddingStyles.ts new file mode 100644 index 0000000..0dfcead --- /dev/null +++ b/src/utils/separatePaddingStyles.ts @@ -0,0 +1,46 @@ +import { type ViewStyle } from 'react-native'; +import type { SheetStyleProp } from '../components/bottomSheet/types'; + +type PadProps = + | 'padding' + | 'paddingBottom' + | 'paddingEnd' + | 'paddingHorizontal' + | 'paddingLeft' + | 'paddingRight' + | 'paddingStart' + | 'paddingTop' + | 'paddingVertical'; + +type Styles = { + paddingStyles: Pick; + otherStyles: Omit; +}; + +/** + * Extracts and separates `padding` styles from + * other styles from the given `style` + */ +const separatePaddingStyles = ( + style: SheetStyleProp | undefined +): Styles | undefined => { + if (!style) return; + const styleKeys = Object.keys(style || {}); + if (!styleKeys.length) return; + + const styles: Styles = { + paddingStyles: {}, + otherStyles: {}, + }; + + for (const key of styleKeys) { + // @ts-expect-error + styles[key.startsWith('padding') ? 'paddingStyles' : 'otherStyles'][key] = + // @ts-expect-error + style[key]; + } + + return styles; +}; + +export default separatePaddingStyles; From 5292ae74053769a0bc8ee804c6aa89739e9728bd Mon Sep 17 00:00:00 2001 From: Stanley Ugwu Date: Fri, 5 Jan 2024 02:03:55 +0100 Subject: [PATCH 6/7] =?UTF-8?q?=F0=9F=90=9E=20fix(type):=20fix=20typescrip?= =?UTF-8?q?t=20and=20eslint=20issues?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/index.ts | 2 +- src/utils/separatePaddingStyles.ts | 5 ++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/index.ts b/src/index.ts index 5aef4fb..3a98363 100644 --- a/src/index.ts +++ b/src/index.ts @@ -6,4 +6,4 @@ export { type BottomSheetMethods, } from './types.d'; export type { BottomSheetProps } from './components/bottomSheet/types.d'; -export default BottomSheet; \ No newline at end of file +export default BottomSheet; diff --git a/src/utils/separatePaddingStyles.ts b/src/utils/separatePaddingStyles.ts index 0dfcead..3a86ab7 100644 --- a/src/utils/separatePaddingStyles.ts +++ b/src/utils/separatePaddingStyles.ts @@ -11,7 +11,6 @@ type PadProps = | 'paddingStart' | 'paddingTop' | 'paddingVertical'; - type Styles = { paddingStyles: Pick; otherStyles: Omit; @@ -34,9 +33,9 @@ const separatePaddingStyles = ( }; for (const key of styleKeys) { - // @ts-expect-error + // @ts-ignore styles[key.startsWith('padding') ? 'paddingStyles' : 'otherStyles'][key] = - // @ts-expect-error + // @ts-ignore style[key]; } From f39db982cd2b5fee0fac9b3d89b3d2b677a28b07 Mon Sep 17 00:00:00 2001 From: Stanley Ugwu Date: Tue, 9 Jan 2024 17:44:00 +0100 Subject: [PATCH 7/7] =?UTF-8?q?=F0=9F=93=9D=20docs:=20correct=20example=20?= =?UTF-8?q?code=20snippet=20mistake=20for=20typescript=20and=20javascript.?= =?UTF-8?q?=20Fixes=20#11?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 124 ++++++++++++++++++++++++++++++------------------------ 1 file changed, 68 insertions(+), 56 deletions(-) diff --git a/README.md b/README.md index 4e5de7a..c9ac742 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,5 @@ # React Native Bottom Sheet 💖 + ![GitHub](https://img.shields.io/github/license/stanleyugwu/react-native-bottom-sheet?style=plastic&label=License&color=%23fea9f8) ![GitHub Workflow Status (with event)](https://img.shields.io/github/actions/workflow/status/stanleyugwu/react-native-bottom-sheet/ci.yml?color=%23fea9f8&label=Build) [![runs with expo](https://img.shields.io/badge/Expo-Support-fea9f8.svg?style=platic&logo=EXPO&logoColor=fff)](https://expo.io/) @@ -6,11 +7,12 @@ ![npm bundle size (scoped)](https://img.shields.io/bundlephobia/minzip/@devvie/bottom-sheet?style=plastic&logo=npm&color=%23fea9f8&label=Bundle%20Size) ![npm downloads](https://img.shields.io/npm/dm/@devvie/bottom-sheet?style=plastic&logo=npm&color=%23fea9f8&label=Downloads) - The smart 😎, tiny 📦, and flexible 🎗 bottom sheet your app craves 🚀 ![Preview for Android & iOS](https://i.ibb.co/Y38XsMr/Combined.gif) + #### Web Preview +

@@ -45,7 +47,8 @@ yarn add @devvie/bottom-sheet ``` ## 📱 Minimal Usage -Opening and closing the bottom sheet is done imperatively, so just pass a `ref` to the bottom sheet and call the `open` or `close` methods via the `ref` instance to open and close the bottom sheet respectively. + +Opening and closing the bottom sheet is done imperatively, so just pass a `ref` to the bottom sheet and call the `open` or `close` methods via the `ref` instance to open and close the bottom sheet respectively. ##### Examples @@ -54,130 +57,139 @@ Opening and closing the bottom sheet is done imperatively, so just pass a `ref` ```tsx import React, { useRef } from 'react'; import BottomSheet, { BottomSheetMethods } from '@devvie/bottom-sheet'; -import { Button } from 'react-native'; +import { Button, View } from 'react-native'; const App = () => { const sheetRef = useRef(null); return ( -