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.0React 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.
npm install react-sortable-hocimport { SortableContainer, SortableElement, SortableHandle, arrayMove, isSortableHandle, SortableContext } from 'react-sortable-hoc';Alternative lowercase imports (identical functionality):
import { sortableContainer, sortableElement, sortableHandle } from 'react-sortable-hoc';Note: The lowercase imports are aliases for the uppercase versions and provide identical functionality.
For CommonJS:
const { SortableContainer, SortableElement, SortableHandle, arrayMove, isSortableHandle, SortableContext } = require('react-sortable-hoc');import React, { Component } from 'react';
import { SortableContainer, SortableElement } from 'react-sortable-hoc';
import { arrayMove } from 'array-move';
const SortableItem = SortableElement(({ value }) => <li>{value}</li>);
const SortableList = SortableContainer(({ items }) => {
return (
<ul>
{items.map((value, index) => (
<SortableItem key={`item-${value}`} index={index} value={value} />
))}
</ul>
);
});
class SortableComponent extends Component {
state = {
items: ['Item 1', 'Item 2', 'Item 3', 'Item 4', 'Item 5', 'Item 6'],
};
onSortEnd = ({ oldIndex, newIndex }) => {
this.setState(({ items }) => ({
items: arrayMove(items, oldIndex, newIndex),
}));
};
render() {
return <SortableList items={this.state.items} onSortEnd={this.onSortEnd} />;
}
}React Sortable HOC is built around several key components:
SortableContainer, SortableElement, SortableHandle) that enhance existing React components with sortable functionalityHigher-order component that makes any component capable of containing sortable elements. Provides comprehensive configuration for animations, constraints, events, and behavior.
function SortableContainer<P>(
wrappedComponent: WrappedComponent<P>,
config?: Config
): React.ComponentClass<P & SortableContainerProps>;
interface SortableContainerProps {
axis?: 'x' | 'y' | 'xy';
lockAxis?: 'x' | 'y';
helperClass?: string;
transitionDuration?: number;
keyboardSortingTransitionDuration?: number;
pressDelay?: number;
pressThreshold?: number;
distance?: number;
shouldCancelStart?: (event: SortEvent | SortEventWithTag) => boolean;
updateBeforeSortStart?: SortStartHandler;
onSortStart?: SortStartHandler;
onSortMove?: SortMoveHandler;
onSortEnd?: SortEndHandler;
onSortOver?: SortOverHandler;
useDragHandle?: boolean;
useWindowAsScrollContainer?: boolean;
hideSortableGhost?: boolean;
lockToContainerEdges?: boolean;
lockOffset?: Offset | [Offset, Offset];
getContainer?: ContainerGetter;
getHelperDimensions?: (sort: SortStart) => Dimensions;
helperContainer?: HTMLElement | HelperContainerGetter;
disableAutoscroll?: boolean;
keyCodes?: {
lift?: number[];
drop?: number[];
cancel?: number[];
up?: number[];
down?: number[];
};
}Higher-order component that makes individual elements sortable within a SortableContainer. Simple interface focused on positioning and state management.
function SortableElement<P>(
wrappedComponent: WrappedComponent<P>,
config?: Config
): React.ComponentClass<P & SortableElementProps>;
interface SortableElementProps {
index: number;
collection?: Offset;
disabled?: boolean;
}Higher-order component that creates designated drag areas within sortable elements. Enables fine-grained control over drag initiation.
function SortableHandle<P>(
wrappedComponent: WrappedComponent<P>,
config?: Config
): React.ComponentClass<P>;Utility function for reordering arrays after sort operations (deprecated - use separate 'array-move' package).
function arrayMove<T>(
collection: T[],
previousIndex: number,
newIndex: number
): T[];Helper functions and context for working with sortable handles and drag state.
function isSortableHandle(node: Element): boolean;
const SortableContext: React.Context<{
manager: Manager;
}>;type Axis = 'x' | 'y' | 'xy';
type Offset = number | string;
type SortEvent = React.MouseEvent<any> | React.TouchEvent<any>;
interface SortStart {
node: Element;
index: number;
collection: Offset;
isKeySorting: boolean;
nodes: HTMLElement[];
helper: HTMLElement;
}
interface SortOver {
index: number;
oldIndex: number;
newIndex: number;
collection: Offset;
isKeySorting: boolean;
nodes: HTMLElement[];
helper: HTMLElement;
}
interface SortEnd {
oldIndex: number;
newIndex: number;
collection: Offset;
isKeySorting: boolean;
nodes: HTMLElement[];
}
interface Dimensions {
width: number;
height: number;
}
interface Config {
withRef: boolean;
}
type WrappedComponent<P> =
| React.ComponentClass<P>
| React.SFC<P>
| WrappedComponentFactory<P>;
type WrappedComponentFactory<P> = (props: P) => JSX.Element;
type SortStartHandler = (sort: SortStart, event: SortEvent) => void;
type SortMoveHandler = (event: SortEvent) => void;
type SortEndHandler = (sort: SortEnd, event: SortEvent) => void;
type SortOverHandler = (sort: SortOver, event: SortEvent) => void;
type ContainerGetter = (element: React.ReactElement<any>) => HTMLElement | Promise<HTMLElement>;
type HelperContainerGetter = () => HTMLElement;
interface Manager {
refs: { [key: string]: HTMLElement };
}