# Slides

> Organism — orn-ui

> ⚠️ Requiere <UIProvider>: Este componente (como todos los de orn-ui) debe renderizarse dentro de un ancestro <UIProvider>, o lanza un error en runtime. See https://orn-ui-docs.vercel.app/getting-started.md

> Corre en Expo SDK 54, 55, 56 y 57, y en React Native puro >=0.81 con react >=19.1. Sin módulos nativos — funciona en Expo Go, sin prebuild.

## Instalación

Instala solo este componente (copia el código fuente a tu proyecto, sin dependencia npm)
```bash
npx orn-ui add slides
```

O instala el paquete completo e impórtalo
```tsx
pnpm add orn-ui
import { Slides } from 'orn-ui/slides';
```

Depende de: core (theme + icons), transition, gradient

## Variantes

### horizontal · gradient · dots · infinite + autoPlay

```tsx
<View style={STAGE}>
  <Slides
    data={SLIDES}
    keyExtractor={(item) => item.id}
    background={(item) => item.gradient}
    renderItem={(item) => <Panel slide={item} />}
    loop
    autoPlay
    interval={2500}
  />
</View>
```

### numbered indicators · flat colors · finite · button inside

```tsx
<View style={{ width: '100%', gap: 8 }}>
  <View style={STAGE}>
    <Slides
      data={SLIDES}
      keyExtractor={(item) => item.id}
      background={(item, index) => FLAT[index]}
      renderItem={(item) => <Panel slide={item} onPress={() => setTapped(item.title)} />}
      indicators="numbers"
    />
  </View>
  <Body>{tapped ? `pressed: ${tapped}` : 'press the button inside a slide'}</Body>
</View>
```

### vertical orientation

```tsx
<View style={STAGE}>
  <Slides
    data={SLIDES}
    keyExtractor={(item) => item.id}
    background={(item) => item.gradient}
    renderItem={(item) => <Panel slide={item} />}
    orientation="vertical"
  />
</View>
```

## Código completo del demo

```tsx
const variants: VariantDef[] = [
  {
    label: 'horizontal · gradient · dots · infinite + autoPlay',
    content: (
      <View style={STAGE}>
        <Slides
          data={SLIDES}
          keyExtractor={(item) => item.id}
          background={(item) => item.gradient}
          renderItem={(item) => <Panel slide={item} />}
          loop
          autoPlay
          interval={2500}
        />
      </View>
    ),
  },
  {
    label: 'numbered indicators · flat colors · finite · button inside',
    content: (
      <View style={{ width: '100%', gap: 8 }}>
        <View style={STAGE}>
          <Slides
            data={SLIDES}
            keyExtractor={(item) => item.id}
            background={(item, index) => FLAT[index]}
            renderItem={(item) => <Panel slide={item} onPress={() => setTapped(item.title)} />}
            indicators="numbers"
          />
        </View>
        <Body>{tapped ? `pressed: ${tapped}` : 'press the button inside a slide'}</Body>
      </View>
    ),
  },
  {
    label: 'vertical orientation',
    content: (
      <View style={STAGE}>
        <Slides
          data={SLIDES}
          keyExtractor={(item) => item.id}
          background={(item) => item.gradient}
          renderItem={(item) => <Panel slide={item} />}
          orientation="vertical"
        />
      </View>
    ),
  },
];
```

## Props

| Nombre | Tipo | Por defecto | Descripción |
|---|---|---|---|
| `data` | `T[]` | — | — |
| `keyExtractor` | `(item: T, index: number) => string` | — | — |
| `renderItem` | `(item: T, index: number) => ReactNode` | — | Contenido de la slide: imágenes, botones, lo que sea. Se dibuja sobre `background`. |
| `background?` | `(item: T, index: number) => SlideBackground` | — | Fondo por slide: `'#101014'` pinta plano, `['#004cef', '#00cae1']` degrada. |
| `gradientDirection?` | `'vertical' \| 'horizontal' \| 'diagonal' \| 'diagonal-reverse'` | vertical | Dirección del degradado cuando `background` devuelve varios colores. |
| `orientation?` | `'vertical' \| 'horizontal'` | horizontal | — |
| `indicators?` | `'dots' \| 'numbers' \| 'none'` | dots | Círculos, círculos numerados, o ninguno. |
| `indicatorPlacement?` | `'overlay' \| 'outside'` | overlay | 'overlay' los apoya sobre la slide, en blanco; 'outside' los saca fuera del área deslizable, con los colores del tema. |
| `loop?` | `boolean` | false | Después de la última vuelve a la primera (y al revés). |
| `autoPlay?` | `boolean` | false | Avanza solo. Se pausa mientras el dedo arrastra. |
| `interval?` | `number` | 4000 | ms entre avances de `autoPlay`. |
| `showAutoPlayToggle?` | `boolean` | true | Botón para frenar el avance automático. Sólo aparece con `autoPlay`, y va en `true` porque contenido que se mueve solo necesita una forma de pausarlo (WCAG 2.2.2). |
| `spacing?` | `number` | 0 | Hueco entre slides, en px. En 0 quedan pegadas. |
| `index?` | `number` | — | Índice controlado. Sin él, el componente maneja el suyo desde `defaultIndex`. |
| `defaultIndex?` | `number` | 0 | — |
| `onIndexChange?` | `(index: number) => void` | — | — |
| `height?` | `number` | 240 | Alto del área deslizable. |
| `swipeEnabled?` | `boolean` | true | — |
| `slideStyle?` | `StyleProp<ViewStyle>` | — | Estilos de la caja visible de cada slide — padding, alineación, radio. |
| `style?` | `StyleProp<ViewStyle>` | — | — |
