or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

array-utilities.mdindex.mdsortable-container.mdsortable-element.mdsortable-handle.md

sortable-container.mddocs/

0

# Sortable Container

1

2

Higher-order component that transforms any React component into a container capable of holding sortable elements. Provides comprehensive configuration for drag behavior, animations, constraints, and event handling.

3

4

## Capabilities

5

6

### SortableContainer HOC

7

8

Creates a sortable container from any React component.

9

10

```typescript { .api }

11

/**

12

* Higher-order component that makes a component capable of containing sortable elements

13

* @param wrappedComponent - The React component to enhance with sortable functionality

14

* @param config - Optional configuration object

15

* @returns Enhanced React component with sortable container capabilities

16

*/

17

function SortableContainer<P>(

18

wrappedComponent: WrappedComponent<P>,

19

config?: Config

20

): React.ComponentClass<P & SortableContainerProps>;

21

22

interface Config {

23

withRef: boolean;

24

}

25

26

interface SortableContainerProps {

27

// Sorting Direction & Constraints

28

axis?: Axis;

29

lockAxis?: Axis;

30

lockToContainerEdges?: boolean;

31

lockOffset?: Offset | [Offset, Offset];

32

33

// Animation & Visual

34

helperClass?: string;

35

transitionDuration?: number;

36

keyboardSortingTransitionDuration?: number;

37

hideSortableGhost?: boolean;

38

39

// Trigger Behavior

40

pressDelay?: number;

41

pressThreshold?: number;

42

distance?: number;

43

useDragHandle?: boolean;

44

45

// Event Handlers

46

shouldCancelStart?: (event: SortEvent | SortEventWithTag) => boolean;

47

updateBeforeSortStart?: SortStartHandler;

48

onSortStart?: SortStartHandler;

49

onSortMove?: SortMoveHandler;

50

onSortEnd?: SortEndHandler;

51

onSortOver?: SortOverHandler;

52

53

// Scrolling & Container

54

useWindowAsScrollContainer?: boolean;

55

disableAutoscroll?: boolean;

56

getContainer?: ContainerGetter;

57

helperContainer?: HTMLElement | HelperContainerGetter;

58

getHelperDimensions?: (sort: SortStart) => Dimensions;

59

60

// Keyboard Navigation

61

keyCodes?: KeyCodes;

62

}

63

64

interface KeyCodes {

65

lift?: number[];

66

drop?: number[];

67

cancel?: number[];

68

up?: number[];

69

down?: number[];

70

}

71

```

72

73

**Usage Examples:**

74

75

```typescript

76

import React from 'react';

77

import { SortableContainer, SortableElement } from 'react-sortable-hoc';

78

79

// Basic sortable list

80

const SortableList = SortableContainer(({ items }) => {

81

return (

82

<ul>

83

{items.map((value, index) => (

84

<SortableItem key={`item-${value}`} index={index} value={value} />

85

))}

86

</ul>

87

);

88

});

89

90

// With configuration options

91

const AdvancedSortableList = SortableContainer(({ items }) => (

92

<div className="grid">

93

{items.map((item, index) => (

94

<SortableGridItem key={item.id} index={index} item={item} />

95

))}

96

</div>

97

));

98

99

// Usage with props

100

<AdvancedSortableList

101

items={items}

102

axis="xy"

103

helperClass="sortable-helper"

104

transitionDuration={200}

105

pressDelay={100}

106

onSortEnd={handleSortEnd}

107

useDragHandle={true}

108

/>

109

```

110

111

### Core Configuration Props

112

113

#### Sorting Direction

114

115

```typescript { .api }

116

/** Items can be sorted horizontally, vertically or in a grid */

117

axis?: 'x' | 'y' | 'xy'; // default: 'y'

118

119

/** Lock movement to an axis while sorting */

120

lockAxis?: 'x' | 'y';

121

```

122

123

#### Animation & Visual Props

124

125

```typescript { .api }

126

/** CSS class to add to the sortable helper element */

127

helperClass?: string;

128

129

/** Duration of transition when elements shift positions (ms) */

130

transitionDuration?: number; // default: 300

131

132

/** Duration for keyboard sorting transitions (ms) */

133

keyboardSortingTransitionDuration?: number; // defaults to transitionDuration

134

135

/** Whether to auto-hide the element being sorted */

136

hideSortableGhost?: boolean; // default: true

137

```

138

139

#### Trigger Behavior Props

140

141

```typescript { .api }

142

/** Time to wait before sorting begins (ms) - good for mobile */

143

pressDelay?: number; // default: 0

144

145

/** Pixels of movement to tolerate before ignoring press event */

146

pressThreshold?: number; // default: 5

147

148

/** Distance to drag before sorting begins (pixels) */

149

distance?: number; // default: 0

150

151

/** Whether to use drag handles for sorting */

152

useDragHandle?: boolean; // default: false

153

```

154

155

### Event Handler Props

156

157

#### Core Event Handlers

158

159

```typescript { .api }

160

/** Function to determine if sorting should be cancelled */

161

shouldCancelStart?: (event: SortEvent | SortEventWithTag) => boolean;

162

163

/** Async function called before sorting begins */

164

updateBeforeSortStart?: SortStartHandler;

165

166

/** Callback when sorting begins */

167

onSortStart?: SortStartHandler;

168

169

/** Callback during sorting as cursor moves */

170

onSortMove?: SortMoveHandler;

171

172

/** Callback when moving over an item */

173

onSortOver?: SortOverHandler;

174

175

/** Callback when sorting ends */

176

onSortEnd?: SortEndHandler;

177

```

178

179

**Event Handler Examples:**

180

181

```typescript

182

const handleSortStart = ({ node, index, collection, isKeySorting }, event) => {

183

console.log('Sorting started:', { index, collection, isKeySorting });

184

};

185

186

const handleSortEnd = ({ oldIndex, newIndex, collection, isKeySorting }, event) => {

187

if (oldIndex !== newIndex) {

188

const newItems = arrayMove(items, oldIndex, newIndex);

189

setItems(newItems);

190

}

191

};

192

193

const shouldCancel = (event) => {

194

// Don't sort if clicking on buttons or inputs

195

return ['INPUT', 'BUTTON', 'SELECT'].includes(event.target.tagName);

196

};

197

198

<SortableList

199

items={items}

200

onSortStart={handleSortStart}

201

onSortEnd={handleSortEnd}

202

shouldCancelStart={shouldCancel}

203

/>

204

```

205

206

### Advanced Configuration Props

207

208

#### Container & Scrolling

209

210

```typescript { .api }

211

/** Use window as the scrolling container */

212

useWindowAsScrollContainer?: boolean; // default: false

213

214

/** Disable autoscrolling while dragging */

215

disableAutoscroll?: boolean; // default: false

216

217

/** Function to return the scrollable container element */

218

getContainer?: ContainerGetter;

219

220

/** Container for the sortable helper element */

221

helperContainer?: HTMLElement | HelperContainerGetter; // default: document.body

222

223

/** Function to compute helper dimensions */

224

getHelperDimensions?: (sort: SortStart) => Dimensions;

225

```

226

227

#### Constraint Props

228

229

```typescript { .api }

230

/** Lock movement to container edges */

231

lockToContainerEdges?: boolean; // default: false

232

233

/** Offset distance from container edges when locked */

234

lockOffset?: Offset | [Offset, Offset]; // default: '50%'

235

```

236

237

**Constraint Examples:**

238

239

```typescript

240

// Lock to container with 10px margins

241

<SortableList

242

items={items}

243

lockToContainerEdges={true}

244

lockOffset="10px"

245

onSortEnd={handleSortEnd}

246

/>

247

248

// Different lock offsets for top/bottom

249

<SortableList

250

items={items}

251

lockToContainerEdges={true}

252

lockOffset={["0%", "100%"]}

253

onSortEnd={handleSortEnd}

254

/>

255

```

256

257

### Keyboard Navigation

258

259

#### Key Code Configuration

260

261

```typescript { .api }

262

/** Keyboard navigation key codes */

263

keyCodes?: {

264

lift?: number[]; // default: [32] (SPACE)

265

drop?: number[]; // default: [32] (SPACE)

266

cancel?: number[]; // default: [27] (ESC)

267

up?: number[]; // default: [38, 37] (UP, LEFT)

268

down?: number[]; // default: [40, 39] (DOWN, RIGHT)

269

};

270

```

271

272

**Keyboard Navigation Example:**

273

274

```typescript

275

// Custom key bindings

276

<SortableList

277

items={items}

278

keyCodes={{

279

lift: [13, 32], // Enter or Space to lift

280

drop: [13, 32], // Enter or Space to drop

281

cancel: [27], // Escape to cancel

282

up: [38, 87], // Up arrow or W

283

down: [40, 83], // Down arrow or S

284

}}

285

onSortEnd={handleSortEnd}

286

/>

287

```

288

289

## withRef Configuration

290

291

```typescript { .api }

292

interface Config {

293

/** Enable access to wrapped component instance */

294

withRef: boolean;

295

}

296

```

297

298

**withRef Example:**

299

300

```typescript

301

const SortableList = SortableContainer(ListComponent, { withRef: true });

302

303

// Access wrapped instance

304

const listRef = useRef();

305

const wrappedInstance = listRef.current?.getWrappedInstance();

306

307

<SortableList ref={listRef} items={items} onSortEnd={handleSortEnd} />

308

```

309

310

## SortableContext

311

312

React context that provides access to the internal sortable manager. Primarily used for advanced integrations and custom components.

313

314

```typescript { .api }

315

/**

316

* React context providing access to sortable manager

317

*/

318

const SortableContext: React.Context<{

319

manager: Manager;

320

}>;

321

```

322

323

**Usage Examples:**

324

325

```typescript

326

import React, { useContext } from 'react';

327

import { SortableContext } from 'react-sortable-hoc';

328

329

// Access sortable manager from context

330

const CustomSortableComponent = () => {

331

const { manager } = useContext(SortableContext);

332

333

// Use manager for advanced operations

334

const handleCustomAction = () => {

335

console.log('Sortable elements:', manager.refs);

336

};

337

338

return (

339

<div onClick={handleCustomAction}>

340

Custom sortable component

341

</div>

342

);

343

};

344

345

// Use within SortableContainer

346

const SortableList = SortableContainer(({ items }) => (

347

<ul>

348

{items.map((value, index) => (

349

<SortableItem key={`item-${index}`} index={index} value={value} />

350

))}

351

<CustomSortableComponent />

352

</ul>

353

));

354

```

355

356

**Note:** SortableContext is an advanced API primarily intended for library authors and complex integrations. Most applications should use the standard SortableContainer, SortableElement, and SortableHandle components.