> For AI agents: the complete documentation index is available at https://react-native-swipe-deck.pages.dev/llms.txt, the full documentation bundle is available at https://react-native-swipe-deck.pages.dev/llms-full.txt.

# Quick Start

Create one typed deck family for your item type. `Root`, `Card`, hooks, actions,
and events from that factory share the same registry namespace.

## Examples & Demo

- [📁 Example Project](https://github.com/react-native-motion-kit/react-native-swipe-deck/tree/main/example) -
  Real implementation code with various use cases.
- [🤖 Expo Snack](https://snack.expo.dev/@harang/react-native-swipe-deck) -
  Try it instantly on Expo Snack.


```tsx
import { Text, View } from 'react-native';
import { createSwipeDeck, SwipeDeckMotion } from '@react-native-motion-kit/swipe-deck';

type Profile = {
  id: string;
  name: string;
  bio: string;
};

const ProfileDeck = createSwipeDeck<Profile>({
  motion: SwipeDeckMotion.tinder({
    drag: {
      mode: 'horizontal',
      liftYFactor: 0.15,
    },
    rotation: {
      mode: 'grab-position',
    },
    dismiss: {
      threshold: ({ width }) => width * 0.3,
      velocityThreshold: 800,
      minDuration: 300,
      maxDuration: 520,
    },
  }),
});

function ProfileDeckEvents() {
  ProfileDeck.useDeckEventListener('swipe', ({ item, direction, source }) => {
    console.log(item.name, direction, source);
  });

  ProfileDeck.useDeckEventListener('endReached', () => {
    console.log('No more cards');
  });

  return null;
}

function ProfileCard({ profile, active }: { profile: Profile; active: boolean }) {
  return (
    <View>
      <Text>{active ? 'Now viewing' : 'Up next'}</Text>
      <Text>{profile.name}</Text>
      <Text>{profile.bio}</Text>
    </View>
  );
}

export function ProfileDeckScreen({ profiles }: { profiles: Profile[] }) {
  return (
    <>
      <ProfileDeckEvents />
      <ProfileDeck.Root data={profiles} getKey={(item) => item.id} visibleCardCount={3}>
        <ProfileDeck.Card>
          {({ item, isActive }) => <ProfileCard profile={item} active={isActive} />}
        </ProfileDeck.Card>
      </ProfileDeck.Root>
    </>
  );
}
```

## Add Controls

Use state and action hooks for React-rendered UI such as counters and buttons.

```tsx
function ProfileDeckControls() {
  const { activeIndex, count, canSwipe, canUndo, isCompleted } = ProfileDeck.useDeckState();
  const { swipeLeft, swipeRight, swipeUp, undo } = ProfileDeck.useDeckActions();
  const current = activeIndex >= 0 ? activeIndex + 1 : 0;

  return (
    <View>
      <Text>{isCompleted ? 'Done' : `${current} / ${count}`}</Text>
      <Pressable disabled={!canSwipe} onPress={swipeLeft}>
        <Text>Nope</Text>
      </Pressable>
      <Pressable disabled={!canUndo} onPress={undo}>
        <Text>Undo</Text>
      </Pressable>
      <Pressable disabled={!canSwipe} onPress={swipeRight}>
        <Text>Like</Text>
      </Pressable>
      <Pressable disabled={!canSwipe} onPress={swipeUp}>
        <Text>Up</Text>
      </Pressable>
    </View>
  );
}
```

Add `allowedDirections={['left', 'right', 'up']}` on `Root` to enable the up action. Upward
gestures also require `drag.mode: 'free'`; the horizontal configuration above intentionally keeps
vertical finger movement disabled.

Enable undo tracking only when you expose undo UX:

```tsx
<ProfileDeck.Root data={profiles} getKey={(item) => item.id} undoEnabled>
  <ProfileDeck.Card>{({ item }) => <ProfileCard profile={item} />}</ProfileDeck.Card>
</ProfileDeck.Root>
```
