start on virtual list

This commit is contained in:
Nolan Lawson 2018-01-15 10:54:02 -08:00
parent d5ac34eb73
commit 3ef701fd57
7 changed files with 1335 additions and 20 deletions

4
package-lock.json generated
View file

@ -6829,9 +6829,7 @@
"integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=" "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc="
}, },
"svelte": { "svelte": {
"version": "1.51.0", "version": "github:nolanlawson/svelte#c5cd9fc76e069faa364e5c2c6343ddaf2adc4dcf"
"resolved": "https://registry.npmjs.org/svelte/-/svelte-1.51.0.tgz",
"integrity": "sha512-lqa9eAZ4ZQLMWsoyynAogUtib7HhHnrJJaS93uRgZU5cfXquBVR+FkKVK41LdlwffmOfOjbUin6pT8e/LZUwjA=="
}, },
"svelte-extras": { "svelte-extras": {
"version": "1.6.0", "version": "1.6.0",

View file

@ -31,10 +31,10 @@
"npm-run-all": "^4.1.2", "npm-run-all": "^4.1.2",
"performance-now": "^2.1.0", "performance-now": "^2.1.0",
"pify": "^3.0.0", "pify": "^3.0.0",
"sapper": "^0.3.1", "sapper": "^0.3.2",
"serve-static": "^1.13.1", "serve-static": "^1.13.1",
"style-loader": "^0.19.1", "style-loader": "^0.19.1",
"svelte": "^1.50.0", "svelte": "github:nolanlawson/svelte#master-8057884",
"svelte-extras": "^1.6.0", "svelte-extras": "^1.6.0",
"svelte-loader": "^2.3.3", "svelte-loader": "^2.3.3",
"svelte-transitions": "^1.1.1", "svelte-transitions": "^1.1.1",

View file

@ -0,0 +1,17 @@
<div class="list-item">
<Status status="{{virtualProps}}" />
</div>
<style>
.list-item {
border-bottom: 1px solid var(--main-border);
}
</style>
<script>
import Status from './Status.html'
export default {
components: {
Status
}
}
</script>

View file

@ -1,33 +1,27 @@
<ul> <div class="timeline">
{{#each statuses as status}} <VirtualList component="{{StatusListItem}}" items="{{statuses}}" />
<li> </div>
<Status :status />
</li>
{{/each}}
</ul>
<style> <style>
ul { .timeline {
list-style: none;
padding-right: 10px; padding-right: 10px;
} }
li {
border-bottom: 1px solid var(--main-border);
}
</style> </style>
<script> <script>
import { store } from '../_utils/store' import { store } from '../_utils/store'
import { getHomeTimeline } from '../_utils/mastodon/oauth' import { getHomeTimeline } from '../_utils/mastodon/oauth'
import fixture from '../_utils/fixture.json' import fixture from '../_utils/fixture.json'
import Status from './Status.html' import StatusListItem from './StatusListItem.html'
import VirtualList from './VirtualList.html'
export default { export default {
data: () => ({ data: () => ({
target: 'home', target: 'home',
statuses: fixture statuses: fixture,
StatusListItem: StatusListItem
}), }),
store: () => store, store: () => store,
components: { components: {
Status VirtualList
} }
} }
</script> </script>

View file

@ -0,0 +1,70 @@
<div class="virtual-list" ref:node style="height: {{height}}px;">
{{#each visibleItems as visibleItem, index}}
<VirtualListItem :component
:intersectionObserver
virtualOffset="{{visibleItem.offset}}"
virtualProps="{{visibleItem.props}}"
virtualIndex="{{index}}" />
{{/each}}
</div>
<style>
.virtual-list {
position: relative;
}
</style>
<script>
import VirtualListItem from './VirtualListItem'
function sum(arr) {
return arr.reduce((a, b) => a + b, 0)
}
export default {
oncreate() {
let intersectionObserver = new IntersectionObserver((entries) => {
let totalHeight = sum(entries.map(entry => entry.boundingClientRect.height))
let offset = 0
let offsets = []
entries.forEach(entry => {
offsets.push(offset)
offset += entry.boundingClientRect.height
})
this.set({
height: totalHeight,
offsets: offsets
})
console.log('entries', entries.map(entry => entry.target.getAttribute('data-virtual-index')))
}, {
root: this.refs.node
})
this.set({
intersectionObserver: intersectionObserver
})
},
ondestroy() {
let intersectionObserver = this.get('intersectionObserver')
if (intersectionObserver) {
intersectionObserver.disconnect()
}
},
computed: {
visibleItems: (items, offsets) => {
return items.map((item, idx) => ({
props: item,
offset: offsets[idx]
}))
}
},
data: () => ({
scrollHeight: 0,
component: null,
intersectionObserver: null,
items: [],
offsets: [],
height: 400
}),
components: {
VirtualListItem
}
}
</script>

View file

@ -0,0 +1,29 @@
<div class="virtual-list-item"
ref:node
style="transform: translate3d(0, {{virtualOffset}}px, 0);"
data-virtual-index="{{virtualIndex}}">
<:Component {component} :virtualProps :virtualIndex :intersectionObserver />
</div>
<style>
.virtual-list-item {
position: absolute;
top: 0;
will-change: transform;
}
</style>
<script>
export default {
oncreate() {
this.observe('intersectionObserver', (intersectionObserver) => {
if (intersectionObserver) {
intersectionObserver.observe(this.refs.node)
}
})
},
methods: {
showRefs () {
console.log(this.refs)
}
}
}
</script>

File diff suppressed because it is too large Load diff