Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

react-native-raw-bottom-sheet

Package Overview
Dependencies
Maintainers
1
Versions
18
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

react-native-raw-bottom-sheet - npm Package Compare versions

Comparing version 2.2.1 to 3.0.0-rc.1

.eslintrc.js

160

__tests__/RBSheet.test.js

@@ -1,150 +0,28 @@

import React from "react";
import { View, Text, Modal, TouchableOpacity, Animated } from "react-native";
import Enzyme, { shallow } from "enzyme";
import Adapter from "enzyme-adapter-react-16";
import RBSheet from "../src";
import React from 'react';
import {render, act} from '@testing-library/react-native';
import RBSheet from '../src';
Enzyme.configure({ adapter: new Adapter() });
describe('<RBSheet />', () => {
let ref;
let getByTestId;
describe("React Native Raw Bottom Sheet", () => {
describe("Render", () => {
it("should render correctly with no props", () => {
const wrapper = shallow(<RBSheet />);
expect(wrapper).toMatchSnapshot();
});
it("should render correctly with given props", () => {
const wrapper = shallow(
<RBSheet
height={300}
minClosingHeight={100}
openDuration={350}
closeOnSwipeDown={false}
closeOnPressMask={false}
customStyles={{
wrapper: {
backgroundColor: "#00000066"
},
container: {
justifyContent: "center",
alignItems: "center"
}
}}
onClose={() => {}}
/>
);
expect(wrapper).toMatchSnapshot();
});
it("should render correctly with any children", () => {
const wrapper = shallow(
<RBSheet>
<View>
<Text>React Native Raw Bottom Sheet</Text>
</View>
</RBSheet>
);
expect(wrapper).toMatchSnapshot();
});
describe("Mask", () => {
it("should render mask", () => {
const wrapper = shallow(<RBSheet />);
expect(wrapper.find(TouchableOpacity).length).toEqual(1);
});
it("should closeOnPressMask when given prop true", () => {
const wrapper = shallow(<RBSheet closeOnPressMask />);
wrapper.instance().close = jest.fn();
wrapper.find(TouchableOpacity).simulate("Press");
expect(wrapper.instance().close).toHaveBeenCalled();
});
it("should not closeOnPressMask when given prop false", () => {
const wrapper = shallow(<RBSheet closeOnPressMask={false} />);
wrapper.instance().close = jest.fn();
wrapper.find(TouchableOpacity).simulate("Press");
expect(wrapper.instance().close).not.toHaveBeenCalled();
});
});
describe("Modal", () => {
it("should render modal", () => {
const wrapper = shallow(<RBSheet />);
expect(wrapper.find(Modal).length).toEqual(1);
});
});
describe("DraggableArea", () => {
it("should not render draggable area", () => {
const wrapper = shallow(<RBSheet />);
expect(wrapper.find(View).length).toEqual(1);
});
it("should render draggable area", () => {
const wrapper = shallow(<RBSheet closeOnDragDown />);
expect(wrapper.find(View).length).toEqual(3);
});
});
beforeEach(() => {
ref = React.createRef();
getByTestId = render(<RBSheet ref={ref} />).getByTestId;
});
describe("Method", () => {
let wrapper;
let setModalVisible;
beforeEach(() => {
wrapper = shallow(<RBSheet />);
setModalVisible = jest.spyOn(RBSheet.prototype, "setModalVisible");
Animated.timing = (value, config) => {
return {
start: callback => {
value.setValue(config.toValue);
if (typeof callback === "function") callback();
}
};
};
});
it('should render correctly', () => {
getByTestId = render(<RBSheet ref={ref} draggable />).getByTestId;
it("should createPanResponder called", () => {
wrapper = shallow(<RBSheet />);
const createPanResponder = jest.spyOn(RBSheet.prototype, "createPanResponder");
wrapper.instance().createPanResponder({ closeOnSwipeDown: true, height: 300 });
expect(createPanResponder).toHaveBeenCalledTimes(1);
act(() => {
ref.current.open();
});
it("should method open called", () => {
wrapper.instance().open();
expect(setModalVisible).toHaveBeenCalled();
expect(wrapper.state().modalVisible).toBe(true);
});
it("should onOpen callback function called", () => {
const onOpen = jest.fn();
wrapper = shallow(<RBSheet onOpen={onOpen} />);
wrapper.instance().open();
expect(onOpen).toHaveBeenCalled();
});
it("should method close called", () => {
wrapper.instance().close();
expect(setModalVisible).toHaveBeenCalled();
expect(wrapper.state().modalVisible).toBe(false);
});
it("should onClose callback function called", () => {
const onClose = jest.fn();
wrapper = shallow(<RBSheet onClose={onClose} />);
wrapper.instance().close();
expect(onClose).toHaveBeenCalled();
});
it("should onRequestClose called", () => {
const mockFn = jest.fn();
RBSheet.prototype.setModalVisible = mockFn;
wrapper
.find(Modal)
.props()
.onRequestClose();
expect(mockFn).toHaveBeenCalled();
});
expect(getByTestId('Modal')).toBeTruthy();
expect(getByTestId('KeyboardAvoidingView')).toBeTruthy();
expect(getByTestId('TouchableOpacity')).toBeTruthy();
expect(getByTestId('AnimatedView')).toBeTruthy();
expect(getByTestId('DraggableView')).toBeTruthy();
expect(getByTestId('DraggableIcon')).toBeTruthy();
});
});

@@ -1,30 +0,39 @@

import { Component } from "react";
import { StyleProp, ViewStyle } from "react-native";
import React from 'react';
import {
StyleProp,
ViewStyle,
ModalProps,
KeyboardAvoidingViewProps,
} from 'react-native';
declare module "react-native-raw-bottom-sheet" {
export type RBSheetProps = {
animationType?: "none" | "fade" | "slide";
height?: number;
minClosingHeight?: number;
openDuration?: number;
closeDuration?: number;
closeOnDragDown?: boolean;
dragFromTopOnly?: boolean;
closeOnPressMask?: boolean;
closeOnPressBack?: boolean;
onClose?: (params?: any) => void;
onOpen?: (params?: any) => void;
customStyles?: {
wrapper?: StyleProp<ViewStyle>;
container?: StyleProp<ViewStyle>;
draggableIcon?: StyleProp<ViewStyle>;
};
keyboardAvoidingViewEnabled?: boolean;
children?: React.ReactNode;
interface RBSheetProps {
height?: number;
openDuration?: number;
closeDuration?: number;
closeOnPressMask?: boolean;
closeOnPressBack?: boolean;
draggable?: boolean;
dragOnContent?: boolean;
useNativeDriver?: boolean;
customStyles?: {
wrapper?: StyleProp<ViewStyle>;
container?: StyleProp<ViewStyle>;
draggableIcon?: StyleProp<ViewStyle>;
};
customModalProps?: ModalProps;
customAvoidingViewProps?: KeyboardAvoidingViewProps;
onOpen?: () => void;
onClose?: () => void;
children?: React.ReactNode;
}
export default class RBSheet extends Component<RBSheetProps> {
open(params?: any): void;
close(params?: any): void;
}
interface RBSheetRef {
open: () => void;
close: () => void;
}
declare const RBSheet: React.ForwardRefExoticComponent<
RBSheetProps & React.RefAttributes<RBSheetRef>
>;
export default RBSheet;

@@ -1,3 +0,3 @@

import RBSheet from "./src";
import RBSheet from './src';
export default RBSheet;
{
"name": "react-native-raw-bottom-sheet",
"version": "2.2.1",
"version": "3.0.0-rc.1",
"description": "Add Your Own Component To Bottom Sheet Whatever You Want (Android & iOS)",

@@ -8,3 +8,4 @@ "main": "index.js",

"scripts": {
"test": "jest --coverage"
"lint": "eslint .",
"test": "jest"
},

@@ -34,25 +35,20 @@ "repository": {

"devDependencies": {
"enzyme": "^3.9.0",
"enzyme-adapter-react-16": "^1.10.0",
"eslint": "^5.14.1",
"eslint-config-airbnb": "^17.1.0",
"eslint-config-prettier": "^4.0.0",
"eslint-plugin-import": "^2.16.0",
"eslint-plugin-jsx-a11y": "^6.2.1",
"eslint-plugin-prettier": "^3.0.1",
"eslint-plugin-react": "^7.12.4",
"jest": "^24.9.0",
"metro-react-native-babel-preset": "^0.52.0",
"prettier": "^1.16.4",
"prop-types": "^15.7.2",
"react": "^16.8.6",
"react-dom": "^16.8.3",
"react-native": "^0.62.2"
"@babel/core": "^7.24.0",
"@babel/preset-env": "^7.24.0",
"@react-native/eslint-config": "0.73.2",
"@react-native/typescript-config": "0.73.1",
"@testing-library/react-native": "^12.4.3",
"babel-jest": "^29.7.0",
"eslint": "8.19.0",
"jest": "29.6.3",
"metro-react-native-babel-preset": "^0.77.0",
"prettier": "2.8.8",
"react": "18.2.0",
"react-native": "0.73.2",
"react-test-renderer": "^18.2.0",
"typescript": "5.0.4"
},
"jest": {
"preset": "react-native",
"transform": {
"^.+\\.js$": "<rootDir>/node_modules/react-native/jest/preprocessor.js"
}
"preset": "react-native"
}
}
# react-native-raw-bottom-sheet
> ## Motivation
>
> Thank you for using the `react-native-raw-bottom-sheet` library.
>
> This library has been published for over 5 years and I've noticed that new libraries are being published frequently, and I hope that those newer libraries will replace this small library with time, that's why I have stopped maintaining this project for the past few years.
>
> However, I was pleasantly surprised to see that the number of installations has remained high over the past year. Therefore, I have decided to continue to maintain this project.
>
> I will ensure that this project remains simple and lightweight, without requiring any configuration or external dependencies.
>
> I would also like to express my gratitude to all the contributors who have made pull requests. Thank you!
## Hooray! The new version 3 has been released.
Please pay close attention if you are upgrading the RBSheet from version 2 to version 3.
- Functional Components: Starting from v3.0.0, RBSheet has been completely rewritten using Functional Components. This improves performance and aligns with modern React practices.
- Prop Removal & Renaming: Several props have been removed and renamed for improved clarity and maintainability. Please refer to the updated documentation for a complete list of available props and their intended behavior.
<hr>
[![npm version](https://badge.fury.io/js/react-native-raw-bottom-sheet.svg)](//npmjs.com/package/react-native-raw-bottom-sheet)
[![npm downloads](https://img.shields.io/npm/dm/react-native-raw-bottom-sheet.svg)
](//npmjs.com/package/react-native-raw-bottom-sheet)
[![Build Status](https://travis-ci.org/nysamnang/react-native-raw-bottom-sheet.svg?branch=master)](https://travis-ci.org/nysamnang/react-native-raw-bottom-sheet)
[![codecov](https://codecov.io/gh/nysamnang/react-native-raw-bottom-sheet/graph/badge.svg?token=tJuJsd1V8e)](https://codecov.io/gh/nysamnang/react-native-raw-bottom-sheet)
- Super Lightweight Component
- Add Your own Component To Bottom Sheet
- Add Your Own Component To Bottom Sheet
- Customize Whatever You Like

@@ -29,3 +26,3 @@ - Support Drag Down Gesture

- Zero dependency
- Top Search Ranking (react native bottom sheet) at [npms.io](https://npms.io/search?q=react%20native%20bottom%20sheet)
- Millions of Downloads

@@ -50,67 +47,38 @@ | Showcase iOS | Showcase Android |

#### Class component
Please check the [example](https://github.com/nysamnang/react-native-raw-bottom-sheet/tree/master/example) folder to explore more example codes.
```jsx
import React, { Component } from "react";
import { View, Button } from "react-native";
import RBSheet from "react-native-raw-bottom-sheet";
#### Single Bottom Sheet
export default class Example extends Component {
render() {
return (
<View style={{ flex: 1, justifyContent: "center", alignItems: "center" }}>
<Button title="OPEN BOTTOM SHEET" onPress={() => this.RBSheet.open()} />
<RBSheet
ref={ref => {
this.RBSheet = ref;
}}
height={300}
openDuration={250}
customStyles={{
container: {
justifyContent: "center",
alignItems: "center"
}
}}
>
<YourOwnComponent />
</RBSheet>
</View>
);
}
}
```
#### Functional component
```jsx
import React, { useRef } from "react";
import { View, Button } from "react-native";
import RBSheet from "react-native-raw-bottom-sheet";
import React, {useRef} from 'react';
import {View, Button} from 'react-native';
import RBSheet from 'react-native-raw-bottom-sheet';
export default function Example() {
const refRBSheet = useRef();
return (
<View
style={{
flex: 1,
justifyContent: "center",
alignItems: "center",
backgroundColor: "#000"
}}
>
<Button title="OPEN BOTTOM SHEET" onPress={() => refRBSheet.current.open()} />
<View style={{flex: 1}}>
<Button
title="OPEN BOTTOM SHEET"
onPress={() => refRBSheet.current.open()}
/>
<RBSheet
ref={refRBSheet}
closeOnDragDown={true}
closeOnPressMask={false}
useNativeDriver={true}
customStyles={{
wrapper: {
backgroundColor: "transparent"
backgroundColor: 'transparent',
},
draggableIcon: {
backgroundColor: "#000"
}
backgroundColor: '#000',
},
}}
>
customModalProps={{
animationType: 'slide',
statusBarTranslucent: true,
}}
customAvoidingViewProps={{
enabled: false,
}}>
<YourOwnComponent />

@@ -123,17 +91,24 @@ </RBSheet>

#### Dynamic Bottom Sheet
#### Multiple Bottom Sheet
```jsx
renderItem = (item, index) => (
<View>
<Button title={`OPEN BOTTOM SHEET-${index}`} onPress={() => this[RBSheet + index].open()} />
<RBSheet
ref={ref => {
this[RBSheet + index] = ref;
}}
>
<YourOwnComponent onPress={() => this[RBSheet + index].close()} />
</RBSheet>
</View>
);
const refRBSheet = useRef([]);
const renderItem = ({item, index}) => {
return (
<View>
<TouchableOpacity
style={styles.button}
onPress={() => refRBSheet.current[index].open()}>
<Text style={styles.buttonText}>ITEM {item + 1}</Text>
</TouchableOpacity>
<RBSheet ref={ref => (refRBSheet.current[index] = ref)}>
<View style={styles.bottomSheetContainer}>
<Text style={styles.bottomSheetText}>I AM ITEM {item + 1}</Text>
</View>
</RBSheet>
</View>
);
};
```

@@ -143,27 +118,25 @@

| Props | Type | Description | Default |
| ---------------------------| -------- | ------------------------------------------------------- | -------- |
| animationType | string | Background animation ("none", "fade", "slide") | "none" |
| height | number | Height of Bottom Sheet | 260 |
| minClosingHeight | number | Minimum height of Bottom Sheet before close | 0 |
| openDuration | number | Open Bottom Sheet animation duration | 300 (ms) |
| closeDuration | number | Close Bottom Sheet animation duration | 200 (ms) |
| closeOnDragDown | boolean | Use gesture drag down to close Bottom Sheet | false |
| closeOnTouchablesDragDown | boolean | Use gesture drag down on touchable components to close Bottom Sheet<br/> (Doesn't work for touchable components inside a scrollView) <br/> (closeOnDragDown must be enabled for this to work) | false |
| dragFromTopOnly | boolean | Drag only the top area of the draggableIcon to close Bottom Sheet instead of the whole content | false |
| closeOnPressMask | boolean | Press the area outside to close Bottom Sheet | true |
| closeOnPressBack | boolean | Press back android to close Bottom Sheet (Android only) | true |
| onClose | function | Callback function when Bottom Sheet has closed | null |
| onOpen | function | Callback function when Bottom Sheet has opened | null |
| customStyles | object | Custom style to Bottom Sheet | {} |
| keyboardAvoidingViewEnabled | boolean | Enable KeyboardAvoidingView | true (ios) |
| customModalProps | object | Custom props to Bottom Sheet Modal | {} |
| Props | Type | Description | Default |
| ----------------------- | -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- | -------- |
| height | number | The height of bottom sheet | 260 |
| openDuration | number | Duration of the animation when opening bottom sheet | 300 (ms) |
| closeDuration | number | Duration of the animation when closing bottom sheet | 200 (ms) |
| closeOnPressMask | boolean | Press the outside area (mask) to close bottom sheet | true |
| closeOnPressBack | boolean | Press hardware back android to close bottom sheet (Android only) | false |
| draggable | boolean | Enable the drag-down gesture to close the bottom sheet | false |
| dragOnContent | boolean | The draggable is only worked on the draggable icon. Set this to `true`<br />if you want to drag on the content as well (doesn't work with ScrollView) | false |
| useNativeDriver | boolean | Use the native driver to run smoother animation | false |
| customStyles | object | Add [custom styles](#available-custom-style) to bottom sheet | {} |
| customModalProps | object | Add [custom props](https://reactnative.dev/docs/modal#props) to modal | {} |
| customAvoidingViewProps | object | Add [custom props](https://reactnative.dev/docs/keyboardavoidingview#props) to KeyboardAvoidingView | {} |
| onOpen | function | Callback function that will be called after the bottom sheet has been opened | null |
| onClose | function | Callback function that will be called after the bottom sheet has been closed | null |
### Available Custom Style
```
```js
customStyles: {
wrapper: {...}, // The Root of Component (You can change the `backgroundColor` or any styles)
container: {...}, // The Container of Bottom Sheet
draggableIcon: {...} // The Draggable Icon (If you set closeOnDragDown to true)
wrapper: {...}, // The Root of component (Change the mask's background color here).
container: {...}, // The Container of bottom sheet (The animated view that contains your component).
draggableIcon: {...} // The style of Draggable Icon (If you set `draggable` to `true`).
}

@@ -174,15 +147,28 @@ ```

| Method Name | Description |
| ----------- | ------------------ |
| open | Open Bottom Sheet |
| close | Close Bottom Sheet |
| Method Name | Description | Usage |
| ----------- | ---------------------- | ---------------------------- |
| open | Open the bottom sheet | `refRBSheet.current.open()` |
| close | Close the bottom sheet | `refRBSheet.current.close()` |
## Note
## CONTRIBUTING
- If you combind `RBSheet` with <a href="https://github.com/kmagiera/react-native-gesture-handler" target="_blank">react-native-gesture-handler</a>, the components inside RBSheet will not fire onPress event on Android [#37](https://github.com/nysamnang/react-native-raw-bottom-sheet/issues/37).
- The demo source codes are in `example folder`.
I'm really glad you're reading this, because we need volunteer developers to help bring this project to life.
#### How to contribute:
1. Clone this repository
2. Open project, then run `yarn` to install devDependencies
3. Add your magic code for contribution
4. Test your code
- Navigate to `example` folder
- Run `yarn` & `yarn start` to run the example project
- Test your code in `example/App.js`
5. Update `README.md` to update documentation (Optional)
6. Write unit testing in `__tests__` folder (Optional)
7. Update `index.d.ts` to update typing (Optional)
8. Make a pull request, Genius!
## License
This project is licensed under the MIT License - see the [LICENSE.md](https://github.com/nysamnang/react-native-raw-bottom-sheet/blob/master/LICENSE) file for details
This project is licensed under the MIT License - see the [LICENSE.md](https://github.com/nysamnang/react-native-raw-bottom-sheet/blob/master/LICENSE) file for details.

@@ -189,0 +175,0 @@ ## Author

@@ -1,200 +0,164 @@

import React, { Component } from "react";
import PropTypes from "prop-types";
// Importing necessary packages and components
import React, {useState, useRef, forwardRef, useImperativeHandle} from 'react';
import {
View,
KeyboardAvoidingView,
Modal,
TouchableOpacity,
Animated,
PanResponder,
Platform
} from "react-native";
import styles from "./style";
TouchableOpacity,
Modal,
KeyboardAvoidingView,
Platform,
View,
} from 'react-native';
import styles from './style';
const SUPPORTED_ORIENTATIONS = [
"portrait",
"portrait-upside-down",
"landscape",
"landscape-left",
"landscape-right"
];
// Creating the RBSheet component
const RBSheet = forwardRef((props, ref) => {
// Props destructuring
const {
height = 260,
openDuration = 300,
closeDuration = 200,
closeOnPressMask = true,
closeOnPressBack = false,
draggable = false,
dragOnContent = false,
useNativeDriver = false,
customStyles = {},
customModalProps = {},
customAvoidingViewProps = {},
onOpen = null,
onClose = null,
children = <View />,
} = props;
class RBSheet extends Component {
constructor(props) {
super(props);
this.state = {
modalVisible: false,
animatedHeight: new Animated.Value(0),
pan: new Animated.ValueXY()
};
// Using useState hook to manage modal visibility
const [modalVisible, setModalVisible] = useState(false);
this.createPanResponder(props);
}
// Using useRef hook to reference animated values
const animatedHeight = useRef(new Animated.Value(0)).current;
const pan = useRef(new Animated.ValueXY()).current;
setModalVisible(visible, props) {
const { height, minClosingHeight, openDuration, closeDuration, onClose, onOpen } = this.props;
const { animatedHeight, pan } = this.state;
if (visible) {
this.setState({ modalVisible: visible });
if (typeof onOpen === "function") onOpen(props);
Animated.timing(animatedHeight, {
useNativeDriver: false,
toValue: height,
duration: openDuration
}).start();
} else {
Animated.timing(animatedHeight, {
useNativeDriver: false,
toValue: minClosingHeight,
duration: closeDuration
}).start(() => {
pan.setValue({ x: 0, y: 0 });
this.setState({
modalVisible: visible,
animatedHeight: new Animated.Value(0)
});
// Exposing component methods to parent via useImperativeHandle hook
useImperativeHandle(ref, () => ({
open: () => handleSetVisible(true),
close: () => handleSetVisible(false),
}));
if (typeof onClose === "function") onClose(props);
});
}
}
// Function to create PanResponder
const createPanResponder = () => {
return PanResponder.create({
// Respond only if draggable is true
onStartShouldSetPanResponder: () => draggable,
createPanResponder(props) {
const { closeOnDragDown, closeOnTouchablesDragDown, height } = props;
const { pan } = this.state;
this.panResponder = PanResponder.create({
onStartShouldSetPanResponder: () => closeOnDragDown,
onMoveShouldSetPanResponder: (e, gestureState) => (
(closeOnTouchablesDragDown && closeOnDragDown)
&& (Math.abs(gestureState.dx) >= 5
|| Math.abs(gestureState.dy) >= 5)
),
// Respond only if draggable, dragOnContent is true, and vertical movement is positive
onMoveShouldSetPanResponder: (e, gestureState) =>
draggable && dragOnContent && gestureState.dy > 0,
// Update pan.y value on vertical move if gestureState.dy is positive
onPanResponderMove: (e, gestureState) => {
if (gestureState.dy > 0) {
Animated.event([null, { dy: pan.y }], { useNativeDriver: false })(e, gestureState);
}
gestureState.dy > 0 &&
Animated.event([null, {dy: pan.y}], {useNativeDriver})(
e,
gestureState,
);
},
// Handle when the user has released the touche
onPanResponderRelease: (e, gestureState) => {
if (height / 4 - gestureState.dy < 0) {
this.setModalVisible(false);
// Close modal if swipe down distance is more than 100
if (gestureState.dy > 100) {
handleSetVisible(false);
} else {
Animated.spring(pan, { toValue: { x: 0, y: 0 }, useNativeDriver: false }).start();
// Reset pan to original position on release
Animated.spring(pan, {
toValue: {x: 0, y: 0},
useNativeDriver,
}).start();
}
}
},
});
}
};
open(props) {
this.setModalVisible(true, props);
}
// Referencing the panResponder
const panResponder = useRef(createPanResponder()).current;
close(props) {
this.setModalVisible(false, props);
}
setHeight(newHeight) {
const { animatedHeight } = this.state;
const { duration } = this.props;
Animated.timing(animatedHeight, {
toValue: newHeight,
duration
}).start();
}
// Function to handle the visibility of the modal
const handleSetVisible = visible => {
if (visible) {
setModalVisible(visible);
// Call onOpen callback if provided
if (typeof onOpen === 'function') {
onOpen();
}
// Animate height on open
Animated.timing(animatedHeight, {
useNativeDriver,
toValue: height,
duration: openDuration,
}).start();
} else {
// Animate height on close
Animated.timing(animatedHeight, {
useNativeDriver,
toValue: 0,
duration: closeDuration,
}).start(() => {
setModalVisible(visible);
// Reset pan value
pan.setValue({x: 0, y: 0});
// Call onClose callback if provided
if (typeof onClose === 'function') {
onClose();
}
});
}
};
render() {
const {
animationType,
closeOnDragDown,
dragFromTopOnly,
closeOnPressMask,
closeOnPressBack,
children,
customStyles,
keyboardAvoidingViewEnabled,
customModalProps
} = this.props;
const { animatedHeight, pan, modalVisible } = this.state;
const panStyle = {
transform: pan.getTranslateTransform()
};
return (
<Modal
transparent
animationType={animationType}
visible={modalVisible}
supportedOrientations={SUPPORTED_ORIENTATIONS}
onRequestClose={() => {
if (closeOnPressBack) this.setModalVisible(false);
}}
{...customModalProps}
>
<KeyboardAvoidingView
enabled={keyboardAvoidingViewEnabled}
behavior="padding"
style={[styles.wrapper, customStyles.wrapper]}
>
<TouchableOpacity
style={styles.mask}
activeOpacity={1}
onPress={() => (closeOnPressMask ? this.close() : null)}
/>
<Animated.View
{...(!dragFromTopOnly && this.panResponder.panHandlers)}
style={[panStyle, styles.container, { height: animatedHeight }, customStyles.container]}
>
{closeOnDragDown && (
// Returning the RBSheet component
return (
<Modal
testID="Modal"
transparent
visible={modalVisible}
onRequestClose={closeOnPressBack ? () => handleSetVisible(false) : null} // Close on hardware button press (Android) if enabled
{...customModalProps}>
<KeyboardAvoidingView
testID="KeyboardAvoidingView"
behavior={Platform.OS === 'ios' ? 'padding' : 'height'}
style={[styles.wrapper, customStyles.wrapper]}
{...customAvoidingViewProps}>
<TouchableOpacity
testID="TouchableOpacity"
style={styles.mask}
activeOpacity={1}
onPress={closeOnPressMask ? () => handleSetVisible(false) : null} // Close on mask press if enabled
/>
<Animated.View
testID="AnimatedView"
{...(dragOnContent && panResponder.panHandlers)} // Attach pan handlers to content if dragOnContent is true
style={[
styles.container,
{transform: pan.getTranslateTransform()},
{height: animatedHeight},
customStyles.container,
]}>
{draggable && ( // Show draggable icon if set it to true
<View
testID="DraggableView"
{...(!dragOnContent && panResponder.panHandlers)} // Attach pan handlers to draggable icon if dragOnContent is false
style={styles.draggableContainer}>
<View
{...(dragFromTopOnly && this.panResponder.panHandlers)}
style={styles.draggableContainer}
>
<View style={[styles.draggableIcon, customStyles.draggableIcon]} />
</View>
)}
{children}
</Animated.View>
</KeyboardAvoidingView>
</Modal>
);
}
}
testID="DraggableIcon"
style={[styles.draggableIcon, customStyles.draggableIcon]}
/>
</View>
)}
{children}
</Animated.View>
</KeyboardAvoidingView>
</Modal>
);
});
RBSheet.propTypes = {
animationType: PropTypes.oneOf(["none", "slide", "fade"]),
height: PropTypes.number,
minClosingHeight: PropTypes.number,
openDuration: PropTypes.number,
closeDuration: PropTypes.number,
closeOnDragDown: PropTypes.bool,
closeOnTouchablesDragDown: PropTypes.bool,
closeOnPressMask: PropTypes.bool,
dragFromTopOnly: PropTypes.bool,
closeOnPressBack: PropTypes.bool,
keyboardAvoidingViewEnabled: PropTypes.bool,
customStyles: PropTypes.objectOf(PropTypes.object),
customModalProps: PropTypes.objectOf(PropTypes.any),
onClose: PropTypes.func,
onOpen: PropTypes.func,
children: PropTypes.node
};
RBSheet.defaultProps = {
animationType: "none",
height: 260,
minClosingHeight: 0,
openDuration: 300,
closeDuration: 200,
closeOnDragDown: false,
closeOnTouchablesDragDown: false,
dragFromTopOnly: false,
closeOnPressMask: true,
closeOnPressBack: true,
keyboardAvoidingViewEnabled: Platform.OS === "ios",
customStyles: {},
customModalProps: {},
onClose: null,
onOpen: null,
children: <View />
};
// Exporting the RBSheet component
export default RBSheet;

@@ -1,2 +0,2 @@

import { StyleSheet } from "react-native";
import {StyleSheet} from 'react-native';

@@ -6,18 +6,18 @@ const styles = StyleSheet.create({

flex: 1,
backgroundColor: "#00000077"
backgroundColor: '#00000077',
},
mask: {
flex: 1,
backgroundColor: "transparent"
backgroundColor: 'transparent',
},
container: {
backgroundColor: "#fff",
width: "100%",
backgroundColor: '#fff',
width: '100%',
height: 0,
overflow: "hidden"
overflow: 'hidden',
},
draggableContainer: {
width: "100%",
alignItems: "center",
backgroundColor: "transparent"
width: '100%',
alignItems: 'center',
backgroundColor: 'transparent',
},

@@ -29,6 +29,6 @@ draggableIcon: {

margin: 10,
backgroundColor: "#ccc"
}
backgroundColor: '#ccc',
},
});
export default styles;
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc