Skip to content

Commit 301229e

Browse files
committed
Add updateOrder event streams
1 parent 72de31e commit 301229e

File tree

5 files changed

+92
-28
lines changed

5 files changed

+92
-28
lines changed

src/eventHandler.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
import { VNode } from '@cycle/dom';
22

3-
import { SortableOptions } from './makeSortable';
3+
import { SortableOptions, UpdateOrder } from './makeSortable';
44

55
import { mousedownHandler } from './eventHandlers/mousedown';
66
import { mouseupHandler } from './eventHandlers/mouseup';
77
import { mousemoveHandler } from './eventHandlers/mousemove';
88

99
export function handleEvent(
1010
options: SortableOptions
11-
): (node: VNode, event: MouseEvent) => VNode {
12-
return function(node: VNode, event: MouseEvent): VNode {
11+
): (data: [VNode, any], event: MouseEvent) => [VNode, UpdateOrder | undefined] {
12+
return function(data, event) {
1313
const eventHandlerMapping = {
1414
mousedown: mousedownHandler,
1515
touchstart: mousedownHandler,
@@ -19,6 +19,6 @@ export function handleEvent(
1919
mousemove: mousemoveHandler,
2020
touchmove: mousemoveHandler
2121
};
22-
return eventHandlerMapping[event.type](node, event, options);
22+
return eventHandlerMapping[event.type](data[0], event, options);
2323
};
2424
}

src/eventHandlers/mousedown.ts

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ export function mousedownHandler(
1616
node: VNode,
1717
ev: MouseEvent,
1818
opts: SortableOptions
19-
): VNode {
19+
): [VNode, undefined] {
2020
const item: Element = ev.currentTarget as Element;
2121
const indexClicked = [...item.parentElement.children].indexOf(item);
2222

@@ -29,15 +29,18 @@ export function mousedownHandler(
2929
] as VNode)
3030
);
3131

32-
return {
33-
...addDataEntry(node, 'style', {
34-
...selectNames
35-
.map(n => ({ [n]: 'none' }))
36-
.reduce((a, c) => ({ ...a, ...c }), {}),
37-
position: 'relative'
38-
}),
39-
children
40-
};
32+
return [
33+
{
34+
...addDataEntry(node, 'style', {
35+
...selectNames
36+
.map(n => ({ [n]: 'none' }))
37+
.reduce((a, c) => ({ ...a, ...c }), {}),
38+
position: 'relative'
39+
}),
40+
children
41+
},
42+
undefined
43+
];
4144
}
4245

4346
function addData(node: VNode, index: number): VNode {

src/eventHandlers/mousemove.ts

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
import { VNode } from '@cycle/dom';
22

3-
import { SortableOptions } from '../makeSortable';
3+
import { SortableOptions, UpdateOrder } from '../makeSortable';
44
import { addDataEntry } from '../helpers';
55

66
export function mousemoveHandler(
77
node: VNode,
88
ev: MouseEvent,
99
opts: SortableOptions
10-
): VNode {
10+
): [VNode, undefined | UpdateOrder] {
1111
const item: Element = (node.children as any[])
1212
.map(n => n.data.dataset.item)
1313
.filter(n => !!n)[0];
@@ -29,21 +29,32 @@ export function mousemoveHandler(
2929
swapIndex = index + 1;
3030
}
3131

32+
let updateOrder = undefined;
33+
3234
if (swapIndex !== index) {
3335
const tmp = children[index];
3436
children[index] = children[swapIndex];
3537
children[swapIndex] = tmp;
38+
39+
updateOrder = {
40+
indexMap: [],
41+
oldIndex: index,
42+
swapIndex: index
43+
};
3644
}
3745

3846
children[children.length - 1] = updateGhost(
3947
children[children.length - 1],
4048
ev
4149
);
4250

43-
return {
44-
...node,
45-
children
46-
};
51+
return [
52+
{
53+
...node,
54+
children
55+
},
56+
updateOrder
57+
];
4758
}
4859

4960
function getArea(item: Element): number {

src/eventHandlers/mouseup.ts

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,21 @@ export function mouseupHandler(
88
node: VNode,
99
ev: MouseEvent,
1010
opts: SortableOptions
11-
): VNode {
11+
): [VNode, undefined] {
1212
const children = node.children.slice(0, -1).map(cleanup);
1313

14-
return {
15-
...deleteData(node, 'style', ['position'].concat(selectNames), true),
16-
children
17-
};
14+
return [
15+
{
16+
...deleteData(
17+
node,
18+
'style',
19+
['position'].concat(selectNames),
20+
true
21+
),
22+
children
23+
},
24+
undefined
25+
];
1826
}
1927

2028
function cleanup(node: VNode): VNode {

src/makeSortable.ts

Lines changed: 45 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,12 @@ export interface SortableOptions {
2121
selectionDelay?: number;
2222
}
2323

24+
export interface UpdateOrder {
25+
indexMap: { [old: number]: number };
26+
oldIndex: number;
27+
newIndex: number;
28+
}
29+
2430
export function toSortable(options: SortableOptions): HOC {
2531
return component => makeSortable(component, options);
2632
}
@@ -81,22 +87,58 @@ export function makeSortable(
8187
.map(start => move$.endWhen(mouseup$))
8288
.flatten();
8389

84-
const vdom$: Stream<VNode> = childDOM$
90+
const data$: Stream<[VNode, UpdateOrder | undefined]> = childDOM$
8591
.map(dom =>
8692
xs
8793
.merge(mousedown$, mousemove$, mouseup$)
88-
.fold(eventHandler, dom)
94+
.fold(eventHandler, [dom, undefined])
8995
)
9096
.flatten();
9197

98+
const vdom$: Stream<VNode> = data$.map(([dom, _]) => dom);
99+
100+
const updateOrder$: Stream<UpdateOrder> = data$
101+
.map(([_, x]) => x)
102+
.filter(x => x !== undefined);
103+
104+
const updateAccumulated$: Stream<UpdateOrder> = mousedown$
105+
.mapTo(updateOrder$
106+
.fold(
107+
(acc, curr) => ({
108+
indexMap: acc.indexMap
109+
? Object.keys(acc.indexMap)
110+
.map(k => ({
111+
[k]: curr.indexMap[acc.indexMap[k]]
112+
}))
113+
.reduce((a, c) => ({ ...a, ...c }), {})
114+
: curr.indexMap,
115+
oldIndex:
116+
acc.oldIndex === -1 ? curr.oldIndex : acc.oldIndex,
117+
newIndex: curr.newIndex
118+
}),
119+
{
120+
indexMap: undefined,
121+
oldIndex: -1,
122+
newIndex: -1
123+
}
124+
)
125+
.drop(1) as Stream<UpdateOrder>)
126+
.flatten();
127+
128+
const updateDone$: Stream<UpdateOrder> = mouseup$
129+
.compose(sampleCombine(updateAccumulated$))
130+
.map(([_, x]) => x);
131+
92132
const dragInProgress$ = xs
93133
.merge(mousedown$, mouseup$)
94134
.fold(acc => !acc, false);
95135

96136
return {
97137
...sinks,
98138
DOM: adapt(vdom$),
99-
drag: adapt(dragInProgress$)
139+
drag: adapt(dragInProgress$),
140+
updateLive: adapt(updateOrder$),
141+
updateDone$: adapt(updateDone$)
100142
};
101143
};
102144
}

0 commit comments

Comments
 (0)