{"id":17283670,"url":"https://github.com/computerjazz/react-native-swipeable-item","last_synced_at":"2025-04-13T04:59:22.021Z","repository":{"id":37739850,"uuid":"232038540","full_name":"computerjazz/react-native-swipeable-item","owner":"computerjazz","description":"A swipe-to-reveal wrapper for list items.","archived":false,"fork":false,"pushed_at":"2023-01-27T04:35:59.000Z","size":1404,"stargazers_count":314,"open_issues_count":14,"forks_count":24,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-04-13T04:59:17.615Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/computerjazz.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null},"funding":{"github":["computerjazz"],"patreon":null,"open_collective":null,"ko_fi":null,"tidelift":null,"community_bridge":null,"liberapay":null,"issuehunt":null,"otechie":null,"lfx_crowdfunding":null,"custom":null}},"created_at":"2020-01-06T06:29:09.000Z","updated_at":"2025-04-02T00:16:27.000Z","dependencies_parsed_at":"2023-02-06T11:46:33.123Z","dependency_job_id":null,"html_url":"https://github.com/computerjazz/react-native-swipeable-item","commit_stats":null,"previous_names":[],"tags_count":34,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/computerjazz%2Freact-native-swipeable-item","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/computerjazz%2Freact-native-swipeable-item/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/computerjazz%2Freact-native-swipeable-item/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/computerjazz%2Freact-native-swipeable-item/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/computerjazz","download_url":"https://codeload.github.com/computerjazz/react-native-swipeable-item/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248665758,"owners_count":21142123,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-10-15T09:51:54.602Z","updated_at":"2025-04-13T04:59:21.997Z","avatar_url":"https://github.com/computerjazz.png","language":"TypeScript","funding_links":["https://github.com/sponsors/computerjazz"],"categories":[],"sub_categories":[],"readme":"# React Native Swipeable Item\n\nA swipeable component with underlay for React Native.\u003cbr /\u003e\nFully 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)\n\nCompatible with [React Native Draggable Flatlist](https://github.com/computerjazz/react-native-draggable-flatlist)\n\n![Swipeable Item demo](https://i.imgur.com/fFCnQ0n.gif)\n\n## Install\n\n1. 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)\n2. `npm install` or `yarn add` `react-native-swipeable-item`\n3. `import SwipeableItem from 'react-native-swipeable-item'`\n\n### Props\n\n_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.\n\n| Name                  | Type                                                                    | Description                                                                                                                                                              |\n| :-------------------- | :---------------------------------------------------------------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| `renderUnderlayLeft`  | `RenderUnderlay`                                                        | Component to be rendered underneath row on left swipe.                                                                                                                   |\n| `renderUnderlayRight` | `RenderUnderlay`                                                        | Component to be rendered underneath row on right swipe.                                                                                                                  |\n| `snapPointsLeft`      | `number[]`                                                              | Pixel values left-swipe snaps to (eg. `[100, 300]`)                                                                                                                      |\n| `snapPointsRight`     | `number[]`                                                              | Pixel values right-swipe snaps to (eg. `[100, 300]`)                                                                                                                     |\n| `renderOverlay`       | `RenderOverlay`                                                         | Component to be rendered on top. Use if you need access to programmatic open/close methods. May altenatively pass children to SwipeableItem.                             |\n| `onChange`            | `(params: { openDirection: OpenDirection, snapPoint: number }) =\u003e void` | Called when row is opened or closed.                                                                                                                                     |\n| `swipeEnabled`        | `boolean`                                                               | Enable/disable swipe. Defaults to `true`.                                                                                                                                |\n| `activationThreshold` | `number`                                                                | Distance finger must travel before swipe engages. Defaults to 20.                                                                                                        |\n| `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`. |\n\n### Hooks\n\n| Name                     | Type                                                                                           | Description                                                                                                                                                                                                          |\n| :----------------------- | :--------------------------------------------------------------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| `useSwipeableItemParams` | `() =\u003e OverlayParams\u003cT\u003e \u0026 { open: OpenPromiseFn, percentOpen: Animated.DerivedValue\u003cnumber\u003e }` | 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). |\n|                          |\n\n```tsx\nfunction MyUnderlayComponent() {\n  // Underlay components \"know\" which direction to open, so we don't need to call `openLeft()` or `openRight()`, we can just call 'open()'\n  // Underlay components also receive the `percentOpen` value of their own direction (`percentOpenLeft` or `percentOpenRight`)\n  const swipeableItemParams = useSwipeableItemParams();\n  return \u003cTouchableOpacity onPress={swipeableItemParams.open} /\u003e;\n}\n\nfunction MyOverlayComponent() {\n  // Overlay components get the same params, but have defaults filled in for `open()` and `percentOpen` params.\n  const swipeableItemParams = useSwipeableItemParams();\n  return \u003cTouchableOpacity onPress={swipeableItemParams.openLeft} /\u003e;\n}\n```\n\n### Instance Methods\n\n| Name    | Type                                                                                                                | Description                                                  |\n| :------ | :------------------------------------------------------------------------------------------------------------------ | :----------------------------------------------------------- |\n| `open`  | `(OpenDirection.LEFT \\| OpenDirection.RIGHT, snapIndex?: number, options?: { animated: boolean }) =\u003e Promise\u003cvoid\u003e` | Imperatively open left or right. Promise resolves once open. |\n| `close` | `(options?: { animated?: boolean}) =\u003e Promise\u003cvoid\u003e`                                                                | Close all. Promise resolves once closed.                     |\n\n```tsx\n// Imperative open example\nconst itemRef = useRef\u003cSwipeableItemImperativeRef\u003e(null)\n\n...\n\n\u003cSwipeableItem ref={itemRef} /\u003e\n\n...\nitemRef.current?.open(OpenDirection.LEFT)\n```\n\n### Types\n\n```ts\ntype OpenCloseOptions = { animated?: boolean };\ntype OpenPromiseFn = (\n  snapPoint?: number,\n  options?: OpenCloseOptions\n) =\u003e Promise\u003cvoid\u003e;\ntype ClosePromiseFn = (options?: OpenCloseOptions) =\u003e Promise\u003cvoid\u003e;\n\nexport type UnderlayParams\u003cT\u003e = {\n  item: T;\n  open: OpenPromiseFn;\n  close: ClosePromiseFn;\n  percentOpen: Animated.DerivedValue\u003cnumber\u003e;\n  isGestureActive: Animated.DerivedValue\u003cboolean\u003e;\n  direction: OpenDirection;\n};\n\nexport type OverlayParams\u003cT\u003e = {\n  item: T;\n  openLeft: OpenPromiseFn;\n  openRight: OpenPromiseFn;\n  close: ClosePromiseFn;\n  openDirection: OpenDirection;\n  percentOpenLeft: Animated.DerivedValue\u003cnumber\u003e;\n  percentOpenRight: Animated.DerivedValue\u003cnumber\u003e;\n};\n```\n\n### Notes\n\nGesture 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).\n\n### Example\n\nhttps://snack.expo.io/@computerjazz/swipeable-item\n\n```typescript\nimport React, { useCallback } from \"react\";\nimport {\n  Text,\n  View,\n  StyleSheet,\n  TouchableOpacity,\n  FlatList,\n  ListRenderItem,\n} from \"react-native\";\nimport SwipeableItem, {\n  useSwipeableItemParams,\n} from \"react-native-swipeable-item\";\n\nconst NUM_ITEMS = 10;\n\nfunction SimpleExample() {\n  const renderItem: ListRenderItem\u003cItem\u003e = useCallback(({ item }) =\u003e {\n    return (\n      \u003cSwipeableItem\n        key={item.key}\n        item={item}\n        renderUnderlayLeft={() =\u003e \u003cUnderlayLeft /\u003e}\n        snapPointsLeft={[150]}\n      \u003e\n        \u003cView\n          style={[\n            styles.row,\n            { backgroundColor: item.backgroundColor, height: 100 },\n          ]}\n        \u003e\n          \u003cText style={styles.text}\u003e{`${item.text}`}\u003c/Text\u003e\n        \u003c/View\u003e\n      \u003c/SwipeableItem\u003e\n    );\n  }, []);\n\n  return (\n    \u003cView style={styles.container}\u003e\n      \u003cFlatList\n        keyExtractor={(item) =\u003e item.key}\n        data={initialData}\n        renderItem={renderItem}\n      /\u003e\n    \u003c/View\u003e\n  );\n}\n\nexport default SimpleExample;\n\nconst UnderlayLeft = () =\u003e {\n  const { close } = useSwipeableItemParams\u003cItem\u003e();\n  return (\n    \u003cView style={[styles.row, styles.underlayLeft]}\u003e\n      \u003cTouchableOpacity onPress={() =\u003e close()}\u003e\n        \u003cText style={styles.text}\u003eCLOSE\u003c/Text\u003e\n      \u003c/TouchableOpacity\u003e\n    \u003c/View\u003e\n  );\n};\n\ntype Item = {\n  key: string;\n  text: string;\n  backgroundColor: string;\n};\n\nfunction getColor(i: number) {\n  const multiplier = 255 / (NUM_ITEMS - 1);\n  const colorVal = i * multiplier;\n  return `rgb(${colorVal}, ${Math.abs(128 - colorVal)}, ${255 - colorVal})`;\n}\n\nconst initialData: Item[] = [...Array(NUM_ITEMS)].fill(0).map((d, index) =\u003e {\n  const backgroundColor = getColor(index);\n  return {\n    text: `${index}`,\n    key: `key-${backgroundColor}`,\n    backgroundColor,\n  };\n});\n\nconst styles = StyleSheet.create({\n  container: {\n    flex: 1,\n  },\n  row: {\n    flexDirection: \"row\",\n    flex: 1,\n    alignItems: \"center\",\n    justifyContent: \"center\",\n    padding: 15,\n  },\n  text: {\n    fontWeight: \"bold\",\n    color: \"white\",\n    fontSize: 32,\n  },\n  underlayLeft: {\n    flex: 1,\n    backgroundColor: \"tomato\",\n    justifyContent: \"flex-end\",\n  },\n});\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcomputerjazz%2Freact-native-swipeable-item","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcomputerjazz%2Freact-native-swipeable-item","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcomputerjazz%2Freact-native-swipeable-item/lists"}