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-ultra-carousel

v1.0.2

Published

The Ultimate Carousel Ecosystem for React Native. 35+ animation presets, plugin system, CLI tool. Built on Reanimated.

Readme


Highlights

  • 35+ Animation Presets — From basic slide/fade to 3D cube, coverflow, tinder, helix, and more
  • 60 FPS Animations — All animations run on the UI thread via Reanimated worklets
  • Plugin System — Extend carousel behavior with custom or built-in plugins
  • Theme Support — Light, dark, vibrant, minimal themes out of the box
  • Cross-Platform — iOS, Android, and Expo (SDK 50+)
  • TypeScript First — Strict mode, full type coverage, IntelliSense-friendly API
  • Accessible — Screen reader support, accessibility actions built in
  • Auto Play — Built-in auto-advance with pause-on-interaction
  • Flexible Layout — Horizontal/vertical, multi-item, gap, snap alignment
  • Custom Animations — Write your own worklet-based animation functions
  • Built-in ComponentsParallaxImage, ImageGallery, OnboardingCarousel

Installation

npm install react-native-ultra-carousel react-native-reanimated react-native-gesture-handler
yarn add react-native-ultra-carousel react-native-reanimated react-native-gesture-handler
npx expo install react-native-ultra-carousel react-native-reanimated react-native-gesture-handler

Follow the setup guides for react-native-reanimated and react-native-gesture-handler if you haven't already.

Add the Reanimated babel plugin to your babel.config.js:

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

Compatibility

| Environment | Versions | |---|---| | React | >= 18.0.0 (including React 19) | | React Native | >= 0.72.0 | | react-native-reanimated | >= 3.0.0 | | react-native-gesture-handler | >= 2.9.0 | | Expo SDK | 50, 51, 52, 53 |

Expo Go note: If you encounter a Worklets version mismatch error with react-native-reanimated >= 4.x in Expo Go, use a development build instead, or pin reanimated to ~3.16.0 for Expo SDK 53 compatibility.

Quick Start

import { Carousel } from 'react-native-ultra-carousel';
import { View, Text } from 'react-native';

const data = [
  { id: '1', title: 'First Slide', color: '#FF6B6B' },
  { id: '2', title: 'Second Slide', color: '#4ECDC4' },
  { id: '3', title: 'Third Slide', color: '#45B7D1' },
];

export default function App() {
  return (
    <Carousel
      data={data}
      renderItem={({ item }) => (
        <View style={{ flex: 1, backgroundColor: item.color, justifyContent: 'center', alignItems: 'center' }}>
          <Text style={{ fontSize: 24, color: '#fff', fontWeight: 'bold' }}>{item.title}</Text>
        </View>
      )}
      preset="slide"
      pagination
      autoPlay
      width={350}
      height={200}
    />
  );
}

Animation Presets

Basic (10 presets)

| Preset | Description | |--------|-------------| | slide | Standard horizontal slide (default) | | fade | Crossfade between stacked items | | slide-fade | Slide + fade combination | | scale | Active item full-size, neighbors shrink | | scale-fade | Scale + fade combination | | vertical | Vertical slide transition | | vertical-fade | Vertical slide + fade | | parallax | Multi-layer parallax depth | | overlap | Items overlap with 30% coverage | | peek | Adjacent items peek from sides |

Advanced (10 presets)

| Preset | Description | |--------|-------------| | stack | Stacked cards with swipe-to-reveal | | tinder | Tinder-style swipe cards with rotation | | coverflow | Apple CoverFlow 3D perspective | | cube | 3D cube rotation | | flip | 3D card flip | | wheel | Ferris wheel circular motion | | accordion | Fold/unfold effect | | zoom | Zoom in/out transition | | rotate | Rotation-based transition | | depth | Depth-of-field effect |

Creative (15 presets)

| Preset | Description | |--------|-------------| | newspaper | Fly in with spin like headlines | | origami | Paper-fold origami effect | | carousel-3d | True 3D circular carousel | | wave | Sine wave motion | | spiral | Spiral outward with rotation | | glitch | Digital glitch jitter effect | | morph | Shape morphing transition | | shutter | Camera shutter open/close | | domino | Domino falling effect | | elastic | Elastic bounce stretch | | blur-slide | Slide with simulated blur | | windmill | Windmill pivot rotation | | film-strip | Film strip slide with jitter | | helix | DNA helix 3D spiral | | gravity | Gravity drop with bounce |

API Reference

<Carousel /> Props

| Prop | Type | Default | Description | |------|------|---------|-------------| | data | T[] | required | Array of data items | | renderItem | (info: RenderItemInfo<T>) => ReactNode | required | Render function for each item | | preset | PresetName \| CustomAnimationFn | 'slide' | Animation preset or custom function | | width | number | 375 | Container width | | height | number | 250 | Container height | | itemWidth | number | container width | Width of each item | | itemHeight | number | container height | Height of each item | | direction | 'horizontal' \| 'vertical' | 'horizontal' | Scroll direction | | gap | number | 0 | Gap between items | | snapAlignment | 'start' \| 'center' \| 'end' | 'center' | Snap position | | loop | boolean | false | Enable infinite loop | | initialIndex | number | 0 | Starting slide index | | enabled | boolean | true | Enable/disable gesture | | autoPlay | boolean \| AutoPlayConfig | false | Auto advance slides | | autoPlayInterval | number | 3000 | Auto play interval (ms) | | pagination | boolean \| PaginationConfig | false | Show pagination indicator | | gestureConfig | GestureConfig | — | Gesture customization | | plugins | CarouselPlugin[] | — | Array of plugins | | onIndexChange | (index: number) => void | — | Called when active index changes | | onScrollStart | () => void | — | Called when scrolling starts | | onScrollEnd | (index: number) => void | — | Called when scrolling ends | | scrollProgress | SharedValue<number> | — | External shared value for scroll offset | | accessible | boolean | true | Enable accessibility | | style | ViewStyle | — | Container style | | itemStyle | ViewStyle | — | Style applied to each item wrapper |

<Carousel /> Ref Methods

import { Carousel, CarouselRef } from 'react-native-ultra-carousel';

const ref = useRef<CarouselRef>(null);

ref.current?.next();                    // Go to next slide
ref.current?.prev();                    // Go to previous slide
ref.current?.scrollTo(3);               // Jump to index 3
ref.current?.scrollTo(3, false);        // Jump without animation
ref.current?.getCurrentIndex();         // Get current index
ref.current?.startAutoPlay();           // Start auto play
ref.current?.stopAutoPlay();            // Stop auto play
ref.current?.pauseAutoPlay();           // Pause auto play

<Carousel ref={ref} data={data} renderItem={renderItem} />

useCarousel Hook

import { useCarousel } from 'react-native-ultra-carousel';

function MyScreen() {
  const carousel = useCarousel();

  return (
    <>
      <Carousel ref={carousel.ref} data={data} renderItem={renderItem} />
      <Button title="Next" onPress={() => carousel.next()} />
      <Button title="Prev" onPress={() => carousel.prev()} />
      <Text>Current: {carousel.activeIndex}</Text>
    </>
  );
}

Custom Animations

Create your own animation function. It receives the normalized progress value (-1 to 1, where 0 = active item) and returns an animated style:

import { Carousel, type CustomAnimationFn } from 'react-native-ultra-carousel';
import { interpolate, Extrapolation } from 'react-native-reanimated';

const myAnimation: CustomAnimationFn = (progress) => {
  'worklet';

  const rotate = interpolate(progress, [-1, 0, 1], [-30, 0, 30], Extrapolation.CLAMP);
  const scale = interpolate(Math.abs(progress), [0, 1], [1, 0.8], Extrapolation.CLAMP);
  const opacity = interpolate(Math.abs(progress), [0, 1], [1, 0.5], Extrapolation.CLAMP);

  return {
    transform: [
      { rotate: `${rotate}deg` },
      { scale },
    ],
    opacity,
  };
};

<Carousel data={data} renderItem={renderItem} preset={myAnimation} />

Pagination

// Dot pagination (default)
<Carousel data={data} renderItem={renderItem} pagination />

// Bar pagination
<Carousel data={data} renderItem={renderItem} pagination={{ type: 'bar' }} />

// Number pagination ("1 / 5")
<Carousel data={data} renderItem={renderItem} pagination={{ type: 'number' }} />

// Progress bar
<Carousel data={data} renderItem={renderItem} pagination={{ type: 'progress' }} />

// Customized dots
<Carousel
  data={data}
  renderItem={renderItem}
  pagination={{
    type: 'dot',
    activeColor: '#FF6B6B',
    inactiveColor: '#ddd',
    size: 10,
    gap: 8,
  }}
/>

// Custom renderer
<Carousel
  data={data}
  renderItem={renderItem}
  pagination={{
    type: 'custom',
    renderCustom: ({ currentIndex, totalItems }) => (
      <Text>{currentIndex + 1} of {totalItems}</Text>
    ),
  }}
/>

Plugin System

Extend carousel behavior with plugins:

import { Carousel, createPlugin } from 'react-native-ultra-carousel';

// Create a custom plugin
const analyticsPlugin = createPlugin({
  name: 'analytics',
  onIndexChange: (index) => {
    analytics.track('carousel_swipe', { slideIndex: index });
  },
  onInit: (carouselRef) => {
    console.log('Carousel initialized');
  },
  onDestroy: () => {
    console.log('Carousel destroyed');
  },
});

<Carousel data={data} renderItem={renderItem} plugins={[analyticsPlugin]} />

Built-in Plugins

import {
  createAutoPlayPlugin,
  createPaginationPlugin,
  createParallaxImagePlugin,
} from 'react-native-ultra-carousel';

// Auto play plugin with custom config
const autoPlay = createAutoPlayPlugin({ interval: 5000, direction: 'forward' });

// Pagination plugin
const pagination = createPaginationPlugin({ type: 'dot', position: 'bottom' });

// Parallax image plugin
const parallax = createParallaxImagePlugin({ speed: 0.5 });

Theme Support

import { Carousel, lightTheme, darkTheme, createTheme } from 'react-native-ultra-carousel';

// Use built-in themes: 'light', 'dark', 'vibrant', 'minimal'
<Carousel theme={darkTheme} ... />

// Create a custom theme
const myTheme = createTheme({
  colors: {
    primary: '#FF6B6B',
    background: '#1a1a2e',
    text: '#ffffff',
    border: '#333366',
  },
  borderRadius: 16,
  spacing: 12,
});

Built-in Components

<ParallaxImage />

Parallax scrolling image inside carousel items:

import { Carousel, ParallaxImage } from 'react-native-ultra-carousel';

<Carousel
  data={images}
  renderItem={({ item, animationProgress }) => (
    <ParallaxImage
      source={{ uri: item.url }}
      animationProgress={animationProgress}
      speed={0.3}
      style={{ width: '100%', height: '100%' }}
    />
  )}
/>

<ImageGallery />

Full-featured image gallery carousel:

import { ImageGallery } from 'react-native-ultra-carousel';

<ImageGallery
  images={[
    { uri: 'https://example.com/1.jpg', title: 'Photo 1' },
    { uri: 'https://example.com/2.jpg', title: 'Photo 2' },
  ]}
  width={400}
  height={300}
  pagination
/>

<OnboardingCarousel />

Ready-to-use onboarding flow:

import { OnboardingCarousel } from 'react-native-ultra-carousel';

<OnboardingCarousel
  steps={[
    { title: 'Welcome', description: 'Get started...', image: require('./welcome.png') },
    { title: 'Features', description: 'Discover...', image: require('./features.png') },
    { title: 'Ready', description: 'Let\'s go!', image: require('./ready.png') },
  ]}
  onComplete={() => navigation.navigate('Home')}
/>

Advanced Usage

Vertical Carousel

<Carousel
  data={data}
  renderItem={renderItem}
  direction="vertical"
  width={300}
  height={500}
  preset="vertical-fade"
/>

Multi-Item with Gaps

<Carousel
  data={data}
  renderItem={renderItem}
  width={screenWidth}
  height={200}
  itemWidth={screenWidth * 0.7}
  gap={16}
  snapAlignment="center"
  preset="scale"
/>

Auto Play with Custom Config

<Carousel
  data={data}
  renderItem={renderItem}
  autoPlay={{
    enabled: true,
    interval: 4000,
    direction: 'forward',
    pauseOnInteraction: true,
  }}
/>

Tracking Scroll Progress

import { useSharedValue } from 'react-native-reanimated';

function MyCarousel() {
  const scrollProgress = useSharedValue(0);

  return (
    <Carousel
      data={data}
      renderItem={renderItem}
      scrollProgress={scrollProgress}
    />
  );
}

Animation Preset Registry

import { registerPreset, getAllPresetNames, getPresetMeta } from 'react-native-ultra-carousel';

// Register a custom preset
registerPreset('my-custom', myAnimationFn, {
  name: 'My Custom',
  category: 'custom',
  description: 'A custom animation',
});

// Use it by name
<Carousel preset="my-custom" ... />

// List all available presets
const names = getAllPresetNames(); // ['slide', 'fade', ..., 'my-custom']

Performance Tips

  • All 35+ presets run at 60 FPS on the UI thread via Reanimated worklets
  • Use maxRenderItems to limit rendered items for very large datasets
  • Custom animations must include the 'worklet' directive
  • Avoid heavy JS computations inside renderItem — keep it lightweight
  • Use React.memo for complex item components

TypeScript

Full type coverage with strict mode:

import type {
  CarouselProps,
  CarouselRef,
  PresetName,
  RenderItemInfo,
  CustomAnimationFn,
  AnimatedItemStyle,
  CarouselPlugin,
  PaginationConfig,
  GestureConfig,
  AutoPlayConfig,
} from 'react-native-ultra-carousel';

Contributing

Contributions are welcome! See CONTRIBUTING.md for details.

License

MIT © toankhontech