orn-ui
Organism

ReorderableList

Requiere <UIProvider> — Primeros pasos →

Instalación

Instala solo este componente (copia el código fuente a tu proyecto, sin dependencia npm)

npx orn-ui add reorderable-list

O instala el paquete completo e impórtalo

pnpm add orn-ui
import { ReorderableList } from 'orn-ui/reorderable-list';
Depende de:core (theme + icons)

Uso

  • cuándo usarlo — Una lista corta y ya cargada que la gente reordena a mano: playlists, prioridades, orden custom.
  • itemHeight — Obligatorio y fijo — el índice destino se calcula por distancia de arrastre, no midiendo layout.
  • onReorder — Se dispara al soltar, con el arreglo ya reordenado; `data` en sí nunca se muta.
  • disabled — Las filas siguen renderizando, solo deja de responder el arrastre — no hace falta una variante de solo lectura aparte.
Clip del demo todavía sin grabar — ver MEDIA.md

Variantes

Long-press a row and drag — the rows in between shift out of the way

<ReorderableList
  data={data}
  keyExtractor={(item) => item.id}
  itemHeight={ITEM_HEIGHT}
  onReorder={setData}
  renderItem={(item, _index, dragging) => <Row name={item.name} dragging={dragging} />}
/>

disabled — rows render but can’t be dragged

<ReorderableList
  data={INITIAL}
  keyExtractor={(item) => item.id}
  itemHeight={ITEM_HEIGHT}
  disabled
  onReorder={() => {}}
  renderItem={(item, _index, dragging) => <Row name={item.name} dragging={dragging} />}
/>
Código completo del demo
const variants: VariantDef[] = [
  {
    label: 'Long-press a row and drag — the rows in between shift out of the way',
    content: (
      <ReorderableList
        data={data}
        keyExtractor={(item) => item.id}
        itemHeight={ITEM_HEIGHT}
        onReorder={setData}
        renderItem={(item, _index, dragging) => <Row name={item.name} dragging={dragging} />}
      />
    ),
  },
  {
    label: 'disabled — rows render but can’t be dragged',
    content: (
      <ReorderableList
        data={INITIAL}
        keyExtractor={(item) => item.id}
        itemHeight={ITEM_HEIGHT}
        disabled
        onReorder={() => {}}
        renderItem={(item, _index, dragging) => <Row name={item.name} dragging={dragging} />}
      />
    ),
  },
];
return (
  <>
    <Caption style={{ marginBottom: 8 }}>Web preview doesn’t simulate touch drag — see the gif on this page.</Caption>
    <VariantList variants={variants} />
  </>
);

Props

NombreTipoPor defectoDescripción
dataT[]
keyExtractor(item: T, index: number) => string
itemHeightnumberAlto fijo de cada fila: necesario para calcular el índice destino sin medir layout async.
renderItem(item: T, index: number, dragging: boolean) => ReactElement<unknown, string | JSXElementConstructor<any>>
onReorder(data: T[]) => voidSe llama al soltar, con el array ya reordenado. No muta `data`.
onDragStart?(index: number) => voidEmpieza a arrastrar la fila `index`. Usalo para apagar el scroll del contenedor (`scrollEnabled={false}`) mientras dure: en iOS el `UIScrollView` padre cancela los toques sobre el contenido apenas arranca su gesto vertical, y sin esto el drag muere a los pocos píxeles.
onDragEnd?() => voidTermina el drag — al soltar o cancelar. Siempre corre si `onDragStart` corrió.
disabled?booleanfalse
style?StyleProp<ViewStyle>