Higher-order components to turn any list into animated, accessible and touch-friendly sortable lists
npx @tessl/cli install tessl/npm-react-sortable-hoc@2.0.00
# React Sortable HOC
1
2
React Sortable HOC is a set of higher-order components that transform any list into animated, accessible, and touch-friendly sortable lists. It provides smooth 60 FPS animations with drag handles, auto-scrolling, axis locking, keyboard navigation, and extensive event handling for creating sophisticated interactive UI components.
3
4
## Package Information
5
6
- **Package Name**: react-sortable-hoc
7
- **Package Type**: npm
8
- **Language**: JavaScript/TypeScript
9
- **Installation**: `npm install react-sortable-hoc`
10
11
## Core Imports
12
13
```typescript
14
import { SortableContainer, SortableElement, SortableHandle, arrayMove, isSortableHandle, SortableContext } from 'react-sortable-hoc';
15
```
16
17
Alternative lowercase imports (identical functionality):
18
19
```typescript
20
import { sortableContainer, sortableElement, sortableHandle } from 'react-sortable-hoc';
21
```
22
23
**Note:** The lowercase imports are aliases for the uppercase versions and provide identical functionality.
24
25
For CommonJS:
26
27
```javascript
28
const { SortableContainer, SortableElement, SortableHandle, arrayMove, isSortableHandle, SortableContext } = require('react-sortable-hoc');
29
```
30
31
## Basic Usage
32
33
```typescript
34
import React, { Component } from 'react';
35
import { SortableContainer, SortableElement } from 'react-sortable-hoc';
36
import { arrayMove } from 'array-move';
37
38
const SortableItem = SortableElement(({ value }) => <li>{value}</li>);
39
40
const SortableList = SortableContainer(({ items }) => {
41
return (
42
<ul>
43
{items.map((value, index) => (
44
<SortableItem key={`item-${value}`} index={index} value={value} />
45
))}
46
</ul>
47
);
48
});
49
50
class SortableComponent extends Component {
51
state = {
52
items: ['Item 1', 'Item 2', 'Item 3', 'Item 4', 'Item 5', 'Item 6'],
53
};
54
55
onSortEnd = ({ oldIndex, newIndex }) => {
56
this.setState(({ items }) => ({
57
items: arrayMove(items, oldIndex, newIndex),
58
}));
59
};
60
61
render() {
62
return <SortableList items={this.state.items} onSortEnd={this.onSortEnd} />;
63
}
64
}
65
```
66
67
## Architecture
68
69
React Sortable HOC is built around several key components:
70
71
- **Higher-Order Components**: Three main HOCs (`SortableContainer`, `SortableElement`, `SortableHandle`) that enhance existing React components with sortable functionality
72
- **Event System**: Comprehensive mouse, touch, and keyboard event handling with customizable callbacks
73
- **Animation Engine**: 60 FPS animations using CSS transforms with configurable transition durations
74
- **Manager System**: Internal state management for tracking sortable elements and coordinating drag operations
75
- **Auto-Scrolling**: Automatic container scrolling during drag operations with customizable thresholds
76
- **Accessibility**: Full keyboard navigation support with ARIA-friendly interactions
77
78
## Capabilities
79
80
### Sortable Container
81
82
Higher-order component that makes any component capable of containing sortable elements. Provides comprehensive configuration for animations, constraints, events, and behavior.
83
84
```typescript { .api }
85
function SortableContainer<P>(
86
wrappedComponent: WrappedComponent<P>,
87
config?: Config
88
): React.ComponentClass<P & SortableContainerProps>;
89
90
interface SortableContainerProps {
91
axis?: 'x' | 'y' | 'xy';
92
lockAxis?: 'x' | 'y';
93
helperClass?: string;
94
transitionDuration?: number;
95
keyboardSortingTransitionDuration?: number;
96
pressDelay?: number;
97
pressThreshold?: number;
98
distance?: number;
99
shouldCancelStart?: (event: SortEvent | SortEventWithTag) => boolean;
100
updateBeforeSortStart?: SortStartHandler;
101
onSortStart?: SortStartHandler;
102
onSortMove?: SortMoveHandler;
103
onSortEnd?: SortEndHandler;
104
onSortOver?: SortOverHandler;
105
useDragHandle?: boolean;
106
useWindowAsScrollContainer?: boolean;
107
hideSortableGhost?: boolean;
108
lockToContainerEdges?: boolean;
109
lockOffset?: Offset | [Offset, Offset];
110
getContainer?: ContainerGetter;
111
getHelperDimensions?: (sort: SortStart) => Dimensions;
112
helperContainer?: HTMLElement | HelperContainerGetter;
113
disableAutoscroll?: boolean;
114
keyCodes?: {
115
lift?: number[];
116
drop?: number[];
117
cancel?: number[];
118
up?: number[];
119
down?: number[];
120
};
121
}
122
```
123
124
[Sortable Container](./sortable-container.md)
125
126
### Sortable Element
127
128
Higher-order component that makes individual elements sortable within a SortableContainer. Simple interface focused on positioning and state management.
129
130
```typescript { .api }
131
function SortableElement<P>(
132
wrappedComponent: WrappedComponent<P>,
133
config?: Config
134
): React.ComponentClass<P & SortableElementProps>;
135
136
interface SortableElementProps {
137
index: number;
138
collection?: Offset;
139
disabled?: boolean;
140
}
141
```
142
143
[Sortable Element](./sortable-element.md)
144
145
### Sortable Handle
146
147
Higher-order component that creates designated drag areas within sortable elements. Enables fine-grained control over drag initiation.
148
149
```typescript { .api }
150
function SortableHandle<P>(
151
wrappedComponent: WrappedComponent<P>,
152
config?: Config
153
): React.ComponentClass<P>;
154
```
155
156
[Sortable Handle](./sortable-handle.md)
157
158
### Array Utilities
159
160
Utility function for reordering arrays after sort operations (deprecated - use separate 'array-move' package).
161
162
```typescript { .api }
163
function arrayMove<T>(
164
collection: T[],
165
previousIndex: number,
166
newIndex: number
167
): T[];
168
```
169
170
[Array Utilities](./array-utilities.md)
171
172
### Utility Functions
173
174
Helper functions and context for working with sortable handles and drag state.
175
176
```typescript { .api }
177
function isSortableHandle(node: Element): boolean;
178
179
const SortableContext: React.Context<{
180
manager: Manager;
181
}>;
182
```
183
184
## Types
185
186
```typescript { .api }
187
type Axis = 'x' | 'y' | 'xy';
188
type Offset = number | string;
189
type SortEvent = React.MouseEvent<any> | React.TouchEvent<any>;
190
191
interface SortStart {
192
node: Element;
193
index: number;
194
collection: Offset;
195
isKeySorting: boolean;
196
nodes: HTMLElement[];
197
helper: HTMLElement;
198
}
199
200
interface SortOver {
201
index: number;
202
oldIndex: number;
203
newIndex: number;
204
collection: Offset;
205
isKeySorting: boolean;
206
nodes: HTMLElement[];
207
helper: HTMLElement;
208
}
209
210
interface SortEnd {
211
oldIndex: number;
212
newIndex: number;
213
collection: Offset;
214
isKeySorting: boolean;
215
nodes: HTMLElement[];
216
}
217
218
interface Dimensions {
219
width: number;
220
height: number;
221
}
222
223
interface Config {
224
withRef: boolean;
225
}
226
227
type WrappedComponent<P> =
228
| React.ComponentClass<P>
229
| React.SFC<P>
230
| WrappedComponentFactory<P>;
231
232
type WrappedComponentFactory<P> = (props: P) => JSX.Element;
233
234
type SortStartHandler = (sort: SortStart, event: SortEvent) => void;
235
type SortMoveHandler = (event: SortEvent) => void;
236
type SortEndHandler = (sort: SortEnd, event: SortEvent) => void;
237
type SortOverHandler = (sort: SortOver, event: SortEvent) => void;
238
type ContainerGetter = (element: React.ReactElement<any>) => HTMLElement | Promise<HTMLElement>;
239
type HelperContainerGetter = () => HTMLElement;
240
241
interface Manager {
242
refs: { [key: string]: HTMLElement };
243
}
244
```