Skip to content

Commit d6e715a

Browse files
committed
Fix and test the update events
1 parent 301229e commit d6e715a

File tree

7 files changed

+191
-38
lines changed

7 files changed

+191
-38
lines changed

examples/simple/src/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,6 @@ function Child({ DOM }: Sources): Sinks {
3434
};
3535
}
3636

37-
run(main, {
37+
run(main as any, {
3838
DOM: makeDOMDriver('#app')
3939
});

examples/updateEvent/css/main.css

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
#app {
2+
font-size: 35px;
3+
}
4+
5+
html {
6+
box-sizing: border-box;
7+
}
8+
*, *:before, *:after {
9+
box-sizing: inherit;
10+
}
11+
12+
body, html {
13+
max-height: 100%;
14+
margin: 0;
15+
}
16+
17+
body {
18+
padding: 20px;
19+
}
20+
21+
ul {
22+
margin: 0;
23+
position: relative;
24+
}
25+
26+
li {
27+
/*padding: 5px;*/
28+
background: lightgray;
29+
}
30+
31+
li + li {
32+
margin-top: 5px;
33+
}
34+
35+
.ghost {
36+
border: 1px solid black;
37+
}

examples/updateEvent/index.html

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<!DOCTYPE html>
2+
<html>
3+
<head>
4+
<meta charset="utf-8" />
5+
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0">
6+
<meta name="description" content="Cycle.js example - Sortable"/>
7+
<link rel="stylesheet" href="css/main.css" type="text/css">
8+
<title>Cycle.js example - Sortable</title>
9+
</head>
10+
<body>
11+
<div id="app"></div>
12+
<script src="./index.js"></script>
13+
</body>
14+
</html>

examples/updateEvent/src/index.ts

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
import xs, { Stream } from 'xstream';
2+
import { run } from '@cycle/run';
3+
import {
4+
ul,
5+
li,
6+
p,
7+
h2,
8+
div,
9+
makeDOMDriver,
10+
DOMSource,
11+
VNode
12+
} from '@cycle/dom';
13+
14+
import { makeSortable } from '../../../src/makeSortable';
15+
16+
interface Sources {
17+
DOM: DOMSource;
18+
}
19+
20+
interface Sinks {
21+
DOM: Stream<VNode>;
22+
}
23+
24+
const sortable = makeSortable(Child, {
25+
itemSelector: '.li'
26+
});
27+
28+
function Child({ DOM }: Sources): Sinks {
29+
const vdom$: Stream<VNode> = xs.of(
30+
ul('.ul', [
31+
li('.li', '', ['Option 1']),
32+
li('.li', '', ['Option 2']),
33+
li('.li', '', ['Option 3']),
34+
li('.li', '', ['Option 4']),
35+
li('.li', '', ['Option 5']),
36+
li('.li', '', ['Option 6'])
37+
])
38+
);
39+
40+
return {
41+
DOM: vdom$
42+
};
43+
}
44+
45+
function main(sources: Sources): Sinks {
46+
const sinks = sortable(sources);
47+
48+
const vdom$ = xs
49+
.combine(
50+
sinks.DOM,
51+
sinks.dragging,
52+
sinks.updateLive.startWith(undefined),
53+
sinks.updateDone.startWith(undefined)
54+
)
55+
.map(([childDOM, isDragging, lastUpdate, update]) =>
56+
div([
57+
h2(['Event example']),
58+
childDOM,
59+
p(['Is dragging: ' + isDragging]),
60+
lastUpdate
61+
? p([
62+
'Last reordering: ' +
63+
lastUpdate.oldIndex +
64+
' to ' +
65+
lastUpdate.newIndex
66+
])
67+
: p(['Last reordering: none']),
68+
update
69+
? p([
70+
'Last completed reordering: ' +
71+
update.oldIndex +
72+
' to ' +
73+
update.newIndex
74+
])
75+
: p(['Last completed reordering: none'])
76+
])
77+
);
78+
79+
return {
80+
DOM: vdom$
81+
};
82+
}
83+
84+
run(main, {
85+
DOM: makeDOMDriver('#app')
86+
});

package.json

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,9 @@
1717
"build:examples": "tsc",
1818
"documentation": "typedoc --out docs src && touch docs/.nojekyll",
1919
"prepublishOnly": "npm run build && npm run documentation && cp-cli examples docs/",
20-
"examples": "npm run build:examples && npm run examples:simple && npm run examples:horizontal && npm run examples:parentSelector && npm run examples:updateEvent",
20+
"examples": "npm run build:examples && npm run examples:simple && npm run examples:horizontal && npm run examples:updateEvent",
2121
"examples:simple": "browserify build/examples/simple/src/index.js -o examples/simple/index.js && open-cli examples/simple/index.html",
2222
"examples:horizontal": "browserify build/examples/horizontal/src/index.js -o examples/horizontal/index.js && open-cli examples/horizontal/index.html",
23-
"examples:parentSelector": "browserify build/examples/parentSelector/src/index.js -o examples/parentSelector/index.js && open-cli examples/parentSelector/index.html",
2423
"examples:updateEvent": "browserify build/examples/updateEvent/src/index.js -o examples/updateEvent/index.js && open-cli examples/updateEvent/index.html"
2524
},
2625
"repository": {

src/eventHandlers/mousemove.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ export function mousemoveHandler(
2929
swapIndex = index + 1;
3030
}
3131

32-
let updateOrder = undefined;
32+
let updateOrder: UpdateOrder | undefined = undefined;
3333

3434
if (swapIndex !== index) {
3535
const tmp = children[index];
@@ -39,7 +39,7 @@ export function mousemoveHandler(
3939
updateOrder = {
4040
indexMap: [],
4141
oldIndex: index,
42-
swapIndex: index
42+
newIndex: swapIndex
4343
};
4444
}
4545

src/makeSortable.ts

Lines changed: 50 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,10 @@ import { adapt } from '@cycle/run/lib/adapt';
88
import { addKeys } from './helpers';
99
import { handleEvent } from './eventHandler';
1010

11-
export type Sources = any;
12-
export type Sinks = any;
13-
export type Component = (s: Sources) => Sinks;
14-
export type HOC = (c: Component) => Component;
11+
export type Component<So, Si> = (s: So) => Si;
12+
export type HOC<So, Si> = (
13+
c: Component<So, Si>
14+
) => Component<So, Si & SortableSinks>;
1515

1616
export interface SortableOptions {
1717
itemSelector: string;
@@ -27,23 +27,31 @@ export interface UpdateOrder {
2727
newIndex: number;
2828
}
2929

30-
export function toSortable(options: SortableOptions): HOC {
30+
export interface SortableSinks {
31+
dragging: Stream<boolean>;
32+
updateLive: Stream<UpdateOrder>;
33+
updateDone: Stream<UpdateOrder>;
34+
}
35+
36+
export function toSortable<Sources extends object, Sinks extends object>(
37+
options: SortableOptions
38+
): HOC<Sources, Sinks> {
3139
return component => makeSortable(component, options);
3240
}
3341

34-
export function makeSortable(
35-
main: Component,
42+
export function makeSortable<Sources extends object, Sinks extends object>(
43+
main: Component<Sources, Sinks>,
3644
options: SortableOptions
37-
): Component {
38-
return function(sources: Sources): Sinks {
45+
): Component<Sources, Sinks & SortableSinks> {
46+
return function(sources: Sources): Sinks & SortableSinks {
3947
if (!options.DOMDriverKey) {
4048
options.DOMDriverKey = 'DOM';
4149
}
4250
if (!options.TimeDriverKey) {
4351
options.TimeDriverKey = 'Time';
4452
}
4553

46-
const sinks = main(sources);
54+
const sinks: any = main(sources);
4755
const eventHandler = handleEvent(options);
4856

4957
const childDOM$: Stream<VNode> = xs
@@ -102,27 +110,36 @@ export function makeSortable(
102110
.filter(x => x !== undefined);
103111

104112
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>)
113+
.map(
114+
() =>
115+
updateOrder$
116+
.fold(
117+
(acc, curr) => ({
118+
indexMap: acc.indexMap
119+
? Object.keys(acc.indexMap)
120+
.map(k => ({
121+
[k]:
122+
curr.indexMap[acc.indexMap[k]]
123+
}))
124+
.reduce(
125+
(a, c) => ({ ...a, ...c }),
126+
{}
127+
)
128+
: curr.indexMap,
129+
oldIndex:
130+
acc.oldIndex === -1
131+
? curr.oldIndex
132+
: acc.oldIndex,
133+
newIndex: curr.newIndex
134+
}),
135+
{
136+
indexMap: undefined,
137+
oldIndex: -1,
138+
newIndex: -1
139+
}
140+
)
141+
.drop(1) as Stream<UpdateOrder>
142+
)
126143
.flatten();
127144

128145
const updateDone$: Stream<UpdateOrder> = mouseup$
@@ -136,9 +153,9 @@ export function makeSortable(
136153
return {
137154
...sinks,
138155
DOM: adapt(vdom$),
139-
drag: adapt(dragInProgress$),
156+
dragging: adapt(dragInProgress$),
140157
updateLive: adapt(updateOrder$),
141-
updateDone$: adapt(updateDone$)
158+
updateDone: adapt(updateDone$)
142159
};
143160
};
144161
}

0 commit comments

Comments
 (0)