or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

configuration.mdcore-api.mdevents.mdindex.mdplugins.mdutilities.md

plugins.mddocs/

0

# Plugins

1

2

Extensible plugin architecture for advanced functionality like multi-drag, auto-scroll, and element swapping.

3

4

## Capabilities

5

6

### Plugin Registration

7

8

Mount plugins to extend Sortable functionality before creating sortable instances.

9

10

```javascript { .api }

11

/**

12

* Mount one or more plugins to extend Sortable functionality

13

* @param plugins - Plugin instances to register

14

*/

15

Sortable.mount(...plugins: SortablePlugin[]): void;

16

```

17

18

**Usage Examples:**

19

20

```javascript

21

import Sortable, { MultiDrag, AutoScroll, Swap, OnSpill } from "sortablejs";

22

23

// Mount individual plugins

24

Sortable.mount(new MultiDrag());

25

Sortable.mount(new AutoScroll());

26

27

// Mount multiple plugins at once

28

Sortable.mount(new MultiDrag(), new AutoScroll(), new Swap());

29

30

// Now create sortables with plugin functionality

31

const sortable = Sortable.create(el, {

32

multiDrag: true, // MultiDrag plugin option

33

selectedClass: 'selected',

34

scroll: true, // AutoScroll plugin option

35

scrollSensitivity: 100

36

});

37

```

38

39

### MultiDrag Plugin

40

41

Enables selection and simultaneous dragging of multiple elements.

42

43

```javascript { .api }

44

/**

45

* MultiDrag plugin options

46

*/

47

interface MultiDragOptions {

48

/** Enable multi-drag functionality */

49

multiDrag?: boolean;

50

51

/** CSS class for selected elements */

52

selectedClass?: string;

53

54

/** Key to hold for multi-selection (e.g., 'ctrl', 'meta') */

55

multiDragKey?: string | null;

56

57

/** Avoid implicit deselection when clicking outside */

58

avoidImplicitDeselect?: boolean;

59

}

60

```

61

62

**Usage Examples:**

63

64

```javascript

65

import Sortable, { MultiDrag } from "sortablejs";

66

67

Sortable.mount(new MultiDrag());

68

69

const sortable = Sortable.create(el, {

70

multiDrag: true,

71

selectedClass: 'selected',

72

multiDragKey: 'ctrl', // Ctrl+click to select multiple

73

74

onSelect: (evt) => {

75

console.log('Item selected:', evt.item);

76

},

77

78

onDeselect: (evt) => {

79

console.log('Item deselected:', evt.item);

80

}

81

});

82

83

// Programmatically select items

84

sortable.select(document.getElementById('item1'));

85

sortable.select(document.getElementById('item2'));

86

87

// Get selected items

88

const selected = sortable.selectedElements; // HTMLElement[]

89

90

// Deselect all

91

sortable.deselectAll();

92

```

93

94

### AutoScroll Plugin

95

96

Automatically scrolls containers when dragging near edges.

97

98

```javascript { .api }

99

/**

100

* AutoScroll plugin options

101

*/

102

interface AutoScrollOptions {

103

/** Enable auto-scrolling */

104

scroll?: boolean;

105

106

/** Auto-scroll container (defaults to window) */

107

scrollSensitivity?: number;

108

109

/** Auto-scroll speed */

110

scrollSpeed?: number;

111

112

/** Pixels from edge to trigger scrolling */

113

bubbleScroll?: boolean;

114

}

115

```

116

117

**Usage Examples:**

118

119

```javascript

120

import Sortable, { AutoScroll } from "sortablejs";

121

122

Sortable.mount(new AutoScroll());

123

124

const sortable = Sortable.create(el, {

125

scroll: true,

126

scrollSensitivity: 100, // 100px from edge triggers scroll

127

scrollSpeed: 20, // Scroll speed

128

bubbleScroll: true // Allow scrolling in nested containers

129

});

130

```

131

132

### Swap Plugin

133

134

Enables element swapping instead of insertion-based reordering.

135

136

```javascript { .api }

137

/**

138

* Swap plugin options

139

*/

140

interface SwapOptions {

141

/** Enable swap mode instead of insertion */

142

swap?: boolean;

143

144

/** CSS class applied to swap target */

145

swapClass?: string;

146

}

147

```

148

149

**Usage Examples:**

150

151

```javascript

152

import Sortable, { Swap } from "sortablejs";

153

154

Sortable.mount(new Swap());

155

156

const sortable = Sortable.create(el, {

157

swap: true,

158

swapClass: 'highlight-swap',

159

160

onSwap: (evt) => {

161

console.log('Elements swapped:', evt.item, evt.swapItem);

162

}

163

});

164

```

165

166

### OnSpill Plugin

167

168

Handles elements that are dragged outside valid drop zones.

169

170

```javascript { .api }

171

/**

172

* OnSpill plugin options

173

*/

174

interface OnSpillOptions {

175

/** Remove element when dragged outside valid drop zone */

176

removeOnSpill?: boolean;

177

178

/** Revert element to original position when spilled */

179

revertOnSpill?: boolean;

180

}

181

```

182

183

**Usage Examples:**

184

185

```javascript

186

import Sortable, { OnSpill } from "sortablejs";

187

188

Sortable.mount(new OnSpill());

189

190

const sortable = Sortable.create(el, {

191

removeOnSpill: true, // Remove element when dragged out

192

193

onSpill: (evt) => {

194

console.log('Element spilled:', evt.item);

195

// Custom handling for spilled elements

196

}

197

});

198

199

// Alternative: revert instead of remove

200

const revertSortable = Sortable.create(el2, {

201

revertOnSpill: true, // Return to original position when spilled

202

});

203

```

204

205

## Plugin Events

206

207

### MultiDrag Events

208

209

Additional events available when MultiDrag plugin is active.

210

211

```javascript { .api }

212

/** Called when an element is selected for multi-drag */

213

onSelect?: (evt: SortableEvent) => void;

214

215

/** Called when an element is deselected */

216

onDeselect?: (evt: SortableEvent) => void;

217

```

218

219

### Swap Events

220

221

Additional events available when Swap plugin is active.

222

223

```javascript { .api }

224

/** Called when two elements are swapped */

225

onSwap?: (evt: SortableEvent & { swapItem: HTMLElement }) => void;

226

```

227

228

### OnSpill Events

229

230

Additional events available when OnSpill plugin is active.

231

232

```javascript { .api }

233

/** Called when an element is dragged outside a valid drop zone */

234

onSpill?: (evt: SortableEvent) => void;

235

```

236

237

## Custom Plugin Development

238

239

### Plugin Interface

240

241

Structure for creating custom Sortable plugins.

242

243

```javascript { .api }

244

interface SortablePlugin {

245

/** Plugin name (must be unique) */

246

name: string;

247

248

/** Default options merged into Sortable defaults */

249

defaults?: { [key: string]: any };

250

251

/** Event options configuration for plugin events */

252

eventOptions?: { [key: string]: any };

253

254

/** Option change listeners for dynamic configuration */

255

optionListeners?: { [optionName: string]: (value: any) => any };

256

257

/** Plugin utilities to extend Sortable.utils */

258

utils?: { [key: string]: any };

259

260

/** Custom event properties injected into SortableEvent */

261

eventProperties?: (eventName: string) => { [key: string]: any };

262

263

/** Initialize plugin on sortable instance creation */

264

initializePlugin?: (sortable: Sortable) => void;

265

266

/** Plugin-specific methods available on sortable instance */

267

[key: string]: any;

268

}

269

```

270

271

**Custom Plugin Example:**

272

273

```javascript

274

// Comprehensive custom plugin demonstrating all interface features

275

const AdvancedLoggerPlugin = {

276

name: 'advancedLogger',

277

278

// Default options merged into Sortable defaults

279

defaults: {

280

logLevel: 'info',

281

logToConsole: true,

282

logToServer: false,

283

serverEndpoint: '/api/drag-logs'

284

},

285

286

// Custom utilities added to Sortable.utils

287

utils: {

288

formatLogMessage: (level, action, item) => {

289

return `[${new Date().toISOString()}] ${level.toUpperCase()}: ${action} - ${item.textContent}`;

290

}

291

},

292

293

// Custom event properties injected into all events

294

eventProperties: function(eventName) {

295

return {

296

logTimestamp: Date.now(),

297

sessionId: this.sessionId

298

};

299

},

300

301

// Option change listeners for dynamic reconfiguration

302

optionListeners: {

303

logLevel: function(newLevel) {

304

console.log(`Logger level changed to: ${newLevel}`);

305

return newLevel;

306

}

307

},

308

309

// Initialize plugin on sortable instance

310

initializePlugin(sortable) {

311

// Generate unique session ID

312

this.sessionId = Math.random().toString(36).substr(2, 9);

313

314

// Store reference for event handlers

315

const plugin = this;

316

const options = sortable.options;

317

318

// Enhanced logging methods on sortable instance

319

sortable.logDragAction = function(action, item) {

320

const message = plugin.utils.formatLogMessage(options.logLevel, action, item);

321

322

if (options.logToConsole) {

323

console.log(message);

324

}

325

326

if (options.logToServer) {

327

fetch(options.serverEndpoint, {

328

method: 'POST',

329

headers: { 'Content-Type': 'application/json' },

330

body: JSON.stringify({

331

sessionId: plugin.sessionId,

332

action,

333

timestamp: Date.now(),

334

item: item.textContent

335

})

336

});

337

}

338

};

339

340

// Hook into events

341

const originalOnStart = options.onStart;

342

const originalOnEnd = options.onEnd;

343

344

options.onStart = (evt) => {

345

sortable.logDragAction('DRAG_START', evt.item);

346

originalOnStart && originalOnStart(evt);

347

};

348

349

options.onEnd = (evt) => {

350

sortable.logDragAction('DRAG_END', evt.item);

351

originalOnEnd && originalOnEnd(evt);

352

};

353

}

354

};

355

356

// Mount and use the advanced plugin

357

Sortable.mount(AdvancedLoggerPlugin);

358

359

const sortable = Sortable.create(el, {

360

logLevel: 'debug',

361

logToServer: true,

362

serverEndpoint: '/api/custom-logs',

363

364

onAdd: (evt) => {

365

// Custom event properties are automatically available

366

console.log('Session ID:', evt.sessionId);

367

console.log('Log timestamp:', evt.logTimestamp);

368

}

369

});

370

371

// Plugin methods are available on sortable instance

372

sortable.logDragAction('CUSTOM_ACTION', document.getElementById('item1'));

373

374

// Plugin utilities are available globally

375

console.log(Sortable.utils.formatLogMessage('warn', 'TEST', { textContent: 'Test Item' }));

376

```

377

378

## Plugin Combinations

379

380

### Comprehensive Setup

381

382

Example showing multiple plugins working together.

383

384

```javascript

385

import Sortable, { MultiDrag, AutoScroll, Swap, OnSpill } from "sortablejs";

386

387

// Mount all plugins

388

Sortable.mount(new MultiDrag(), new AutoScroll(), new Swap(), new OnSpill());

389

390

const sortable = Sortable.create(el, {

391

// MultiDrag options

392

multiDrag: true,

393

selectedClass: 'selected',

394

multiDragKey: 'ctrl',

395

396

// AutoScroll options

397

scroll: true,

398

scrollSensitivity: 100,

399

scrollSpeed: 20,

400

401

// Swap options (mutually exclusive with normal sorting)

402

// swap: true,

403

// swapClass: 'highlight-swap',

404

405

// OnSpill options

406

revertOnSpill: true,

407

408

// Event handlers for plugin functionality

409

onSelect: (evt) => console.log('Selected:', evt.item),

410

onDeselect: (evt) => console.log('Deselected:', evt.item),

411

onSpill: (evt) => console.log('Spilled:', evt.item)

412

});

413

```

414

415

## Available Plugins Summary

416

417

```javascript { .api }

418

/**

419

* MultiDrag - Select and drag multiple elements simultaneously

420

*/

421

class MultiDrag implements SortablePlugin {

422

name: 'multiDrag';

423

select(element: HTMLElement): void;

424

deselect(element: HTMLElement): void;

425

deselectAll(): void;

426

selectedElements: HTMLElement[];

427

}

428

429

/**

430

* AutoScroll - Automatic scrolling when dragging near container edges

431

*/

432

class AutoScroll implements SortablePlugin {

433

name: 'autoScroll';

434

}

435

436

/**

437

* Swap - Element swapping instead of insertion-based reordering

438

*/

439

class Swap implements SortablePlugin {

440

name: 'swap';

441

}

442

443

/**

444

* OnSpill - Handle elements dragged outside valid drop zones

445

*/

446

class OnSpill implements SortablePlugin {

447

name: 'onSpill';

448

}

449

```