# SearchList

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

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

Depende de: core (theme + icons), input, empty-state, skeleton, spinner, icon-button, pressable-scale

## Variantes

### Search + results

```tsx
<SearchList
  searchValue={query}
  onSearchChange={setQuery}
  data={data.map((name) => ({ name }))}
  keyExtractor={(item) => item.name}
  renderItem={({ item }) => (
    <Card style={{ marginBottom: 8 }}>
      <Body>{item.name}</Body>
    </Card>
  )}
  emptyTitle="No matches"
/>
```

### With scan action

```tsx
<SearchList
  searchValue=""
  onSearchChange={() => {}}
  onScanPress={() => {}}
  data={[]}
  keyExtractor={(item: any) => item.name}
  renderItem={() => null}
  emptyTitle="Scan a barcode or search"
/>
```

## Código completo del demo

```tsx
const variants: VariantDef[] = [
  {
    label: 'Search + results',
    content: (
      <SearchList
        searchValue={query}
        onSearchChange={setQuery}
        data={data.map((name) => ({ name }))}
        keyExtractor={(item) => item.name}
        renderItem={({ item }) => (
          <Card style={{ marginBottom: 8 }}>
            <Body>{item.name}</Body>
          </Card>
        )}
        emptyTitle="No matches"
      />
    ),
  },
  {
    label: 'With scan action',
    content: (
      <SearchList
        searchValue=""
        onSearchChange={() => {}}
        onScanPress={() => {}}
        data={[]}
        keyExtractor={(item: any) => item.name}
        renderItem={() => null}
        emptyTitle="Scan a barcode or search"
      />
    ),
  },
];
return <VariantList variants={variants} fill />;
```

## Props

| Nombre | Tipo | Por defecto | Descripción |
|---|---|---|---|
| `header?` | `ReactNode` | — | Chrome opcional arriba del buscador (ej. back button + título). |
| `searchValue` | `string` | — | — |
| `onSearchChange` | `(text: string) => void` | — | — |
| `searchPlaceholder?` | `string` | — | — |
| `searchIsLoading?` | `boolean` | false | — |
| `onScanPress?` | `() => void` | — | — |
| `scanAccessibilityLabel?` | `string` | Scan | — |
| `extraActions?` | `ReactNode` | — | — |
| `data` | `T[]` | — | — |
| `keyExtractor` | `(item: T, index: number) => string` | — | — |
| `renderItem` | `ListRenderItem<T>` | — | — |
| `isLoading?` | `boolean` | false | Carga inicial: mientras es true y no hay datos, se muestran placeholders. |
| `loadingMode?` | `'replace' \| 'overlay'` | replace | 'replace' reemplaza toda la lista por un spinner/skeleton; 'overlay' lo muestra encima manteniendo el layout. |
| `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` | — | — |
| `hasMore?` | `boolean` | false | — |
| `noMoreText?` | `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. |
| `onLoadMore?` | `() => void` | — | — |
| `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?` | `StyleProp<ViewStyle>` | — | — |
| `containerStyle?` | `ViewStyle` | — | — |
| `ListComponent?` | `ComponentType<any>` | FlatList | Componente de lista a usar (FlashList, etc). |
| `listProps?` | `Record<string, unknown>` | — | — |
