# List

> 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 list
```

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

Depende de: core (theme + icons), empty-state, skeleton, spinner

## Variantes

### Loaded

```tsx
<List
  data={DATA}
  keyExtractor={(item) => item.id}
  isLoading={false}
  renderItem={({ item }) => (
    <Card style={{ marginBottom: 8 }}>
      <Body>{item.name}</Body>
    </Card>
  )}
/>
```

### Loading

```tsx
<List data={[]} keyExtractor={(i: any) => i.id} isLoading loadingText="Fetching items..." renderItem={() => null} />
```

### Empty

```tsx
<View style={{ flex: 1 }}>
  <Button
    title={showEmpty ? 'Reset' : 'Simulate empty result'}
    variant="outline"
    onPress={() => setShowEmpty((v) => !v)}
    style={{ marginBottom: 12 }}
  />
  <List
    data={showEmpty ? [] : DATA.slice(0, 3)}
    keyExtractor={(item: any) => item.id}
    isLoading={false}
    emptyTitle="No items"
    emptyDescription="Try a different filter"
    renderItem={({ item }: any) => (
      <Card style={{ marginBottom: 8 }}>
        <Body>{item.name}</Body>
      </Card>
    )}
  />
</View>
```

## Código completo del demo

```tsx
const variants: VariantDef[] = [
  {
    label: 'Loaded',
    content: (
      <List
        data={DATA}
        keyExtractor={(item) => item.id}
        isLoading={false}
        renderItem={({ item }) => (
          <Card style={{ marginBottom: 8 }}>
            <Body>{item.name}</Body>
          </Card>
        )}
      />
    ),
  },
  {
    label: 'Loading',
    content: <List data={[]} keyExtractor={(i: any) => i.id} isLoading loadingText="Fetching items..." renderItem={() => null} />,
  },
  {
    label: 'Empty',
    content: (
      <View style={{ flex: 1 }}>
        <Button
          title={showEmpty ? 'Reset' : 'Simulate empty result'}
          variant="outline"
          onPress={() => setShowEmpty((v) => !v)}
          style={{ marginBottom: 12 }}
        />
        <List
          data={showEmpty ? [] : DATA.slice(0, 3)}
          keyExtractor={(item: any) => item.id}
          isLoading={false}
          emptyTitle="No items"
          emptyDescription="Try a different filter"
          renderItem={({ item }: any) => (
            <Card style={{ marginBottom: 8 }}>
              <Body>{item.name}</Body>
            </Card>
          )}
        />
      </View>
    ),
  },
];
return <VariantList variants={variants} fill />;
```

## Props

| Nombre | Tipo | Por defecto | Descripción |
|---|---|---|---|
| `data` | `T[]` | — | — |
| `keyExtractor` | `(item: T, index: number) => string` | — | — |
| `renderItem` | `ListRenderItem<T>` | — | — |
| `isLoading` | `boolean` | — | Carga inicial: mientras es true y no hay datos, se muestran placeholders. |
| `isRefreshing?` | `boolean` | false | Recarga con datos ya en pantalla (pull-to-refresh). |
| `isLoadingMore?` | `boolean` | false | — |
| `isReady?` | `boolean` | true | Controlado por quien lo consume: mientras es false, se muestra un spinner de pantalla completa. |
| `loadingText?` | `string` | — | — |
| `loadingMoreText?` | `string` | — | — |
| `skeletonCount?` | `number` | 6 | Filas fantasma de la carga inicial. |
| `renderSkeletonItem?` | `() => ReactElement<unknown, string \| JSXElementConstructor<any>>` | — | Placeholder propio, para que calce con la forma real del ítem. |
| `onEndReached?` | `() => void` | — | — |
| `onEndReachedThreshold?` | `number` | 0.3 | — |
| `onRefresh?` | `() => void` | — | — |
| `emptyTitle?` | `string` | — | — |
| `emptyDescription?` | `string` | — | — |
| `emptyIconName?` | `IconName` | — | — |
| `ListHeaderComponent?` | `ReactElement<unknown, string \| JSXElementConstructor<any>> \| ComponentType<any>` | — | — |
| `ListFooterComponent?` | `ReactElement<unknown, string \| JSXElementConstructor<any>> \| ComponentType<any>` | — | — |
| `contentContainerStyle?` | `ViewStyle` | — | — |
| `containerStyle?` | `ViewStyle` | — | — |
| `ListComponent?` | `ComponentType<any>` | FlatList | Componente de lista a usar (FlashList, etc). |
| `listProps?` | `Record<string, unknown>` | — | — |
