Skip to content

Commit 1f5e37d

Browse files
author
Wayne Van Son
authored
Merge pull request #104 from waynevanson/bugfix.multidrag1
Bugfix.multidrag1 Closes basically all the issues available.
2 parents cb8ae99 + 064d2f5 commit 1f5e37d

27 files changed

+1448
-934
lines changed

README.md

Lines changed: 169 additions & 96 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,14 @@ Consider trying it out if you had any troubles earlier.
88

99
## Things still to do.
1010

11-
We've released version 2.0,
11+
We've released version 2.0 but there are still some things to do. We needed public feedback and a major release was the easiest way to get it.
1212

1313
- [x] Create examples from [SortableJS Examples](https://sortablejs.github.io/Sortable/)
14-
- [ ] Create all tests for examples (for 'ron)
15-
- Currently weve got a few.
14+
- [ ] Examples with code underneath.
15+
- [ ] List Props in readme.
16+
- [ ] Allow React to manage class names. Halfway there.
17+
- [x] Write docs for plugins
18+
- [ ] Create all tests for examples (for 'ron). Started
1619
- [ ] Test the following UI component libraries:
1720
- [x] Styled Components
1821
- [ ] AntD
@@ -22,6 +25,40 @@ We've released version 2.0,
2225
- [ ] React Toolbox
2326
- [ ] Your suggestion? :)
2427

28+
29+
## Table of Contents
30+
<!-- START doctoc generated TOC please keep comment here to allow auto update -->
31+
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
32+
33+
34+
- [Features](#features)
35+
- [SortableJS](#sortablejs)
36+
- [Component Specific](#component-specific)
37+
- [Installation](#installation)
38+
- [Learn](#learn)
39+
- [Usage/Examples](#usageexamples)
40+
- [Function Component](#function-component)
41+
- [Class Component](#class-component)
42+
- [Plugins](#plugins)
43+
- [Sortable API](#sortable-api)
44+
- [React API](#react-api)
45+
- [id, className, style](#id-classname-style)
46+
- [list](#list)
47+
- [setList](#setlist)
48+
- [clone](#clone)
49+
- [tag](#tag)
50+
- [HTML Element](#html-element)
51+
- [Custom Component](#custom-component)
52+
- [How does it work?](#how-does-it-work)
53+
- [Caveats / Gotchas](#caveats--gotchas)
54+
- [`key !== index`](#key--index)
55+
- [Nesting](#nesting)
56+
- [Problem](#problem)
57+
- [What does work?](#what-does-work)
58+
- [Solutions](#solutions)
59+
60+
<!-- END doctoc generated TOC please keep comment here to allow auto update -->
61+
2562
## Features
2663

2764
### SortableJS
@@ -43,16 +80,23 @@ If you find any features lacking, create an issue and/or pull request.
4380
## Installation
4481

4582
```shell
46-
npm install --save react-sortablejs-typescript
83+
npm install --save react-sortablejs
4784
# OR
48-
yarn add react-sortablejs-typescript
85+
yarn add react-sortablejs
4986
```
5087

51-
## What you should endeavour to know.
88+
Please note that `sortablejs` is not required, as it's bundled in this component.
89+
90+
## Learn
91+
92+
Here is the TLDR of what sortable is:
5293

53-
- Explore the [Sortable Options API](https://github.com/SortableJS/Sortable#options)
54-
- Array.map
55-
- React.forwardRef
94+
```md
95+
- Shopping List: # list of items / sortable. This represents `react-sortablejs`
96+
- eggs # list item. These are all the items in the list and is what you move around.
97+
- bread # list item
98+
- milk # list item
99+
```
56100

57101
## Usage/Examples
58102

@@ -112,34 +156,37 @@ export class BasicClass extends Component<{}, BasicClassState> {
112156
}
113157
```
114158

115-
### ReactSortable renders a `div` as the parent by default.
159+
## Plugins
116160

117-
ReactSortable is a `div` element by default. This can be changed to be any HTML element (for example `ul`, `ol`)
118-
or can be a React component.
161+
Sortable has some pretty cool pplugins such as MultiDrag and Swap.
119162

120-
This value, be the component or the HTML element should be passed down under `props.tag`.
163+
By Default:
121164

122-
Let's explore both here.
165+
- AutoScroll is premounted and enabled.
166+
- OnSpill is premounted and NOT enabled.
167+
- MultiDrag and Swap and NOT premounted and NOT enabled
123168

124-
#### HTML Element
125-
126-
Here we will use a `ul`. You can use any HTML.
127-
Just add the string and ReactSortable will use a `li` instead of a `div`.
169+
You must mount mount the plugin with sortable **ONCE ONLY**.
128170

129171
```tsx
130-
import React, { FC, useState, forwardRef } from "react";
131-
import { ReactSortable } from "react-sortablejs-typescript";
172+
import React from "react";
173+
import { ReactSortable, Sortable, MultiDrag, Swap } from "react-sortablejs";
132174

133-
interface ItemType {
134-
id: string;
135-
name: string;
136-
}
175+
// mount whatever plugins you'd like to. These are the only current options.
176+
Sortable.mount(new MultiDrag(), new Swap());
137177

138-
export const BasicFunction: FC = props => {
139-
const [state, setState] = useState<ItemType[]>([{ id: "1", name: "shrek" }]);
178+
const App = () => {
179+
const [state, setState] = useState([
180+
{ id: 1, name: "shrek" },
181+
{ id: 2, name: "fiona" }
182+
]);
140183

141184
return (
142-
<ReactSortable tag="ul" list={state} setList={setState}>
185+
<ReactSortable
186+
multiDrag // enables mutidrag
187+
// OR
188+
swap // enables swap
189+
>
143190
{state.map(item => (
144191
<div key={item.id}>{item.name}</div>
145192
))}
@@ -148,44 +195,41 @@ export const BasicFunction: FC = props => {
148195
};
149196
```
150197

151-
#### Custom Component
152-
153-
When using a custom component in the `tag` prop, the only component it allows is a `forwardRef` component.
154-
155-
#### Solution
198+
## Sortable API
156199

157-
If it doesn't have one, you can add one using `React.forwardRef()`.
158-
This fantastic API allows the ref to be visible when creating components.
159-
160-
Use this when third party UI libraries.
200+
For a comprehensive list of options, please visit https://github.com/SortableJS/Sortable#options.
161201

162-
**NOTE:** You may experience inconsistencies with this until we launch the proper version.
163-
164-
> todo: Some third party UI components may have nested elements to create the look they're after.
165-
> This could be an issue and not sure how to fix.
202+
Those options are applied as follows.
166203

167204
```tsx
168-
import React, { FC, useState, forwardRef } from "react";
169-
import { ReactSortable } from "react-sortablejs-typescript";
205+
Sortable.create(element, {
206+
group: " groupName",
207+
animation: 200,
208+
delayOnTouchStart: true,
209+
delay: 2
210+
});
170211

171-
interface ItemType {
172-
id: string;
173-
name: string;
174-
}
212+
// --------------------------
213+
// Will now be..
214+
// --------------------------
175215

176-
// This is just like a normal component, but the
177-
const CustomComponent = forwardRef<HTMLDivElement, any>((props, ref) => {
178-
return <div ref={ref}>{props.children}</div>;
179-
});
216+
import React from "react";
217+
import { ReactSortable } from "react-sortablejs";
180218

181-
export const BasicFunction: FC = props => {
182-
const [state, setState] = useState<ItemType[]>([
219+
const App = () => {
220+
const [state, setState] = useState([
183221
{ id: 1, name: "shrek" },
184222
{ id: 2, name: "fiona" }
185223
]);
186224

187225
return (
188-
<ReactSortable tag={CustomComponent} list={state} setList={setState}>
226+
<ReactSortable
227+
// here they are!
228+
group="groupName"
229+
animation={200}
230+
delayOnTouchStart={true}
231+
delay={2}
232+
>
189233
{state.map(item => (
190234
<div key={item.id}>{item.name}</div>
191235
))}
@@ -194,84 +238,98 @@ export const BasicFunction: FC = props => {
194238
};
195239
```
196240

197-
## How does it work?
241+
## React API
198242

199-
Sortable affects the DOM, adding, and removing nodes/css when it needs to in order to achieve the smooth transitions we all know an love.
200-
This component reverses many of it's actions of the DOM so React can handle this when the state changes.
243+
### id, className, style
201244

202-
## Caveats / Gotchas
245+
Thes are all defaults DOM attributes. Nothing special here.
203246

204-
### `key !== index`
247+
### list
205248

206-
DO NOT use the index as a key for your list items. Sorting will not work.
249+
The same as `state` in `const [ state, setState] = useState([{ id: 1}, {id: 2}])`
207250

208-
In all the examples above, I used an object with an ID. You should do the same!
251+
`state` must be an array of items, with each item being an object that has the following shape:
209252

210-
I may even enforce this into the design to eliminate errors.
253+
```ts
254+
/** The unique id associated with your item. It's recommended this is the same as the key prop for your list item. */
255+
id: string | number;
256+
/** When true, the item is selected using MultiDrag */
257+
selected?: boolean;
258+
/** When true, the item is deemed "chosen", which basically just a mousedown event. */
259+
chosen?: boolean;
260+
/** When true, it will not be possible to pick this item up in the list. */
261+
filtered?: boolean;
262+
[property: string]: any;
263+
```
211264

212-
### `setState()`
265+
### setList
213266

214-
#### Problem
267+
The same as `setState` in `const [ state, setState] = useState([{ id: 1}, {id: 2}])`
215268

216-
`setState` takes one argument only. If we look in the type defs, it does say that it has a second argument, but it is already deprecated. ReactSortable passes three arguments to `setState`.
269+
### clone
217270

218-
If you pass the `setState` straight from a `useState` hook, it will work as expected. However, there will be a warning in the console:
271+
If you're using `{group: { name: 'groupName', pull: 'clone'}}`, this means your in 'clone' mode. You should provide a function for this.
219272

220-
> Warning: State updates from the useState() and useReducer() Hooks don't support the second callback argument.
221-
> To execute a side effect after rendering, declare it in the component body with useEffect().
273+
Check out the source code of the clone example for more information. I'll write it here soon.
222274

223-
It's just a warning and there's nothing to worry about. Nothing will break if you leave the messages there.
275+
### tag
276+
277+
ReactSortable is a `div` element by default. This can be changed to be any HTML element (for example `ul`, `ol`)
278+
or can be a React component.
279+
280+
This value, be the component or the HTML element should be passed down under `props.tag`.
281+
282+
Let's explore both here.
283+
284+
#### HTML Element
285+
286+
Here we will use a `ul`. You can use any HTML.
287+
Just add the string and ReactSortable will use a `li` instead of a `div`.
224288

225289
```tsx
226-
import React, { FC, useState } from "react";
290+
import React, { FC, useState, forwardRef } from "react";
227291
import { ReactSortable } from "react-sortablejs-typescript";
228292

229-
interface ItemType {
230-
id: string;
231-
name: string;
232-
}
233-
234293
export const BasicFunction: FC = props => {
235-
const [state, setState] = useState<ItemType[]>([{ id: "1", name: "shrek" }]);
294+
const [state, setState] = useState([{ id: "1", name: "shrek" }]);
236295

237296
return (
238-
<ReactSortable
239-
list={state}
240-
// will cause warnings in dev mode only.
241-
setList={setState}
242-
>
297+
<ReactSortable tag="ul" list={state} setList={setState}>
243298
{state.map(item => (
244-
<div key={item.id}>{item.name}</div>
299+
<li key={item.id}>{item.name}</li>
245300
))}
246301
</ReactSortable>
247302
);
248303
};
249304
```
250305

251-
This is just a warning, but can be annoying when developing.
306+
#### Custom Component
307+
308+
When using a custom component in the `tag` prop, the only component it allows is a `forwardRef` component.
309+
Currently we only support components who use the `React.forwardRef` API.
252310

253-
Instead of passing `setState` in directly, be explicit in your callback:
311+
If it doesn't have one, you can add one using `React.forwardRef()`.
312+
313+
> todo: Some third party UI components may have nested elements to create the look they're after.
314+
> This could be an issue and not sure how to fix.
254315
255316
```tsx
256-
import React, { FC, useState } from "react";
317+
import React, { FC, useState, forwardRef } from "react";
257318
import { ReactSortable } from "react-sortablejs-typescript";
258319

259-
interface ItemType {
260-
id: string;
261-
name: string;
262-
}
320+
// This is just like a normal component, but now has a ref.
321+
const CustomComponent = forwardRef<HTMLDivElement, any>((props, ref) => {
322+
return <div ref={ref}>{props.children}</div>;
323+
});
263324

264325
export const BasicFunction: FC = props => {
265-
const [state, setState] = useState<ItemType[]>([{ id: "1", name: "shrek" }]);
326+
const [state, setState] = useState([
327+
{ id: 1, name: "shrek" },
328+
{ id: 2, name: "fiona" }
329+
]);
266330

267331
return (
268-
// `sortable` and `store` arguments are here just to show what arguments have been passed.
269-
// They are not required to be used and you shouldn't really need them.
270-
<ReactSortable
271-
list={state}
272-
// will not cause warnings in dev mode only.
273-
setList={(newState, sortable, store) => setState(newState)}
274-
>
332+
<ReactSortable tag={CustomComponent} list={state} setList={setState}>
275333
{state.map(item => (
276334
<div key={item.id}>{item.name}</div>
277335
))}
@@ -280,6 +338,21 @@ export const BasicFunction: FC = props => {
280338
};
281339
```
282340

341+
## How does it work?
342+
343+
Sortable affects the DOM, adding, and removing nodes/css when it needs to in order to achieve the smooth transitions we all know an love.
344+
This component reverses many of it's actions of the DOM so React can handle this when the state changes.
345+
346+
## Caveats / Gotchas
347+
348+
### `key !== index`
349+
350+
DO NOT use the index as a key for your list items. Sorting will not work.
351+
352+
In all the examples above, I used an object with an ID. You should do the same!
353+
354+
I may even enforce this into the design to eliminate errors.
355+
283356
### Nesting
284357

285358
#### Problem

dist/index.d.ts

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
11
export { ReactSortable } from "./react-sortable";
22
export * from "./types";
3-
export { MultiDrag, Swap, DOMRect, Direction, GroupOptions, MoveEvent, Options, PullResult, PutResult, SortableEvent, SortableOptions, Utils } from "sortablejs";
4-
import SortableGlobal from "sortablejs";
5-
export declare const Sortable: typeof SortableGlobal;
3+
export { default as Sortable, MultiDrag, Swap, DOMRect, Direction, GroupOptions, MoveEvent, Options, PullResult, PutResult, SortableEvent, SortableOptions, Utils } from "sortablejs";
64
//# sourceMappingURL=index.d.ts.map

dist/index.d.ts.map

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)