Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/computerjazz/react-native-swipeable-item
A swipe-to-reveal wrapper for list items.
https://github.com/computerjazz/react-native-swipeable-item
Last synced: 1 day ago
JSON representation
A swipe-to-reveal wrapper for list items.
- Host: GitHub
- URL: https://github.com/computerjazz/react-native-swipeable-item
- Owner: computerjazz
- License: mit
- Created: 2020-01-06T06:29:09.000Z (almost 5 years ago)
- Default Branch: main
- Last Pushed: 2023-01-27T04:35:59.000Z (almost 2 years ago)
- Last Synced: 2024-10-18T09:34:25.972Z (29 days ago)
- Language: TypeScript
- Size: 1.34 MB
- Stars: 303
- Watchers: 4
- Forks: 25
- Open Issues: 14
-
Metadata Files:
- Readme: README.md
- Funding: .github/FUNDING.yml
- License: LICENSE.txt
Awesome Lists containing this project
README
# React Native Swipeable Item
A swipeable component with underlay for React Native.
Fully native interactions powered by [Reanimated](https://github.com/kmagiera/react-native-reanimated) and [React Native Gesture Handler](https://github.com/kmagiera/react-native-gesture-handler)Compatible with [React Native Draggable Flatlist](https://github.com/computerjazz/react-native-draggable-flatlist)
![Swipeable Item demo](https://i.imgur.com/fFCnQ0n.gif)
## Install
1. Follow installation instructions for [reanimated](https://github.com/kmagiera/react-native-reanimated) and [react-native-gesture-handler](https://github.com/kmagiera/react-native-gesture-handler)
2. `npm install` or `yarn add` `react-native-swipeable-item`
3. `import SwipeableItem from 'react-native-swipeable-item'`### Props
_NOTE:_ Naming is hard. When you swipe _right_, you reveal the item on the _left_. So what do you name these things? I have decided to name everything according to swipe direction. Therefore, a swipe left reveals the `renderUnderlayLeft` component. Not perfect but it works.
| Name | Type | Description |
| :-------------------- | :---------------------------------------------------------------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `renderUnderlayLeft` | `RenderUnderlay` | Component to be rendered underneath row on left swipe. |
| `renderUnderlayRight` | `RenderUnderlay` | Component to be rendered underneath row on right swipe. |
| `snapPointsLeft` | `number[]` | Pixel values left-swipe snaps to (eg. `[100, 300]`) |
| `snapPointsRight` | `number[]` | Pixel values right-swipe snaps to (eg. `[100, 300]`) |
| `renderOverlay` | `RenderOverlay` | Component to be rendered on top. Use if you need access to programmatic open/close methods. May altenatively pass children to SwipeableItem. |
| `onChange` | `(params: { openDirection: OpenDirection, snapPoint: number }) => void` | Called when row is opened or closed. |
| `swipeEnabled` | `boolean` | Enable/disable swipe. Defaults to `true`. |
| `activationThreshold` | `number` | Distance finger must travel before swipe engages. Defaults to 20. |
| `swipeDamping` | `number` | How much swipe velocity determines snap position. A smaller number means swipe velocity will have a larger effect and row will swipe open more easily. Defaults to `10`. |### Hooks
| Name | Type | Description |
| :----------------------- | :--------------------------------------------------------------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `useSwipeableItemParams` | `() => OverlayParams & { open: OpenPromiseFn, percentOpen: Animated.DerivedValue }` | Utility hook that reutrns the same params as the render functions are called with. `open()` and `percentOpen` params reflect the context in which the hook is called (i.e. within an underlay or overlay component). |
| |```tsx
function MyUnderlayComponent() {
// Underlay components "know" which direction to open, so we don't need to call `openLeft()` or `openRight()`, we can just call 'open()'
// Underlay components also receive the `percentOpen` value of their own direction (`percentOpenLeft` or `percentOpenRight`)
const swipeableItemParams = useSwipeableItemParams();
return ;
}function MyOverlayComponent() {
// Overlay components get the same params, but have defaults filled in for `open()` and `percentOpen` params.
const swipeableItemParams = useSwipeableItemParams();
return ;
}
```### Instance Methods
| Name | Type | Description |
| :------ | :------------------------------------------------------------------------------------------------------------------ | :----------------------------------------------------------- |
| `open` | `(OpenDirection.LEFT \| OpenDirection.RIGHT, snapIndex?: number, options?: { animated: boolean }) => Promise` | Imperatively open left or right. Promise resolves once open. |
| `close` | `(options?: { animated?: boolean}) => Promise` | Close all. Promise resolves once closed. |```tsx
// Imperative open example
const itemRef = useRef(null)...
...
itemRef.current?.open(OpenDirection.LEFT)
```### Types
```ts
type OpenCloseOptions = { animated?: boolean };
type OpenPromiseFn = (
snapPoint?: number,
options?: OpenCloseOptions
) => Promise;
type ClosePromiseFn = (options?: OpenCloseOptions) => Promise;export type UnderlayParams = {
item: T;
open: OpenPromiseFn;
close: ClosePromiseFn;
percentOpen: Animated.DerivedValue;
isGestureActive: Animated.DerivedValue;
direction: OpenDirection;
};export type OverlayParams = {
item: T;
openLeft: OpenPromiseFn;
openRight: OpenPromiseFn;
close: ClosePromiseFn;
openDirection: OpenDirection;
percentOpenLeft: Animated.DerivedValue;
percentOpenRight: Animated.DerivedValue;
};
```### Notes
Gesture handlers can sometimes capture a gesture unintentionally. If you are using with `react-native-draggable-flatlist` and the list is periodically not scrolling, try adding a small `activationDistance` (see the "Advanced" screen in the example snack).
### Example
https://snack.expo.io/@computerjazz/swipeable-item
```typescript
import React, { useCallback } from "react";
import {
Text,
View,
StyleSheet,
TouchableOpacity,
FlatList,
ListRenderItem,
} from "react-native";
import SwipeableItem, {
useSwipeableItemParams,
} from "react-native-swipeable-item";const NUM_ITEMS = 10;
function SimpleExample() {
const renderItem: ListRenderItem = useCallback(({ item }) => {
return (
}
snapPointsLeft={[150]}
>
{`${item.text}`}
);
}, []);return (
item.key}
data={initialData}
renderItem={renderItem}
/>
);
}export default SimpleExample;
const UnderlayLeft = () => {
const { close } = useSwipeableItemParams();
return (
close()}>
CLOSE
);
};type Item = {
key: string;
text: string;
backgroundColor: string;
};function getColor(i: number) {
const multiplier = 255 / (NUM_ITEMS - 1);
const colorVal = i * multiplier;
return `rgb(${colorVal}, ${Math.abs(128 - colorVal)}, ${255 - colorVal})`;
}const initialData: Item[] = [...Array(NUM_ITEMS)].fill(0).map((d, index) => {
const backgroundColor = getColor(index);
return {
text: `${index}`,
key: `key-${backgroundColor}`,
backgroundColor,
};
});const styles = StyleSheet.create({
container: {
flex: 1,
},
row: {
flexDirection: "row",
flex: 1,
alignItems: "center",
justifyContent: "center",
padding: 15,
},
text: {
fontWeight: "bold",
color: "white",
fontSize: 32,
},
underlayLeft: {
flex: 1,
backgroundColor: "tomato",
justifyContent: "flex-end",
},
});
```