🚀 Big News: Socket Acquires Coana to Bring Reachability Analysis to Every Appsec Team.Learn more
Socket
DemoInstallSign in
Socket

react-native-swipeable-item

Package Overview
Dependencies
Maintainers
1
Versions
35
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

react-native-swipeable-item

A horizontally swipeable flatlist row compatible with react-native-draggable-flatlist

1.2.0
Source
npm
Version published
Weekly downloads
3.2K
-26%
Maintainers
1
Weekly downloads
 
Created
Source

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

  • Follow installation instructions for reanimated and react-native-gesture-handler
  • npm install or yarn add react-native-swipeable-item
  • 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 with width underlayWidthLeft. Not perfect but it works.

type RenderUnderlay = (params: {
  item: T;
  percentOpen: Animated.Node<number>;
  open: () => Promise<void>;
  close: () => Promise<void>;
}) => React.ReactNode;
NameTypeDescription
renderUnderlayLeftRenderUnderlayComponent to be rendered underneath row on left swipe.
renderUnderlayRightRenderUnderlayComponent to be rendered underneath row on left swipe.
underlayWidthLeftnumberWidth of left-swiped underlay.
underlayWidthRightnumberWidth of left-swiped underlay.
onChange(params: { open: "left" | "right" | "null" }) => voidCalled when row is opened or closed.
swipeEnabledbooleanEnable/disable swipe. Defaults to true.
activationThresholdnumberDistance finger must travel before swipe engages. Defaults to 20.

Instance Methods

NameTypeDescription
open("left" | "right") => Promise<void>Programmatically open left or right. Promise resolves once open.
close() => Promise<void>Close all. Promise resolves once closed.
// Programmatic open example
const itemRef: SwipeableItem | null = null

...

<SwipeableItem ref={ref => itemRef = ref} />

...
if (itemRef) itemRef.open("left")

Example

import React from "react";
import {
  Text,
  View,
  StyleSheet,
  FlatList,
  LayoutAnimation,
  TouchableOpacity
} from "react-native";
import Animated from "react-native-reanimated";
import SwipeableItem from "react-native-swipeable-item";
import DraggableFlatList from "react-native-draggable-flatlist";
const { multiply, sub } = Animated;

const NUM_ITEMS = 10;
function getColor(i) {
  const multiplier = 255 / (NUM_ITEMS - 1);
  const colorVal = i * multiplier;
  return `rgb(${colorVal}, ${Math.abs(128 - colorVal)}, ${255 - colorVal})`;
}

const initialData = [...Array(NUM_ITEMS)].fill(0).map((d, index) => ({
  text: `Row ${index}`,
  key: `key-${index}`, // Note: It's bad practice to use index as your key. Don't do it in production!
  backgroundColor: getColor(index)
}));

class App extends React.Component {
  state = {
    data: initialData
  };

  itemRefs = new Map();

  deleteItem = item => {
    const updatedData = this.state.data.filter(d => d !== item);
    // Animate list to close gap when item is deleted
    LayoutAnimation.configureNext(LayoutAnimation.Presets.spring);
    this.setState({ data: updatedData });
  };

  renderUnderlayLeft = ({ item, percentOpen }) => (
    <Animated.View
      style={[styles.row, styles.underlayLeft, { opacity: percentOpen }]} // Fade in on open
    >
      <TouchableOpacity onPressOut={() => this.deleteItem(item)}>
        <Text style={styles.text}>{`[x]`}</Text>
      </TouchableOpacity>
    </Animated.View>
  );

  renderUnderlayRight = ({ item, percentOpen, close }) => (
    <Animated.View
      style={[
        styles.row,
        styles.underlayRight,
        {
          transform: [{ translateX: multiply(sub(1, percentOpen), -100) }] // Translate from left on open
        }
      ]}
    >
      <TouchableOpacity onPressOut={close}>
        <Text style={styles.text}>CLOSE</Text>
      </TouchableOpacity>
    </Animated.View>
  );

  renderItem = ({ item, index, drag }) => {
    return (
      <SwipeableItem
        key={item.key}
        item={item}
        ref={ref => {
          if (ref && !this.itemRefs.get(item.key)) {
            this.itemRefs.set(item.key, ref);
          }
        }}
        onChange={({ open }) => {
          if (open) {
            // Close all other open items
            [...this.itemRefs.entries()].forEach(([key, ref]) => {
              if (key !== item.key && ref) ref.close();
            });
          }
        }}
        overSwipe={1000}
        renderUnderlayLeft={this.renderUnderlayLeft}
        underlayWidthLeft={100}
        renderUnderlayRight={this.renderUnderlayRight}
        underlayWidthRight={200}
      >
        <View style={[styles.row, { backgroundColor: item.backgroundColor }]}>
          <TouchableOpacity onLongPress={drag}>
            <Text style={styles.text}>{item.text}</Text>
          </TouchableOpacity>
        </View>
      </SwipeableItem>
    );
  };

  render() {
    return (
      <View style={styles.container}>
        <DraggableFlatList
          keyExtractor={item => item.key}
          data={this.state.data}
          renderItem={this.renderItem}
          onDragEnd={({ data }) => this.setState({ data })}
        />
      </View>
    );
  }
}

export default App;

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
  },
  underlayRight: {
    flex: 1,
    backgroundColor: "teal",
    justifyContent: "flex-start"
  },
  underlayLeft: {
    flex: 1,
    backgroundColor: "tomato",
    justifyContent: "flex-end"
  }
});

Keywords

flatlist

FAQs

Package last updated on 01 Feb 2020

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts