Giter VIP home page Giter VIP logo

react-native-swipeable-item's Introduction

React Native Swipeable Item

A swipeable component with underlay for React Native.
Fully native interactions powered by Reanimated and React Native Gesture Handler

Compatible with React Native Draggable Flatlist

Swipeable Item demo

Install

  1. Follow installation instructions for reanimated and 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<T> & { open: OpenPromiseFn, percentOpen: Animated.DerivedValue<number> } 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).
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 <TouchableOpacity onPress={swipeableItemParams.open} />;
}

function MyOverlayComponent() {
  // Overlay components get the same params, but have defaults filled in for `open()` and `percentOpen` params.
  const swipeableItemParams = useSwipeableItemParams();
  return <TouchableOpacity onPress={swipeableItemParams.openLeft} />;
}

Instance Methods

Name Type Description
open (OpenDirection.LEFT | OpenDirection.RIGHT, snapIndex?: number, options?: { animated: boolean }) => Promise<void> Imperatively open left or right. Promise resolves once open.
close (options?: { animated?: boolean}) => Promise<void> Close all. Promise resolves once closed.
// Imperative open example
const itemRef = useRef<SwipeableItemImperativeRef>(null)

...

<SwipeableItem ref={itemRef} />

...
itemRef.current?.open(OpenDirection.LEFT)

Types

type OpenCloseOptions = { animated?: boolean };
type OpenPromiseFn = (
  snapPoint?: number,
  options?: OpenCloseOptions
) => Promise<void>;
type ClosePromiseFn = (options?: OpenCloseOptions) => Promise<void>;

export type UnderlayParams<T> = {
  item: T;
  open: OpenPromiseFn;
  close: ClosePromiseFn;
  percentOpen: Animated.DerivedValue<number>;
  isGestureActive: Animated.DerivedValue<boolean>;
  direction: OpenDirection;
};

export type OverlayParams<T> = {
  item: T;
  openLeft: OpenPromiseFn;
  openRight: OpenPromiseFn;
  close: ClosePromiseFn;
  openDirection: OpenDirection;
  percentOpenLeft: Animated.DerivedValue<number>;
  percentOpenRight: Animated.DerivedValue<number>;
};

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

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<Item> = useCallback(({ item }) => {
    return (
      <SwipeableItem
        key={item.key}
        item={item}
        renderUnderlayLeft={() => <UnderlayLeft />}
        snapPointsLeft={[150]}
      >
        <View
          style={[
            styles.row,
            { backgroundColor: item.backgroundColor, height: 100 },
          ]}
        >
          <Text style={styles.text}>{`${item.text}`}</Text>
        </View>
      </SwipeableItem>
    );
  }, []);

  return (
    <View style={styles.container}>
      <FlatList
        keyExtractor={(item) => item.key}
        data={initialData}
        renderItem={renderItem}
      />
    </View>
  );
}

export default SimpleExample;

const UnderlayLeft = () => {
  const { close } = useSwipeableItemParams<Item>();
  return (
    <View style={[styles.row, styles.underlayLeft]}>
      <TouchableOpacity onPress={() => close()}>
        <Text style={styles.text}>CLOSE</Text>
      </TouchableOpacity>
    </View>
  );
};

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",
  },
});

react-native-swipeable-item's People

Contributors

adamhake avatar bang9 avatar computerjazz avatar dependabot[bot] avatar goleary avatar guhungry avatar igorskugar avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

react-native-swipeable-item's Issues

SwipeItem suggestions

Just copy-pasting this from the other thread:

  • Support for swiping in both directions; currently your package only supports swiping left or right. Correct me if I'm wrong though.

  • A parameter for allowing swiping all the way but if the user lets go, it'll snap back and stay open depending on the underlayWidth value.

  • A function to programmatically close rows. For example, if I interact with another row I want to be able to call a closeRow() function on the other rows.

  • A callback to keep track of the X value that is being animated for each row. Stemming off my 2nd suggestion, I'd like to be able to keep track of how far the user has swiped, and if it has passed a certain X value then I would remove the row from the list.

Thanks again for doing this.

When scrolling it triggers onChange

Describe the bug
I wanted to map two functions to swipe "left" and swipe "0"
However, when scrolling list of swipable items, onChange gets triggered as well and shows snapPoint: 0.

Steps to reproduce the behavior:

  • Have a scroll view of swipable items
  • log object passed from onChange
  • you will see same output for:
    --- swiping from child to parent
    --- scrolling the list

Platform & Dependencies
Android emulator

Platform (iOS/Android):
React Native or Expo version: 0.61.5
react-native-reanimated version: 1.8.0
react-native-gesture-handler version: ^1.4.1

Production demo

@computerjazz We launched to production this week and users are very happy. Thanks so much again for this library!

Here's a gif demonstrating our use of the library. Feel free to add to README if you want a product demo there.

Reanimated get value error

Hi, thank you for building this great package. Im working with the React Native Draggable FlatList in conjunction with React Native Swipeable Item for IOS. I ran the React Native Draggable FlatList without the swappable item and this didn't occur.

Describe the bug
What I'm encountering is when running the example in the readme of React Native Swipeable Item The first initial boot is fine but then on subsequence saves or re render the following happens.

Warning: Please report: Excessive number of pending callbacks: 501. Some pending callbacks that might have leaked by never being called from native code: {"15183":{"module":"ReanimatedModule","method":"getValue"},"15186":{"module":"ReanimatedModule","method":"getValue"},"15203":{"module":"ReanimatedModule","method":"getValue"},"15221":{"module":"ReanimatedModule","method":"getValue"},"15240":{"module":"ReanimatedModule","method":"getValue"},"15259":{"module":"ReanimatedModule","method":"getValue"},"15286":{"module":"ReanimatedModule","method":"getValue"},"15320":{"module":"ReanimatedModule","method":"getValue"},"15323":{"module":"ReanimatedModule","method":"getValue"},"15326":{"module":"ReanimatedModule","method":"getValue"},"15329":{"module":"ReanimatedModule","method":"getValue"},"15332":{"module":"ReanimatedModule","method":"getValue"},"15335":{"module":"ReanimatedModule","method":"getValue"},"15338":{"module":"ReanimatedModule","method":"getValue"},"15341":{"module":"ReanimatedModule","method":"getValue"},"15360":{"module":"ReanimatedModule","method":"getValue"},"15363":{"module":"ReanimatedModule","method":"getValue"},"15366":{"module":"ReanimatedModule","method":"getValue"},"15369":{"module":"ReanimatedModule","method":"getValue"},"15372":{"module":"ReanimatedModule","method":"getValue"},"15375":{"module":"ReanimatedModule","method":"getValue"},"15436":{"module":"ReanimatedModule","method":"getValue"},"15474":{"module":"ReanimatedModule","method":"getValue"},"15480":{"module":"ReanimatedModule","method":"getValue"},"15483":{"module":"ReanimatedModule","method":"getValue"},"15490":{"module":"ReanimatedModule","method":"getValue"},"15498":{"module":"ReanimatedModule","method":"getValue"},"15509":{},"15523":{"module":"ReanimatedModule","method":"getValue"},"15541":{},"15560":{"module":"ReanimatedModule","method":"getValue"},"15573":{"module":"ReanimatedModule","method":"getValue"},"15594":{"module":"ReanimatedModule","method":"getValue"},"15603":{"module":"ReanimatedModule","method":"getValue"},"15631":{"module":"ReanimatedModule","method":"getValue"},"15639":{"module":"ReanimatedModule","method":"getValue"},"15656":{},"15674":{"module":"ReanimatedModule","method":"getValue"},"15684":{"module":"ReanimatedModule","method":"getValue"},"15688":{"module":"ReanimatedModule","method":"getValue"},"15691":{"module":"ReanimatedModule","method":"getValue"},"15694":{"module":"ReanimatedModule","method":"getValue"},"15713":{"module":"ReanimatedModule","method":"getValue"},"15724":{"module":"ReanimatedModule","method":"getValue"},"15728":{"module":"ReanimatedModule","method":"getValue"},"15734":{"module":"ReanimatedModule","method":"getValue"},"15738":{"module":"ReanimatedModule","method":"getValue"},"15744":{"module":"ReanimatedModule","method":"getValue"},"15748":{"module":"ReanimatedModule","method":"getValue"},"15755":{"module":"ReanimatedModule","method":"getValue"},"...(truncated keys)...":451}

A clear and concise description of what the bug is.

Steps to reproduce the behavior:
To reproduce this just copy and paste the code from the readme example.
Run the code and then upon additional save (re render) the error will appear.

Platform & Dependencies
Please list any applicable dependencies in addition to those below (react-navigation etc).
"@react-navigation/drawer": "^5.8.5",
"@react-navigation/native": "^5.7.0",
"@react-navigation/stack": "^5.7.0",

Platform (iOS/Android):
React Native or Expo version: React native "^0.63.1"
react-native-reanimated version: "^1.10.1",
react-native-gesture-handler version: "^1.7.0",

Additional context

Readme Example code

Hello, @computerjazz

I am trying to implement swipeableItem with draggable flatlist.

I have seen the code in the example in README, but seems like it is not the example code from the demo gif below:

Swipeable Item demo

Where can I find the code for demo in gif? I would like to implement swipe gesture like in demo gif(which can be swiped using gesture instead of clicking button to open left or right in example code), which is different from the example code (currently doesn't swipe with gesture).

Thanks!

Unable to swipe consistently

First of all, THANK YOU! I've been looking for a way to have swipeable, pressable, reorderable lists since 2016 and this with DraggableFlatList is the closest I've come.

When I run the example in the ios simulator, I'm not able to swipe. When I swipe outside the text, nothing happens. When I try to swipe within the text, the TouchableOpacity lightens the text but I can't swipe. Long press + drag and drop works fine!

Interestingly, if I press alt, then I can consistently swipe two rows at once (in opposite directions).

I'm currently unable to test on an iphone due to USB port troubles. I ran on an Android physical device (release build) and had similar problems. I'm able to get it to swipe perhaps 1 time in 10 (oneplus 6).

I tried updating as much as I could to the latest versions on iOS:

Package Version
react-native 0.59.10
draggable-flatlist 2.1.2
swipeable-item 1.1.1
reanimated 1.7.0
gesture-handler 1.5.3

The Android versions I'm testing are a bit older since I haven't upgraded to androidx yet:

Package Version
react-native 0.59.10
draggable-flatlist 2.1.2
swipeable-item 1.1.1
reanimated 1.2.0
gesture-handler 1.2.1

I see from the github README that you're indeed able to swipe from the ios simulator. Are you on RN 0.61? I will try upgrading to 0.61 next. Which versions of draggable-flatlist, reanimated, and gesture-handler are you using?

Can't swipe or drag and drop with TextInput

Describe the bug
Can't swipe or drag on a button with TextInput as children.

Steps to reproduce the behavior:
Follow the instruction on this repo but have a TextInput instead of Text component.

Function trigger with overswipe

Hi,

first of all, your package is awesome, but i have a question. Is there any option, for example to trigger a deletefunction with overswipe. I use the draggable flatlist and i need full swipe delete and delete to tap.

Thank for answer.
Regards, Daniel

Package does not support [email protected]

Describe the bug
This package results in TS errors when used with [email protected].

When I pin react-native-reanimated to 2.2.x things work as expected.

Steps to reproduce the behavior:

  • install latest version of this package with dependencies
  • run tsc (may require imporing of the package)

Platform & Dependencies
Please list any applicable dependencies in addition to those below (react-navigation etc).

Platform (iOS/Android): iOS
React Native or Expo version: 0.66.0
react-native-reanimated version: 2.3.1
react-native-gesture-handler version: 2.1.0

Additional context

These are the errors we see

node_modules/react-native-swipeable-item/src/index.tsx:74:38 - error TS2694: Namespace 'Animated' has no exported member 'WithSpringConfig'.

74   animationConfig?: Partial<Animated.WithSpringConfig>;
                                        ~~~~~~~~~~~~~~~~

node_modules/react-native-swipeable-item/src/index.tsx:107:32 - error TS2694: Namespace 'Animated' has no exported member 'WithSpringConfig'.

107   const springConfig: Animated.WithSpringConfig = {
                                   ~~~~~~~~~~~~~~~~

node_modules/react-native-swipeable-item/src/index.tsx:189:45 - error TS2345: Argument of type 'boolean | undefined' is not assignable to parameter of type 'boolean'.
  Type 'undefined' is not assignable to type 'boolean'.

189           runOnJS(resolvePromiseIfFinished)(isFinished);
                                                ~~~~~~~~~~

node_modules/react-native-swipeable-item/src/index.tsx:203:45 - error TS2345: Argument of type 'boolean | undefined' is not assignable to parameter of type 'boolean'.

203           runOnJS(resolvePromiseIfFinished)(isFinished);
                                                ~~~~~~~~~~

node_modules/react-native-swipeable-item/src/index.tsx:215:43 - error TS2345: Argument of type 'boolean | undefined' is not assignable to parameter of type 'boolean'.

215         runOnJS(resolvePromiseIfFinished)(isFinished);
                                              ~~~~~~~~~~

Generic type not passed to SwipeableItem props

Describe the bug
I have a component that returns a SwipeableItem (example shown below):

function myComponent({item :Item}) => {
  ...
  const renderRemove : RenderUnderlay<Item> = (params: UnderlayParams<Item>) => {
    return (...);
  })

  return (
    <SwipeableItem
      key={id}
      item={item}
      ref={ref => { swipeRef = ref }}
      snapPointsLeft={[90]}
      renderUnderlayLeft={renderRemove}
      overSwipe={20}
    >
    ...
    </SwipeableItem>
  )
}

I would expect the renderUnderlayLeft prop to be of type RenderUnderlay<Item>, but instead, it's RenderUnderlay<unknown>. This causes the following TS error:

Type 'RenderUnderlay<Item>' is not assignable to type 'RenderUnderlay<unknown>'.
Type 'unknown' is not assignable to type 'Item'.

The Item type is getting changed to unknown, or in other words, the generic type T isn't making it to the SwipeableItem props. This seems to be an issue with how to deal with generics in React.forwardRef.

I'm attaching a PR to this issue shortly that I think addresses the issue by type asserting the React.forwardRef function.

Thanks for the great work on this project!

Example causes CPU to go to max

Hey y'all. Really appreciate these libraries!

I've been trying to get the example to work but unfortunately when I run it it causes the CPU to go to 200% in the simulator. To try to isolate the issue I've created a brand new expo project and copied the example, but it still causes the CPU to spike after swiping the first item.

I've included the project.json and a video showing the behavior below.

Any guidance on how to understand what's happening here? Thanks

Package.json

{
  "name": "test-proj",
  "version": "1.0.0",
  "main": "node_modules/expo/AppEntry.js",
  "scripts": {
    "start": "expo start",
    "android": "expo start --android",
    "ios": "expo start --ios",
    "web": "expo start --web"
  },
  "dependencies": {
    "expo": "~46.0.6",
    "expo-status-bar": "~1.4.0",
    "react": "18.0.0",
    "react-dom": "18.0.0",
    "react-native": "0.69.4",
    "react-native-draggable-flatlist": "^3.1.2",
    "react-native-gesture-handler": "~2.5.0",
    "react-native-reanimated": "^2.9.1",
    "react-native-swipeable-item": "^2.0.7",
    "react-native-web": "~0.18.7"
  },
  "devDependencies": {
    "@babel/core": "^7.12.9",
    "@types/react": "~18.0.14",
    "@types/react-native": "~0.69.1",
    "typescript": "~4.3.5"
  },
  "private": true
}

Video

Simulator.Screen.Recording.-.iPhone.13.-.2022-08-12.at.13.08.50.mp4

onPress not working

Describe the bug

I am not able to use onPress inside my SwipeableItem overlays. I started with the demo list from the README and added a onPress in addition to the onLongPress, but it's never called.

Steps to reproduce the behavior:

Here's a demo project. Long pressing to reorder works. But when you do a regular press it should change all the item texts to "An item was pressed". Instead nothing happens.

Platform & Dependencies
None in the demo project.

Platform (iOS/Android):
React Native or Expo version: 0.61.5
react-native-reanimated version: 1.7.0
react-native-gesture-handler version: 1.5.6

Additional context

This is important functionality since you might want to show a new list when tapping, edit the item, etc. So primary action would be through tapping and secondary action(s) through swipes. My first idea for a workaround is to make a new component that extends TouchableOpacity or TouchableWithoutFeedback and uses onPressIn and onPressOut with some timers (although I would have guessed that's exactly how TouchableWithoutFeedback is implemented). Or maybe to just act on onPressOut (if onDragBegin was never called). Have to investigate which events are called and when.

Do you have any idea why it's not working? Seems like it might be nice to document this if a workaround is possible. And if a workaround is possible then it would make sense to me to integrate it into the library and add onPress and onLongPress directly to the SwipeableItem.

SwipeableItem consistently gets stuck between snap points

Describe the bug
When I swipe quickly I am consistently able to get the item into a state where it is stuck at a point not specified in snapPoints

Android
image
iOS
image

Steps to reproduce the behavior:
It's easy to see what I'm talking about using this expo snack.

Platform & Dependencies
Please list any applicable dependencies in addition to those below (react-navigation etc).

Platform (iOS/Android): Both
React Native or Expo version: expo 40, react native 0.63.2
react-native-reanimated version: 1.13.0
react-native-gesture-handler version: 1.9.0

This has also been experienced on device for iOS & Android.

Added extra onPress is always invoked

First of all everything works as expected. Hence, this is not really a bug report.

In my instance I use react-native-swipeable-item together with react-native-draggable-flatlist but the Row would have an additional TouchableOpacity something like that

<SwipeableItem
  key={item.key}
   ...
  snapPointsLeft={[150]}
  snapPointsRight={[175]}>
  <View
    style={[styles.row, { backgroundColor: item.backgroundColor, height: item.height }]}>
    {/* this is the drag handler for reordering */}
    <TouchableOpacity onLongPress={drag}>
      <Text style={styles.text}>...</Text>
    </TouchableOpacity>
    {/* this is the clickable main row that will open an edit modal to edit the row data*/}
    <TouchableOpacity onPress={() => {
      console.log('row pressed')
      openModal()
    }>
      <Text style={styles.text}>The main row</Text>
    </TouchableOpacity>
  </View>
</SwipeableItem>

The setup is like the Google mail app, only that one can't reorder the items. In the Google mail app one can swipe left or right or click on the row to see the content of the mail.

I would like the same outcome but once I begin to swipe the onPress of the main row gets invoked before the onChange event. It would look like that if I log out the value of the onChange event.

LOG      row pressed
LOG      left
LOG      left
LOG      right
LOG      0

Is there a way to accomplish this? SwipeableItem would need an extra event that get's invoked as soon as the swipe starts so the onPress of 2nd TouchableOpacity can be disabled, right?

Animated: 'useNativeDriver' was not specified

Hello. Thank you for you amazing work. Everything work fine, except a warning as I mentioned in the title. On every swipe I have warning: Animated: useNativeDriver was not specified. This is a required 'option and must be explicitly set to true or false

Swipeable-item not swiping but draggable flatlist works

I already solved my problem, posting here in case anyone encounters the same thing. I had react-native-draggable-flatlist working correctly but react-native-swipeable-item wasn't swiping at all.

Turns out my babel plugins were misordered, solution was to ensure react-native-reanimated/plugin is always at the end of the plugins list.

  api.cache(true);
  return {
    presets: ['babel-preset-expo'],
    plugins: [
      ...,
      'react-native-reanimated/plugin',
    ],
  };
};

Uncaught TypeError: Cannot read properties of undefined (reading 'previousStyle') when experimenting readme example

This package has external dependencies of react-native-reanimated and react-native-gesture-handler which must be installed separately. Before opening an issue related to animations or gestures please verify that you have completed ALL installation steps, including the changes to MainActivity.

Describe the bug
When experimenting with the readme example and after swiping any list item, I got the error "Uncaught TypeError: Cannot read properties of undefined (reading 'previousStyle')".
After that, the browser almost froze during this weird error.

Steps to reproduce the behavior:

Just try the readme example.

Platform & Dependencies
Please list any applicable dependencies in addition to those below (react-navigation etc).

Not applied?

Platform (iOS/Android):
React Native or Expo version: Expo v43.0.3
react-native-reanimated version: 2.2.4
react-native-gesture-handler version: 1.10.3

Additional context

The error was raised when testing the example on the web browser (using react-native-web).

Improve README

As a new developer to react-native-swipable-item I find the readme confusing and hard to follow.

I'm creating this Issue so we can track improvements to the Readme.

My issues so far are:

  1. The example is crazy complex. We need a simpler JS example, and without types. I'm a seasoned JS and TS developer myself but that demo is mind boggling.
  2. The order of items is confusing too, Install and then a list of Prop Typings (which makes no sense to me as a newcomer).

Hopefully I can contribute some of these improvements myself (if I can figure out how to use the package!).

Thanks for the great work and great (looking) module.

Freeze some elements from dragging

Is it possible to allow drag of few elements
say I have draggableFlatList from 1-10
I want to drag first 5 elements and remaining elements must be non-draggable.

Is it possible?

Changing `snapPointsLeft` does not re-render `SwipableItem`

Describe the bug

Assigning snapPointsLeft from a useState variable only uses the initial value. Changing it does nothing..

Steps to reproduce the behavior:

For our multi-language app we calculate the width of "Delete" in the user's language on first layout, then set a state variable.

const [deleteButtonWidth, setDeleteButtonWidth] = useState(calculatedDeleteButtonWidth);

<Text
  onLayout={(layoutEvent: LayoutChangeEvent) => {
    const { width } = layoutEvent.nativeEvent.layout;
    const textWidth = Math.round(width);
    // The first underlay that is rendered updates the state: (otherwise CPU goes brrrr)
    if (textWidth !== deleteButtonWidth) {
      setDeleteButtonWidth((calculatedDeleteButtonWidth = textWidth));
    }
  }}>
  {t('i18n.message')}
</Text>

Which is used by SwipableItem to set snapPointsLeft:

function renderAction(actionItem) {
  return (
    <SwipeableItem
      // Enable swiping only when deleteTextWidth has been calculated
      swipeEnabled={deleteButtonWidth != 0}
      renderUnderlayLeft={renderUnderlayLeft}
      snapPointsLeft={[deleteButtonWidth + 24]}
      renderOverlay={renderActionOverlay}
    />
  );
}

However, the snap point is not updated unless we resort to a workaround that forcibly re-renders the entire (long) list. The workaround is changing key:

<DraggableFlatList
  // The key acts as a trigger to re-render the list when deleteTextWidth changes.
  // Without it, the SwipableItem underlays do not change size.
  // This is probably a bug in how `snapPointsLeft` is handled.
  key={deleteButtonWidth}
  renderItem={renderAction}
  ...

Platform & Dependencies**

Platform: iOS & Android
React Native or Expo version: Expo 41
react-native-reanimated version: 2.1.0
react-native-gesture-handler version: 1.10.3

New release with latest PR merges

I see some very helpful merges after the last tag (Feb).
Is it possible that a new tag - including the latest changes - will be created?

Can't press buttons during the swiping

Describe the bug
It's not possible to press elements during the swiping. We have two buttons on the right side. When I swipe to the left, I can press them after the swiping process stops (+ need to wait for ~ 100 ms after a stop).

Steps to reproduce the behavior:
Swipe and try to press any elements that have onPress handlers. Handlers will not be triggered.

Platform & Dependencies
Please list any applicable dependencies in addition to those below (react-navigation etc).

Platform (iOS):
React Native: 0.67.4
react-native-reanimated version: 2.2.4
react-native-gesture-handler version: 2.1.0

Here is an example https://snack.expo.dev/@moro/swipeable-draggable-list
If you swipe and press delete it will not trigger the action, you need to wait until the swiping stops.

Types incompatible with reanimated 3.2

Describe the bug
Getting this type error when running yarn tsc --noEmit

node_modules/react-native-swipeable-item/src/index.tsx:117:9 - error TS2322: Type '{ stiffness: number; overshootClamping: boolean; restSpeedThreshold: number; restDisplacementThreshold: number; velocity?: number | undefined; mass: number; damping: number; duration?: undefined; dampingRatio?: undefined; } | { ...; }' is not assignable to type 'WithSpringConfig'.
  Type '{ stiffness: number; overshootClamping: boolean; restSpeedThreshold: number; restDisplacementThreshold: number; velocity?: number | undefined; mass: number; damping: number; duration?: number | undefined; dampingRatio?: number | undefined; }' is not assignable to type 'WithSpringConfig'.
    Type '{ stiffness: number; overshootClamping: boolean; restSpeedThreshold: number; restDisplacementThreshold: number; velocity?: number | undefined; mass: number; damping: number; duration?: number | undefined; dampingRatio?: number | undefined; }' is not assignable to type '{ stiffness?: number | undefined; overshootClamping?: boolean | undefined; restSpeedThreshold?: number | undefined; restDisplacementThreshold?: number | undefined; velocity?: number | undefined; } & { ...; }'.
      Type '{ stiffness: number; overshootClamping: boolean; restSpeedThreshold: number; restDisplacementThreshold: number; velocity?: number | undefined; mass: number; damping: number; duration?: number | undefined; dampingRatio?: number | undefined; }' is not assignable to type '{ mass?: undefined; damping?: undefined; duration?: number | undefined; dampingRatio?: number | undefined; }'.
        Types of property 'mass' are incompatible.
          Type 'number' is not assignable to type 'undefined'.

117   const springConfig: WithSpringConfig = {
            ~~~~~~~~~~~~

Found 1 error in node_modules/react-native-swipeable-item/src/index.tsx:117

Platform & Dependencies
Please list any applicable dependencies in addition to those below (react-navigation etc).

Platform (iOS/Android):
React Native or Expo version: 0.71
react-native-reanimated version: 3.2.0
react-native-gesture-handler version: 2.11.0

Please support `react-native-reanimated` 2

Describe the problem

Please support react-native-reanimated 2.
Also please update peer dependency react-native to 0.65 (or >=0.60 etc.).

Platform & Dependencies

Platform (iOS/Android): Android
React Native or Expo version: 0.65.1
react-native-reanimated version: 2.2.0
react-native-gesture-handler version: 1.10.3

Calling %s on the ref of an Animated component is no longer necessary. You can now directly use the ref instead. This method will be removed in a future release. e getNode()

Describe the bug
Hi @computerjazz ,

I am receiving the following notice:

%s: Calling %s on the ref of an Animated component is no longer necessary. You can now directly use the ref instead. This method will be removed in a future release. e getNode()

Link: https://snack.expo.io/tmKuyAZBM

Platform & Dependencies

Platform (iOS/Android):
React Native or Expo version: expo 41
react-native-reanimated version: ~2.1.0

Trying to get it to work with Reanimated

Hi there.

I'm trying to get the underlay opacity to increase in proportion to percentOpen.
Am getting this error and am struggling to figure out why:
image

Am using it with react-native-draggable-flatlist like this:

  const DeleteUnderlay = () => {
    const { percentOpen } = useSwipeableItemParams<PlayerSet>()
    const animatedStyle = useAnimatedStyle(
      () => ({
        opacity: percentOpen.value,
      }),
      [percentOpen],
    )

    useEffect(() => {
      console.log('swipeableItemParams.percentOpen :>> ', percentOpen.value)
    }, [percentOpen.value])

    return (
      <XStack style={[styles.underlayLeft, animatedStyle]}>
        <TouchableOpacity
          onPress={() => {
            console.log('onPress called')
          }}
        />
      </XStack>
    )
  }
  const renderItem = useCallback(
  ({ item, drag }: RenderItemParams<PlayerSet>) => (
    <SwipeableItem
      activationThreshold={DELETE_ACTIVATION_THRESHOLD}
      item={item}
      key={item.id}
      renderUnderlayLeft={() => <DeleteUnderlay />}
      snapPointsLeft={DELETE_SNAP_POINTS}
      swipeDamping={DELETE_SWIPE_DAMPING}
    >
      {/* <ShadowDecorator> */}
      <SetCardItem
        artists={item.artists}
        artwork={item.artwork}
        assetId={item.id}
        closePopup={() => {}}
        drag={drag}
        duration={item.duration}
        isPopupOpen={false}
        key={item.id}
        listeningDuration={item.listeningDuration}
        openPopup={() => {}}
        ratingCount={item.ratingCount}
        ratingType={item.ratingType}
        setTitle={item.title}
      />
      {/* </ShadowDecorator> */}
    </SwipeableItem>
  ),
  [],
)

Help/insight would be much appreciated ๐Ÿ™

Swipe not working with latest version of Expo

Describe the bug
On latest version of Expo (SDK 45), the swipe works only intermittently (the FlatList dragging works great). Sometimes it swipes, sometimes it doesn't. Sometimes it takes a few times to swipe a row, but sometimes it doesn't work at all.

Steps to reproduce the behavior:
I copied the example code from the readme. I even removed the animation on the underlay and replaced it with a basic View, but couldn't get it to work

Platform & Dependencies
IOS
react-navigation/native version: 6.0.10
react-navigation/stack version: 6.2.1

Platform (iOS/Android):
expo version: 45.0.4
react-native-reanimated version: 2.8.0
react-native-gesture-handler version: 2.2.1

Additional context
I couldn't get this to work in a basic managed app in Expo Go, nor in an internal development eas build.

Probably not related, but trying to run the Example snack crashes the current version of Expo Go (2.24.3).

Add custom props to RowItem

Describe the bug
This is not a bug, it's an issue I don't know how to solve, so I thought maybe the author of this great package would know the solution.

I'm usig the SwipableItem in DraggableFlatList. I did everything according to the demo, everything works as it should. I'm able to swipe and drag. However, I want to add a custom onPress function to the list item, so I can navigate to the next screen when I press the list item. (I'm using react-navigation). For this to work, I need to pass a navigation prop to the RowItem component, but I couldn't figure out how. The TypeScript restrictions will not let me add an onPress or navigation prop. Is there a way I can pass this prop to the RowItem so I can use it in SwipeableItem?

I tried wrapping the RowItem in TouchableOpacity like shown below, so I can call the onPress event on the TouchableOpacity, but it didn't recognize the touch on the TouchableOpacity component. The SwipeableItem kept working as it should, but the onPress event on the TouchableOpacity wasn't called.

const renderItem = useCallback((params: RenderItemParams<Item>) => {
    return (
    <TouchableOpacity onPressIn={() => console.log('pressin')} onPress={() => console.log('press')}>
      <RowItem {...params} itemRefs={itemRefs} />
    </TouchableOpacity>)
  }, []);
// no console logs were logged

Steps to reproduce the behavior:
I tried adding an onPress prop to the in renderItem() method. In the demo, it's line 56.

const renderItem = useCallback((params: RenderItemParams<Item>) => {
    return <RowItem {...params} itemRefs={itemRefs} onPress={() => myFunction()}/>
  }, []);
// Property 'onPress' does not exist on type 'IntrinsicAttributes & RowItemProps

Here is my repo.
And the specific file, line 121.

Platform & Dependencies
Platform (iOS/Android): iOS and Android
React Native version: 0.64.3
Expo version: 44.0.6
react-native-reanimated version: 2.3.3
react-native-gesture-handler version: 2.1.3
react-navigation/native version: 6.0.8
react-navigation/native-stack version: 6.5.2

Inconsistent behavior with multiple snap points

Describe the bug
When multiple snap points are given, some snap points have difficulty catching.

Steps to reproduce the behavior:
Reproduction here:
https://snack.expo.io/udWUkcb5K

  1. drag a bit past the first snap point on the right hand side of the page. Observe the first point catch.
  2. drag from the first point to the second. Observe a miss, and catch to the third snap point.
  3. drag from the last snap point to the end of the row, observe the second snap point catch.

Expected behavior:
I would expect that dragging a bit past each snap point would catch the nearest point before it.

Platform & Dependencies
ios, web

Platform (iOS/Android):
React Native or Expo version:
react-native-reanimated version: "~1.13.0"
react-native-gesture-handler version: "~1.8.0"

Feature proposal: full open

One key piece of functionality for my app is to swipe fully open (e.g. lots of todo apps have swipe right to mark done). So this would entail:

  • fullOpenRightThreshold prop, meaning if the user swipe beyond this threshold (perhaps 0.5 means half the row width), then the row will open (i.e. animate all the way to the right). Animation would ideally progress constantly at the speed of the user's swipe, unless this would take more than 80ms or something like that. Special case: if the user swiped beyond the threshold and then changed their mind and swiped back toward the left to cancel.
  • onFullOpenRight callback, called when the row has opened.
  • luxury: renderFullOpenUnderlayRight - as the user approaches the threshold, this fades in over the renderUnderlayRight content.

Any thoughts on this? Will be finishing my D&D work over the next weeks, and can attempt a PR (unless you already have something like this in the works).

Does react-native-swipeable-item play well with react-native-gesture-handler/Swipeable and which one should I start with?

Hello, I am testing your snack in #1 and it seems it doesn't work on the web.

I'd like to know what is this project compare to https://github.com/software-mansion/react-native-gesture-handler/blob/master/docs/component-swipeable.md

Both are very recent examples and I have read this article https://medium.com/p/bd7d66085aee

The react-native-gesture-handler versions seems to be more close to what I'd like to achieve since it also work on the web and as no bounce and better feeling for the user.

I want to have 3 lists:

  • list
    • swipe left to delete after a timeout (or tap to cancel)
    • swipe right to add to favorite after a timeout (or tap to cancel)
  • delete list
    • swipe left to remove from delete list after a timeout (or tap cancel)
    • swipe right to add to favorite and remove from delete list after a timeout (or tap to cancel)
  • bookmark list
    • swipe left to remove from bookmark list after a timeout (or tap cancel)

So far the example in https://github.com/software-mansion/react-native-gesture-handler/blob/master/docs/component-swipeable.md only needs to add the delete feature.

Any idea how I could do and do you have any thought about this?

Platform & Dependencies

I want to build this for iOS, Android and web.

Expo version: SDK 36
react-native-reanimated version: 1.4.0
react-native-gesture-handler version: 1.6.0

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.