npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

react-native-drax

v1.0.0

Published

A drag and drop system for React Native

Readme

react-native-drax

A drag-and-drop framework for React Native

React Native CLI Expo CLI platforms GitHub top language CI GitHub license npm version

Docs | Live Example

📖 Overview

Drax is a declarative drag-and-drop framework for React Native, written in TypeScript. It supports free-form drag-and-drop, sortable lists and grids, cross-list reorder, drag handles, collision algorithms, and more.

Built on Reanimated 4 and Gesture Handler 3 with a UI-thread-first architecture for smooth 60fps interactions.

Platforms: iOS, Android, Web

✨ Highlights

  • 📋 List-agnostic sortable — works with FlatList, FlashList, LegendList, or any list component
  • 🔀 Cross-container drag — move items between lists (cross-list reorder)
  • UI-thread hit-testing — spatial index worklet for fast receiver detection
  • Drag handles — only the handle starts a drag, the rest scrolls
  • 💥 Collision algorithms — center, intersect, or contain
  • 📐 Drag bounds — constrain drags within a view
  • 🎨 Hover styles — conditional styles based on drag phase and receiver state
  • 🚫 Drop zone acceptance — accept or reject drops with acceptsDrag
  • 🎬 Animation presets — default, spring, gentle, snappy, none — or custom config
  • 🧲 Snap alignment — snap to 9-point alignment within receivers
  • Accessibility — auto-generated labels, reduced motion support
  • 📡 19 callback events — full drag lifecycle control
  • 🏗️ New Architecture compatible (Fabric)

🤔 Why Drax?

| Feature | Drax | reanimated-dnd | sortables | |---|:---:|:---:|:---:| | Free-form drag & drop | ✅ | ✅ | ➖ | | Sortable list / grid | ✅ | ✅ | ✅ | | Cross-container / cross-list reorder | ⚠️ Experimental | ➖ | ➖ | | List-agnostic (FlatList, FlashList, LegendList) | ✅ | ➖ | ➖ | | Drag handles | ✅ | ✅ | ✅ | | Drag state styling | 15 props + inactive | onStateChange | 5 props + hook | | Drop indicator | ✅ | ➖ | Grid only | | UI-thread DnD collision | ✅ | ➖ | ➖ | | Event callbacks | 19 types | ~12 types | ~10 types | | Accessibility + reduced motion | ✅ | Manual | Manual | | Web support | ✅ | ➖ | Partial | | Reanimated | 4 | ≥ 4.2 | ≥ 3 |

See full comparison →

📦 Installation

npm install react-native-drax
# or
yarn add react-native-drax

🔗 Peer Dependencies

npm install react-native-reanimated react-native-gesture-handler

| Peer Dependency | Version | |---|---| | react | >= 18 | | react-native | >= 0.68 | | react-native-reanimated | ^4.0.0 | | react-native-gesture-handler | >= 2.0.0 (v3 recommended) |

🚀 Quick Start

👋 Basic Drag-and-Drop

import { DraxProvider, DraxView } from 'react-native-drax';

function App() {
  return (
    <DraxProvider>
      <DraxView
        style={{ width: 100, height: 100, backgroundColor: 'blue' }}
        onDragStart={() => console.log('dragging')}
        payload="hello"
      />
      <DraxView
        style={{ width: 100, height: 100, backgroundColor: 'green' }}
        onReceiveDragDrop={({ dragged: { payload } }) => {
          console.log(`received: ${payload}`);
        }}
      />
    </DraxProvider>
  );
}

📋 Sortable List

The simplest way to make a reorderable list:

import { useState } from 'react';
import { Text, View } from 'react-native';
import { DraxProvider, DraxList } from 'react-native-drax';

function App() {
  const [items, setItems] = useState(['A', 'B', 'C', 'D', 'E']);

  return (
    <DraxProvider>
      <DraxList
        data={items}
        keyExtractor={(item) => item}
        onReorder={({ data }) => setItems(data)}
        renderItem={({ item }) => (
          <View style={{ padding: 16, backgroundColor: '#eee', margin: 4 }}>
            <Text>{item}</Text>
          </View>
        )}
      />
    </DraxProvider>
  );
}

DraxList is list-agnostic — pass any list component via the component prop:

import { FlashList } from '@shopify/flash-list';

<DraxList
  component={FlashList}
  data={items}
  keyExtractor={(item) => item.id}
  onReorder={({ data }) => setItems(data)}
  renderItem={({ item }) => <ItemCard item={item} />}
  estimatedItemSize={60}
/>

🧱 Composable API

For full control, use the composable primitives directly:

import {
  DraxProvider,
  useSortableList,
  SortableContainer,
  SortableItem,
} from 'react-native-drax';
import { FlatList } from 'react-native';

function App() {
  const [items, setItems] = useState(['A', 'B', 'C', 'D', 'E']);
  const listRef = useRef<FlatList>(null);

  const sortable = useSortableList({
    data: items,
    keyExtractor: (item) => item,
    onReorder: ({ data }) => setItems(data),
  });

  return (
    <DraxProvider>
      <SortableContainer sortable={sortable} scrollRef={listRef}>
        <FlatList
          ref={listRef}
          data={sortable.data}
          keyExtractor={sortable.stableKeyExtractor}
          onScroll={sortable.onScroll}
          onContentSizeChange={sortable.onContentSizeChange}
          renderItem={({ item, index }) => (
            <SortableItem sortable={sortable} index={index}>
              <Text>{item}</Text>
            </SortableItem>
          )}
        />
      </SortableContainer>
    </DraxProvider>
  );
}

This pattern works with any list component — FlatList, FlashList, LegendList, ScrollView, etc.

🎛 Features

✊ Drag Handles

Only the handle area starts a drag — the rest of the view scrolls normally:

import { DraxView, DraxHandle } from 'react-native-drax';

<DraxView dragHandle>
  <Text>This content scrolls normally</Text>
  <DraxHandle>
    <GripIcon />  {/* Only this starts a drag */}
  </DraxHandle>
</DraxView>

📐 Drag Bounds

Constrain a dragged view within a boundary:

const boundsRef = useRef<View>(null);

<View ref={boundsRef} style={{ flex: 1 }}>
  <DraxView dragBoundsRef={boundsRef}>
    <Text>I can only be dragged within the parent</Text>
  </DraxView>
</View>

💥 Collision Algorithms

Control how receiver detection works:

<DraxView collisionAlgorithm="center" />   {/* hover center inside receiver (default) */}
<DraxView collisionAlgorithm="intersect" /> {/* any overlap triggers receiving */}
<DraxView collisionAlgorithm="contain" />   {/* dragged view must be fully inside */}

🚫 Drop Zone Acceptance

Accept or reject drops conditionally:

<DraxView
  acceptsDrag={(draggedPayload) => items.length < 5}
  onReceiveDragDrop={({ dragged }) => addItem(dragged.payload)}
/>

🎨 Hover Styles

Style the hover layer based on drag state:

<DraxView
  hoverStyle={{ opacity: 0.8 }}
  hoverDraggingWithReceiverStyle={{ borderColor: 'green', borderWidth: 2 }}
  hoverDraggingWithoutReceiverStyle={{ opacity: 0.5 }}
  hoverDragReleasedStyle={{ opacity: 0.3 }}
/>

🧲 Snap Alignment

Snap dropped items to specific positions within a receiver:

import { snapToAlignment } from 'react-native-drax';

<DraxView
  onReceiveDragDrop={({ dragged, receiver }) =>
    snapToAlignment(receiver, dragged, 'top-left', { x: 8, y: 8 })
  }
/>

Alignments: center, top-left, top-center, top-right, center-left, center-right, bottom-left, bottom-center, bottom-right

🎬 Animation Presets

<DraxList animationConfig="spring" />  {/* spring physics */}
<DraxList animationConfig="gentle" />  {/* soft spring */}
<DraxList animationConfig="snappy" />  {/* fast spring */}
<DraxList animationConfig="none" />    {/* instant */}

{/* Or custom: */}
<DraxList animationConfig={{
  useSpring: true,
  springDamping: 15,
  springStiffness: 150,
  springMass: 1,
}} />

Device reduced motion settings are respected automatically.

📡 Continuous Drag Callbacks

<DraxView
  onDrag={(data) => { /* fires every frame while dragging over empty space */ }}
  onDragOver={(data) => { /* fires every frame while over the same receiver */ }}
/>

🔀 Cross-Container Sortable (Experimental)

Move items between lists (cross-list reorder):

import {
  useSortableBoard,
  SortableBoardContainer,
  useSortableList,
  SortableContainer,
  SortableItem,
} from 'react-native-drax';

const board = useSortableBoard({
  onTransfer: ({ fromColumnId, toColumnId, fromIndex, toIndex, item }) => {
    // Move item between columns
  },
});

<SortableBoardContainer board={board}>
  {columns.map((column) => (
    <Column key={column.id} board={board} column={column} />
  ))}
</SortableBoardContainer>

Note: Cross-container drag is experimental. The API may change in future versions.

🏷️ Namespace API

For convenience, all components are available under the Drax namespace:

import { Drax } from 'react-native-drax';

<Drax.Provider>
  <Drax.View draggable>
    <Drax.Handle><GripIcon /></Drax.Handle>
  </Drax.View>
</Drax.Provider>

🧩 Components

| Component | Description | |---|---| | DraxProvider | Context provider — wrap your app's drag-and-drop area | | DraxView | Draggable and/or receptive view with 19 callback events | | DraxList | List-agnostic sortable list (convenience wrapper) | | DraxHandle | Drag handle — only this area starts a drag | | DraxScrollView | Scrollable container with auto-scroll during drag | | SortableContainer | Monitoring wrapper for composable sortable API | | SortableItem | Per-item wrapper with shift animation | | SortableBoardContainer | Cross-container board coordinator (experimental) |

🪝 Hooks

| Hook | Description | |---|---| | useSortableList | List-agnostic reorder state management | | useSortableBoard | Cross-container board coordinator (experimental) | | useDraxContext | Access the Drax context | | useDraxId | Generate a unique Drax view ID |

💡 Examples

The example/ directory contains an Expo Router app with 10 screens demonstrating all features:

| Screen | Features shown | |---|---| | Color Drag & Drop | Drop acceptance, hover styles, snap alignment | | Reorderable List | DraxList, animation presets, auto-scroll | | Reorderable Grid | Sortable grid with multi-column layout | | Drag Handles | Only the grip icon starts a drag | | Drag Bounds | Constrain drag within a view | | Collision Modes | Center vs Intersect vs Contain | | Cross-List Reorder | FlashList + LegendList + FlatList cross-container drag (experimental) | | Knight Moves | Chess knight drag puzzle | | Scrolling | Drag from scroll view to drop zone | | Stress Test | 100 items in a sortable list |

To run the example app:

cd example && yarn start

🔄 Migration from v0.x

v1.0.0 is a complete rewrite. Key changes:

  • DraxList is new — list-agnostic convenience wrapper using the new sortable architecture. The old DraxList / DraxListItem API from v0.10.x and v0.11.0-alpha is removed.
  • New sortable architectureuseSortableList + SortableContainer + SortableItem composable API replaces the old array-indexed approach.
  • Reanimated 4 + Gesture Handler 3 — required peer dependencies (Gesture Handler v2 supported via compat layer with reduced performance).
  • New Architecture (Fabric) compatible.

📋 Changelog

See CHANGELOG.md for a full list of changes.

🤝 Contributing

Issues, pull requests, and discussion are all welcome. See the Contribution Guidelines for details.

📜 Code of Conduct

This project is released with a Contributor Code of Conduct. By participating in this project you agree to abide by its terms.

🏆 Contributors

Originally created by Joe Lafiosca. v1.0.0 rewrite led by Ovidiu Cristescu.

Thanks to all contributors who have helped make Drax better:

📃 License

MIT


Built and maintained using OpenKit.