Skip to content

Commit

Permalink
docs: update docs (#3)
Browse files Browse the repository at this point in the history
* docs: updated readme file

* docs: updated scrollables docs

* docs: added custom-handle, react-navigation & touchables docs

* chore: remove unused dependencies
  • Loading branch information
gorhom authored Aug 11, 2020
1 parent a58a29f commit fdef2a9
Show file tree
Hide file tree
Showing 22 changed files with 826 additions and 125 deletions.
1 change: 1 addition & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
MIT License

Copyright (c) 2020 Mo Gorhom
Copyright (c) 2020 Raul Gomez Acuna

Permission is hereby granted, free of charge, to any person obtaining a copy
Expand Down
197 changes: 194 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,197 @@
> This is a cloned project of `react-native-scroll-bottom-sheet` by [@rgommezz](https://github.com/rgommezz), but with different approach and extra functionalities.
<div align="center">
<h1>Bottom Sheet</h1>

[![npm](https://img.shields.io/npm/v/@gorhom/bottom-sheet?style=flat-square)](https://www.npmjs.com/package/@gorhom/bottom-sheet) [![npm](https://img.shields.io/npm/l/@gorhom/bottom-sheet?style=flat-square)](https://www.npmjs.com/package/@gorhom/bottom-sheet) [![npm](https://img.shields.io/badge/types-included-blue?style=flat-square)](https://www.npmjs.com/package/@gorhom/bottom-sheet)

# Bottom Sheet
<img src="./preview.gif">

> TODO
A performant interactive bottom sheet with fully configurable options 🚀

</div>

> Initially, this project was a cloned of `react-native-scroll-bottom-sheet` by [@rgommezz](https://github.com/rgommezz) ❤️. However, it is been fully re-written to add extra functionalities and simplify the approach.
---

## Table of Contents

1. [Features](#features)
2. [Installation](#installation)
3. [Usage](#usage)
- [Custom Handle](./docs/custom-handle)
- [React Navigation Integration](./docs/react-navigation)
- [Touchables](./docs/touchables)
4. [Props](#props)
5. [Scrollables](#scrollables)
- [BottomSheetFlatList](./docs/flatlist)
- [BottomSheetSectionList](./docs/sectionlist)
- [BottomSheetScrollView](./docs/scrollview)
- [BottomSheetView](./docs/flatlist)
6. [To Do](#to-do)
7. [Credits](#built-with)
8. [License](#license)

## Features

- Smooth interactions & snapping animations.
- Support `FlatList`, `SectionList`, `ScrollView` & `View` scrolling interactions.
- Support `React Navigation` Integration.
- Written in `TypeScript`.

## Installation

```sh
yarn add @gorhom/bottom-sheet
# or
npm install @gorhom/bottom-sheet
```

> ⚠️ You need to install [react-native-reanimated](https://github.com/software-mansion/react-native-reanimated) & [react-native-gesture-handler](https://github.com/software-mansion/react-native-gesture-handler) and follow their installation instructions.
## Usage

```tsx
import React, { useCallback, useMemo, useRef } from 'react';
import { View, StyleSheet } from 'react-native';
import BottomSheet from '@gorhom/bottom-sheet';

const App = () => {
// hooks
const bottomSheetRef = useRef<BottomSheet>(null);

// variables
const snapPoints = useMemo(() => ['25%', '50%', '90%'], []);

// callbacks
const handleSheetChanges = useCallback((index: number) => {
console.log('handleSheetChanges', index);
}, []);

// renders
return (
<View style={styles.container}>
<BottomSheet
ref={bottomSheetRef}
initialSnapIndex={1}
snapPoints={snapPoints}
onChange={handleSheetChanges}
>
{/* INSERT A SCROLLABLE HERE */}
</BottomSheet>
</View>
);
};

const styles = StyleSheet.create({
container: {
flex: 1,
padding: 24,
},
});

export default App;
```

## Props

#### `initialSnapIndex`

Initial snap index. You also could provide {`-1`} to initiate bottom sheet in closed state.

> `required:` NO | `type:` number | `default:` 0
#### `snapPoints`

Points for the bottom sheet to snap to, `points should be sorted from bottom to top`. It accepts array of number, string or mix. String values should be a percentage.

> `required:` YES | `type:` Array<string | number> <br> `example:` [100, '50%', '90%']
#### `topInset`

Top inset value helps to calculate percentage snap points values. usually comes from `@react-navigation/stack` hook `useHeaderHeight` or from `react-native-safe-area-context` hook `useSafeArea`.

> `required:` NO | `type:` number | `default:` 0
#### `animationDuration`

Snapping animation duration.

> `required:` NO | `type:` number | `default:` 500
#### `animationEasing`

Snapping animation easing function.

> `required:` NO | `type:` Animated.EasingFunction | `default:` Easing.out(Easing.back(0.75))
#### `animatedPosition`

Animated value to be used as a callback for the position node internally.

> `required:` NO | `type:` Animated.Value<number>
#### `animatedPositionIndex`

Animated value to be used as a callback for the position index node internally.

> `required:` NO | `type:` Animated.Value<number>
#### `handleComponent`

Component to be placed as a sheet handle.

> `required:` NO | `type:` React.FC<[BottomSheetHandleProps](./src/components/handle/types.d.ts)>
#### `onChange`

Callback when sheet position changed to a provided point.

> `required:` NO | `type:` (index: number) => void
#### `children`

A scrollable node or normal view.

> `required:` YES | `type:` React.ReactNode[] | React.ReactNode
## Scrollables

This library provides a pre-integrated views that utilise an internal functionalities with the bottom sheet to allow smooth interactions. These views i called them `Scrollables` and they are:

- [BottomSheetFlatList](./docs/flatlist)
- [BottomSheetSectionList](./docs/sectionlist)
- [BottomSheetScrollView](./docs/scrollview)
- [BottomSheetView](./docs/flatlist)

## To Do

- [ ] Add tablets support.

<h2 id="built-with">Built With ❤️</h2>

- [react-native-reanimated](https://github.com/software-mansion/react-native-reanimated)
- [react-native-gesture-handler](https://github.com/software-mansion/react-native-gesture-handler)
- [react-native-redash](https://github.com/wcandillon/react-native-redash)
- [@react-native-community/bob](https://github.com/react-native-community/bob)

## Author

- [Mo Gorhom](https://gorhom.dev/)

## License

MIT

<div align="center">

Liked the library? 😇

<a href="https://www.buymeacoffee.com/gorhom" target="_blank"><img src="https://cdn.buymeacoffee.com/buttons/default-red.png" alt="Buy Me A Coffee" height="50" ></a>

</div>

---

<p align="center">
<a href="https://gorhom.dev" target="_blank"><img alt="Mo Gorhom" src="./logo.png"></a>
</p>
134 changes: 134 additions & 0 deletions docs/custom-handle.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
# Custom Handle

The library allows you to override the handle and create your own wonderful interactive animation.

When you provide your own handle component, it will receive an animated value - `animatedPositionIndex` - that indicates the current position of the sheet.

Here is an example of a custom handle component:

```tsx
import React, { useMemo } from 'react';
import { StyleProp, StyleSheet, ViewStyle } from 'react-native';
import { BottomSheetHandleProps } from '@gorhom/bottom-sheet';
import Animated, { interpolate, Extrapolate } from 'react-native-reanimated';
import { transformOrigin, toRad } from 'react-native-redash';

interface HandleProps extends BottomSheetHandleProps {
style?: StyleProp<ViewStyle>;
}

const Handle: React.FC<HandleProps> = ({ style, animatedPositionIndex }) => {
//#region animations
const borderTopRadius = interpolate(animatedPositionIndex, {
inputRange: [1, 2],
outputRange: [20, 0],
extrapolate: Extrapolate.CLAMP,
});
const indicatorTransformOriginY = interpolate(animatedPositionIndex, {
inputRange: [0, 1, 2],
outputRange: [-1, 0, 1],
extrapolate: Extrapolate.CLAMP,
});
const leftIndicatorRotate = interpolate(animatedPositionIndex, {
inputRange: [0, 1, 2],
outputRange: [toRad(-30), 0, toRad(30)],
extrapolate: Extrapolate.CLAMP,
});
const rightIndicatorRotate = interpolate(animatedPositionIndex, {
inputRange: [0, 1, 2],
outputRange: [toRad(30), 0, toRad(-30)],
extrapolate: Extrapolate.CLAMP,
});
//#endregion

//#region styles
const containerStyle = useMemo(
() => [
styles.header,
style,
{
borderTopLeftRadius: borderTopRadius,
borderTopRightRadius: borderTopRadius,
},
],
// eslint-disable-next-line react-hooks/exhaustive-deps
[style]
);
const leftIndicatorStyle = useMemo(
() => ({
...styles.indicator,
...styles.leftIndicator,
transform: transformOrigin(
{ x: 0, y: indicatorTransformOriginY },
{
rotate: leftIndicatorRotate,
translateX: -5,
}
),
}),
// eslint-disable-next-line react-hooks/exhaustive-deps
[]
);
const rightIndicatorStyle = useMemo(
() => ({
...styles.indicator,
...styles.rightIndicator,
transform: transformOrigin(
{ x: 0, y: indicatorTransformOriginY },
{
rotate: rightIndicatorRotate,
translateX: 5,
}
),
}),
// eslint-disable-next-line react-hooks/exhaustive-deps
[]
);
//#endregion

// render
return (
<Animated.View style={containerStyle} renderToHardwareTextureAndroid={true}>
<Animated.View style={leftIndicatorStyle} />
<Animated.View style={rightIndicatorStyle} />
</Animated.View>
);
};

export default Handle;

const styles = StyleSheet.create({
header: {
alignContent: 'center',
alignItems: 'center',
justifyContent: 'center',
backgroundColor: 'white',
paddingVertical: 14,
shadowColor: 'black',
shadowOffset: {
width: 0,
height: -20,
},
shadowOpacity: 0.1,
shadowRadius: 10,
elevation: 16,
borderBottomWidth: 1,
borderBottomColor: '#fff',
},
indicator: {
position: 'absolute',
width: 10,
height: 4,
backgroundColor: '#999',
},
leftIndicator: {
borderTopStartRadius: 2,
borderBottomStartRadius: 2,
},
rightIndicator: {
borderTopEndRadius: 2,
borderBottomEndRadius: 2,
},
});

```
Loading

0 comments on commit fdef2a9

Please sign in to comment.