-
Notifications
You must be signed in to change notification settings - Fork 4
/
DeviewRecycle.svelte
88 lines (73 loc) · 1.85 KB
/
DeviewRecycle.svelte
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
<script>
import VanillaRecycle from "@egjs/deview-recycle";
import { createEventDispatcher, onMount, onDestroy, tick } from "svelte";
export let start = -1;
export let end = -1;
export let items = [];
const dispatch = createEventDispatcher();
let visibleItems = items;
let recycle;
let container;
let itemBy;
let options;
let attributes;
$: {
const props = getProps($$props);
itemBy = props.itemBy;
options = props.options;
attributes = props.attributes;
}
$: syncItems(items);
function getProps($$props) {
const { itemBy = item => item, options = {}, ...attributes } = $$props;
delete attributes.items;
delete attributes.$$slots;
delete attributes.$$scope;
return {
itemBy,
options,
attributes
};
}
function syncItems(items) {
if (recycle) {
recycle.beforeSync(items.map(itemBy));
const indexes = recycle.getRenderingIndexes();
start = indexes.start;
end = indexes.end;
visibleItems = items.slice(start, end + 1);
} else {
visibleItems = items;
}
tick().then(() => {
// afterUpdate
recycle.sync(getChildren());
});
}
function getChildren() {
return [].slice.call(container.children);
}
const callbacks = {};
onMount(ctx => {
recycle = new VanillaRecycle(container, {
...options,
renderExternal: true
})
.on("append", e => {
dispatch("append", { ...e });
})
.on("visibleChange", e => {
syncItems(items);
});
recycle.beforeSync(items.map(itemBy));
recycle.sync(getChildren());
});
onDestroy(() => {
recycle.destroy();
});
</script>
<div {...attributes} bind:this={container}>
{#each visibleItems as item, index (itemBy(item, start + index, items))}
<slot items={visibleItems} {item} index={start + index} />
{/each}
</div>