dataTable/bak/index.v2_unkeyed.js

87 lines
3.0 KiB
JavaScript
Raw Permalink Normal View History

import { Component, NewState, Util, RefreshState } from '@web/state'
import { VirtualScroll } from '@web/base'
Component.register('DataTable', container => {
const vs = VirtualScroll()
if (!container.state) container.state = NewState({})
const state = container.state
Object.assign(state, {
list: [], fields: [], _renderedList: [],
prevHeight: 0, postHeight: 0, _listStartIndex: 0,
perf: { refreshTime: 0, refreshCount: 0, scrollCount: 0, totalNodes: 0 }
})
container.refresh = () => {
const start = performance.now()
const res = vs.calc(container, state.list)
if (res) {
state.perf.refreshCount++
Object.assign(state, {
prevHeight: res.prevHeight, postHeight: res.postHeight,
_listStartIndex: res.listStartIndex, _renderedList: res.renderedList
})
state.perf.refreshTime += (performance.now() - start)
state.perf.totalNodes += res.renderedList.length
}
}
container.onItemUpdate = (index, node) => vs.update(index + (state._listStartIndex || 0), node)
state.__watch('list', list => {
state._listStartIndex = 0
state._renderedList = vs.reset(list, container) || []
setTimeout(() => { if (state.list === list) vs.init(list, container.refresh) })
})
state.__watch('fields', fields => {
if (!fields) return
const gridTemplate = fields.map(f => `var(--w-${f.id}, ${f.width || 150}px)`).join(' ')
container.style.setProperty('--dt-grid-template', gridTemplate)
})
container.onScroll = () => {
state.perf.scrollCount++
container.refresh()
}
}, Util.makeDom(/*html*/`
<div class="dt-root h-100 overflow-auto" onscroll="this.onScroll()" style="overflow-anchor:none; display: block">
<div class="dt-header border-bottom bg-light sticky-top" style="z-index:10">
<div class="dt-grid-row fw-bold text-muted small" style="height:40px">
<div $each="this.state.fields" class="dt-cell border-end px-2 d-flex align-items-center overflow-hidden">
<span $text="item.name" class="text-truncate"></span>
</div>
</div>
</div>
<div class="dt-body" style="position:relative">
<div $if="(this.state?.prevHeight || 0) > 0" $style="'height:' + this.state.prevHeight + 'px;'" class="flex-shrink-0"></div>
<div $each="this.state?._renderedList" class="dt-row dt-grid-row border-bottom bg-white" style="height:40px" $onupdate="this.onItemUpdate(index, thisNode)">
<div $each="this.state.fields" as="f" class="dt-cell border-end px-2 d-flex align-items-center overflow-hidden">
<span $text="item[f.id] ?? ''" class="text-truncate"></span>
</div>
</div>
<div $if="(this.state?.postHeight || 0) > 0" $style="'height:' + this.state.postHeight + 'px;'" class="flex-shrink-0"></div>
</div>
</div>
`), Util.makeDom(/*html*/`
<style>
DataTable { display: block; }
.dt-grid-row {
display: grid;
grid-template-columns: var(--dt-grid-template);
width: max-content;
min-width: 100%;
}
.dt-cell {
background: inherit;
white-space: nowrap;
}
.dt-row:hover {
background-color: #f8f9fa !important;
}
</style>
`))
if (typeof document !== 'undefined') RefreshState(document.documentElement)