npm package: @lumel/react-sortable-hoc
Description: Set of higher-order components to turn any list into a sortable, touch-friendly, animated list
Author: Lumel Inc.
Latest version: 2.0.0

# @lumel/react-sortable-hoc

A set of higher-order components to turn any list into an animated, accessible, and touch-friendly sortable list.

> **Maintenance Note**: This is a fork of the original `react-sortable-hoc`, specifically maintained by **Lumel** to provide compatibility with **React 19** and resolve critical unmount/ref handling issues.

---

## 🚀 React 19 Ready (v2.0.0)

**@lumel/react-sortable-hoc v2.0.0** is fully compatible with **React 19**. This version resolves the "Older version of React" rendering conflicts and implements safe ref handling.

### ⚠️ Critical Migration Requirement

If you are using **functional components**, you **must** wrap them with `React.forwardRef` to ensure the library can correctly attach refs for positioning calculations:

```js
import {SortableElement} from '@lumel/react-sortable-hoc';

// ✅ CORRECT: Wrap with forwardRef and pass the ref
const SortableItem = SortableElement(
  React.forwardRef((props, ref) => <li ref={ref}>{props.value}</li>),
);
```

---

## Features

- **Higher Order Components** – Integrates seamlessly with your existing components.
- **Performance Focused** – Optimized for smooth 60FPS animations.
- **Touch Support** – Built-in support for mobile and touch devices.
- **Accessibility** – Full support for keyboard-based sorting out of the box.
- **Universal** – Works with horizontal lists, vertical lists, and grids.
- **Ecosystem Compatible** – Tested with `react-virtualized`, `react-window`, `react-infinite`, etc.

---

## Installation

Using [npm](https://www.npmjs.com/package/react-sortable-hoc):

```bash
npm install @lumel/react-sortable-hoc
```

Using [yarn](https://yarnpkg.com/package/react-sortable-hoc):

```bash
yarn add @lumel/react-sortable-hoc
```

---

## Basic Usage

```jsx
import React, {useState} from 'react';
import {SortableContainer, SortableElement} from '@lumel/react-sortable-hoc';
import {arrayMoveImmutable} from 'array-move';

// 1. Create your Sortable Element
const SortableItem = SortableElement(
  React.forwardRef(({value}, ref) => (
    <li ref={ref} className="list-item">
      {value}
    </li>
  )),
);

// 2. Create your Sortable Container
const SortableList = SortableContainer(
  React.forwardRef(({items}, ref) => (
    <ul ref={ref}>
      {items.map((value, index) => (
        <SortableItem key={`item-${value}`} index={index} value={value} />
      ))}
    </ul>
  )),
);

// 3. Use the components
const SortableApp = () => {
  const [items, setItems] = useState(['Item 1', 'Item 2', 'Item 3']);

  const onSortEnd = ({oldIndex, newIndex}) => {
    setItems(arrayMoveImmutable(items, oldIndex, newIndex));
  };

  return <SortableList items={items} onSortEnd={onSortEnd} />;
};
```

---

## Detailed Prop API

### SortableContainer HOC

| Property          | Type       | Default | Description                                                          |
| :---------------- | :--------- | :------ | :------------------------------------------------------------------- |
| **axis**          | `string`   | `'y'`   | Sorting direction: `'x'`, `'y'`, or `'xy'`.                          |
| **lockAxis**      | `string`   | -       | Lock movement to `'x'` or `'y'`.                                     |
| **pressDelay**    | `number`   | `0`     | Delay (ms) before sorting starts (recommended for mobile: `200`).    |
| **distance**      | `number`   | `0`     | Drag distance required (px) before sorting starts.                   |
| **useDragHandle** | `boolean`  | `false` | Use if you're wrapping a sub-element with `SortableHandle`.          |
| **onSortStart**   | `function` | -       | Callback: `({node, index, collection, isKeySorting}, event)`.        |
| **onSortEnd**     | `function` | -       | Callback: `({oldIndex, newIndex, collection, isKeySorting}, event)`. |
| **helperClass**   | `string`   | -       | CSS class applied to the floating helper item.                       |

### SortableElement HOC

| Property       | Type               | Default | Description                                                    |
| :------------- | :----------------- | :------ | :------------------------------------------------------------- |
| **index**      | `number`           | -       | **Required**. The position of the item in the collection.      |
| **collection** | `string \| number` | `0`     | Useful for managing multiple sortable groups in one container. |
| **disabled**   | `boolean`          | `false` | Disables sorting for this specific item.                       |

---

## 🛠 React 19 Migration Deep-Dive

### Why is `forwardRef` now required?

In React 19, the underlying `findDOMNode` API is deprecated. To ensure high performance and accurate positioning without using deprecated APIs, the library now relies on direct ref access to the DOM elements. Wrapping your functional components in `forwardRef` is the way to grant the HOC access to the DOM node.

### Troubleshooting "Older version of React" Errors

If you see the error _"A React Element from an older version of React was rendered"_, ensure that your bundler (Webpack/Vite) is not including multiple copies of React.

In a monorepo, it is recommended to add a resolve alias to your bundler:

```js

## Licensing & Contributions

Distributed under the MIT License. Contributions are welcome for bug fixes and compatibility updates.
```