···
45
45
size_observer?: ResizeObserver
46
46
refreshing: RefreshLevel = RefreshLevel.Nothing
47
47
48
48
+
/** Use the `.create()` method instead. I couldn't get the constructor to infer generics */
48
49
private constructor(
49
50
public source_items: I[],
50
51
public options: {
51
52
buffer?: number
52
53
row_prepare: (source_items: I, index: number) => R
53
54
row_render?: (element: HTMLElement, item: R, index: number) => void
55
55
+
row_height: number
54
56
},
55
57
) {}
56
58
···
60
62
buffer?: number
61
63
row_prepare: (source_items: I, index: number) => R
62
64
row_render?: (element: HTMLElement, item: R, index: number) => void
65
65
+
row_height: number
63
66
},
64
67
) {
65
68
return new VirtualGrid<I, R>(source_items, options)
66
69
}
67
67
-
68
68
-
row_height = 24
69
70
70
71
set_source_items(source_items: I[]) {
71
72
this.source_items = source_items
···
89
90
90
91
#update_viewport_size() {
91
92
const viewport_height = this.viewport?.clientHeight ?? 0
92
92
-
this.viewport_row_count = Math.ceil(viewport_height / this.row_height)
93
93
+
this.viewport_row_count = Math.ceil(viewport_height / this.options.row_height)
93
94
94
94
-
const height = this.source_items.length * this.row_height
95
95
+
const height = this.source_items.length * this.options.row_height
95
96
if (this.main_element) {
96
97
this.main_element.style.height = height + 'px'
97
98
}
···
106
107
const buffer = this.options.buffer ?? 5
107
108
const rendered_count = this.viewport_row_count + buffer * 2
108
109
109
109
-
let start_index = Math.max(0, Math.floor(this.viewport.scrollTop / this.row_height - buffer))
110
110
+
let start_index = Math.max(
111
111
+
0,
112
112
+
Math.floor(this.viewport.scrollTop / this.options.row_height - buffer),
113
113
+
)
110
114
const end_index = Math.min(this.source_items.length - 1, start_index - 1 + rendered_count)
111
115
if (end_index - start_index + 1 < rendered_count) {
112
116
// fill backwards when scrolled to the end
···
268
272
if (!row.element) {
269
273
throw new Error('Unexpected missing row element')
270
274
}
271
271
-
row.element.style.translate = `0 ${row.index * this.row_height}px`
275
275
+
row.element.style.translate = `0 ${row.index * this.options.row_height}px`
272
276
row.element.setAttribute('aria-rowindex', String(row.index + 1))
273
277
const row_item = items[row.index]
274
278
for (let ci = 0; ci < this.#inner_columns.length; ci++) {
···
303
307
throw new Error('No viewport')
304
308
}
305
309
const dummy = document.createElement('div')
306
306
-
dummy.style.height = this.row_height + 'px'
310
310
+
dummy.style.height = this.options.row_height + 'px'
307
311
dummy.style.position = 'absolute'
308
308
-
dummy.style.top = index * this.row_height + 'px'
312
312
+
dummy.style.top = index * this.options.row_height + 'px'
309
313
dummy.style.scrollMarginBottom = scroll_margin_bottom + 'px'
310
314
this.viewport.prepend(dummy)
311
315
dummy.scrollIntoView({ behavior: 'instant', block: 'nearest' })
···
8
8
let source_items = generate_source_items(500_000)
9
9
10
10
const virtual_grid = VirtualGrid.create(source_items, {
11
11
+
row_height: 24,
11
12
row_prepare(source_item, index) {
12
13
return {
13
14
id: source_item,