@humanspeak/svelte-virtual-list 0.2.6-beta.2 → 0.2.6-beta.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/SvelteVirtualList.svelte +27 -29
- package/dist/SvelteVirtualList.svelte.d.ts +19 -6
- package/dist/utils/heightCalculation.d.ts +3 -1
- package/dist/utils/heightCalculation.js +5 -3
- package/dist/utils/virtualList.d.ts +3 -1
- package/dist/utils/virtualList.js +10 -13
- package/dist/utils/virtualListDebug.d.ts +6 -6
- package/dist/utils/virtualListDebug.js +7 -7
- package/package.json +1 -1
- package/dist/utils/initialization.d.ts +0 -103
- package/dist/utils/initialization.js +0 -114
|
@@ -41,15 +41,16 @@
|
|
|
41
41
|
- Only visible items + buffer are mounted in the DOM
|
|
42
42
|
- Height caching and estimation for dynamic content
|
|
43
43
|
- Handles resize events and dynamic content changes
|
|
44
|
-
-
|
|
45
|
-
-
|
|
44
|
+
- Optimized for very large lists through virtualization
|
|
45
|
+
- Modular architecture with extracted utility functions
|
|
46
46
|
- Bi-directional support: mode="topToBottom" or "bottomToTop"
|
|
47
47
|
- Designed for extensibility and easy debugging
|
|
48
48
|
|
|
49
49
|
=============================
|
|
50
50
|
== For Contributors ==
|
|
51
51
|
=============================
|
|
52
|
-
-
|
|
52
|
+
- Complex logic is extracted to dedicated utility files in src/lib/utils/
|
|
53
|
+
- Scroll positioning logic is in scrollCalculation.ts (well-tested)
|
|
53
54
|
- Add new features behind feature flags or as optional props
|
|
54
55
|
- Write tests for all new features (see /test and /tests/scroll)
|
|
55
56
|
- Use TypeScript and Svelte 5 runes for all new code
|
|
@@ -110,7 +111,14 @@
|
|
|
110
111
|
* - Added comprehensive documentation
|
|
111
112
|
* - Optimized debug output to reduce noise
|
|
112
113
|
*
|
|
113
|
-
* 9.
|
|
114
|
+
* 9. Architecture Refactoring ✓
|
|
115
|
+
* - Extracted scroll calculation logic to scrollCalculation.ts utility
|
|
116
|
+
* - Extracted ResizeObserver utilities to resizeObserver.ts
|
|
117
|
+
* - Added comprehensive test coverage for extracted utilities
|
|
118
|
+
* - Improved separation of concerns and maintainability
|
|
119
|
+
* - Simplified initialization (removed unnecessary chunked processing)
|
|
120
|
+
*
|
|
121
|
+
* 10. Future Improvements (Planned)
|
|
114
122
|
* - Add horizontal scrolling support
|
|
115
123
|
* - Implement variable-sized item caching
|
|
116
124
|
* - Add keyboard navigation support
|
|
@@ -128,14 +136,19 @@
|
|
|
128
136
|
* - Debug output optimization
|
|
129
137
|
* - Accurate size calculations with caching
|
|
130
138
|
* - Responsive size adjustments
|
|
139
|
+
* - Modular architecture with testable utility functions
|
|
131
140
|
*
|
|
132
141
|
* Current Architecture:
|
|
133
142
|
* - Four-layer DOM structure for optimal performance
|
|
134
143
|
* - State management using Svelte 5's $state
|
|
135
144
|
* - Reactive height and scroll calculations
|
|
136
145
|
* - Configurable buffer zones for smooth scrolling
|
|
137
|
-
* -
|
|
138
|
-
*
|
|
146
|
+
* - Modular utility system with dedicated helper files:
|
|
147
|
+
* * scrollCalculation.ts: Complex scroll positioning logic
|
|
148
|
+
* * resizeObserver.ts: ResizeObserver management utilities
|
|
149
|
+
* * heightCalculation.ts: Debounced height measurement
|
|
150
|
+
* * virtualList.ts: Core virtual list calculations
|
|
151
|
+
* * virtualListDebug.ts: Debug information utilities
|
|
139
152
|
* - Height caching and estimation system
|
|
140
153
|
* - Progressive size adjustment system
|
|
141
154
|
*/
|
|
@@ -156,7 +169,7 @@
|
|
|
156
169
|
} from './utils/virtualList.js'
|
|
157
170
|
import { createDebugInfo, shouldShowDebugInfo } from './utils/virtualListDebug.js'
|
|
158
171
|
import { calculateScrollTarget } from './utils/scrollCalculation.js'
|
|
159
|
-
|
|
172
|
+
|
|
160
173
|
import { BROWSER } from 'esm-env'
|
|
161
174
|
import { onMount, tick } from 'svelte'
|
|
162
175
|
|
|
@@ -215,8 +228,6 @@
|
|
|
215
228
|
*/
|
|
216
229
|
let heightCache = $state<Record<number, number>>({}) // Cache of measured item heights
|
|
217
230
|
let dirtyItems = $state(new Set<number>()) // Set of item indices that need height recalculation
|
|
218
|
-
const chunkSize = $state(50) // Number of items to process in each chunk
|
|
219
|
-
let processedItems = $state(0) // Number of items processed during initialization
|
|
220
231
|
|
|
221
232
|
let prevVisibleRange = $state<SvelteVirtualListPreviousVisibleRange | null>(null)
|
|
222
233
|
let prevHeight = $state<number>(0)
|
|
@@ -242,12 +253,9 @@
|
|
|
242
253
|
lastMeasuredIndex = result.newLastMeasuredIndex
|
|
243
254
|
heightCache = result.updatedHeightCache
|
|
244
255
|
|
|
245
|
-
// Update running totals
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
totalMeasuredHeight = heights.reduce((sum, h) => sum + h, 0)
|
|
249
|
-
measuredCount = heights.length
|
|
250
|
-
}
|
|
256
|
+
// Update running totals efficiently (O(1) instead of O(n)!)
|
|
257
|
+
totalMeasuredHeight = result.newTotalHeight
|
|
258
|
+
measuredCount = result.newValidCount
|
|
251
259
|
|
|
252
260
|
// Clear processed dirty items
|
|
253
261
|
result.clearedDirtyItems.forEach((index) => {
|
|
@@ -262,7 +270,9 @@
|
|
|
262
270
|
}
|
|
263
271
|
},
|
|
264
272
|
100, // debounceTime
|
|
265
|
-
dirtyItems // Pass dirty items for processing
|
|
273
|
+
dirtyItems, // Pass dirty items for processing
|
|
274
|
+
totalMeasuredHeight, // Current running total height
|
|
275
|
+
measuredCount // Current running total count
|
|
266
276
|
)
|
|
267
277
|
}
|
|
268
278
|
|
|
@@ -530,18 +540,6 @@
|
|
|
530
540
|
)
|
|
531
541
|
}
|
|
532
542
|
|
|
533
|
-
// Initialize the virtual list when items change
|
|
534
|
-
$effect(() => {
|
|
535
|
-
if (BROWSER) {
|
|
536
|
-
initializeVirtualList({
|
|
537
|
-
items,
|
|
538
|
-
chunkSize,
|
|
539
|
-
onProgress: (processed) => (processedItems = processed),
|
|
540
|
-
onComplete: () => (initialized = true)
|
|
541
|
-
})
|
|
542
|
-
}
|
|
543
|
-
})
|
|
544
|
-
|
|
545
543
|
// Create itemResizeObserver immediately when in browser
|
|
546
544
|
if (BROWSER) {
|
|
547
545
|
// Watch for individual item size changes
|
|
@@ -836,7 +834,7 @@
|
|
|
836
834
|
{@const debugInfo = createDebugInfo(
|
|
837
835
|
visibleItems(),
|
|
838
836
|
items.length,
|
|
839
|
-
|
|
837
|
+
Object.keys(heightCache).length,
|
|
840
838
|
calculatedItemHeight
|
|
841
839
|
)}
|
|
842
840
|
{debugFunction
|
|
@@ -47,7 +47,14 @@
|
|
|
47
47
|
* - Added comprehensive documentation
|
|
48
48
|
* - Optimized debug output to reduce noise
|
|
49
49
|
*
|
|
50
|
-
* 9.
|
|
50
|
+
* 9. Architecture Refactoring ✓
|
|
51
|
+
* - Extracted scroll calculation logic to scrollCalculation.ts utility
|
|
52
|
+
* - Extracted ResizeObserver utilities to resizeObserver.ts
|
|
53
|
+
* - Added comprehensive test coverage for extracted utilities
|
|
54
|
+
* - Improved separation of concerns and maintainability
|
|
55
|
+
* - Simplified initialization (removed unnecessary chunked processing)
|
|
56
|
+
*
|
|
57
|
+
* 10. Future Improvements (Planned)
|
|
51
58
|
* - Add horizontal scrolling support
|
|
52
59
|
* - Implement variable-sized item caching
|
|
53
60
|
* - Add keyboard navigation support
|
|
@@ -65,14 +72,19 @@
|
|
|
65
72
|
* - Debug output optimization
|
|
66
73
|
* - Accurate size calculations with caching
|
|
67
74
|
* - Responsive size adjustments
|
|
75
|
+
* - Modular architecture with testable utility functions
|
|
68
76
|
*
|
|
69
77
|
* Current Architecture:
|
|
70
78
|
* - Four-layer DOM structure for optimal performance
|
|
71
79
|
* - State management using Svelte 5's $state
|
|
72
80
|
* - Reactive height and scroll calculations
|
|
73
81
|
* - Configurable buffer zones for smooth scrolling
|
|
74
|
-
* -
|
|
75
|
-
*
|
|
82
|
+
* - Modular utility system with dedicated helper files:
|
|
83
|
+
* * scrollCalculation.ts: Complex scroll positioning logic
|
|
84
|
+
* * resizeObserver.ts: ResizeObserver management utilities
|
|
85
|
+
* * heightCalculation.ts: Debounced height measurement
|
|
86
|
+
* * virtualList.ts: Core virtual list calculations
|
|
87
|
+
* * virtualListDebug.ts: Debug information utilities
|
|
76
88
|
* - Height caching and estimation system
|
|
77
89
|
* - Progressive size adjustment system
|
|
78
90
|
*/
|
|
@@ -120,15 +132,16 @@ import { type SvelteVirtualListProps, type SvelteVirtualListScrollOptions } from
|
|
|
120
132
|
* - Only visible items + buffer are mounted in the DOM
|
|
121
133
|
* - Height caching and estimation for dynamic content
|
|
122
134
|
* - Handles resize events and dynamic content changes
|
|
123
|
-
* -
|
|
124
|
-
* -
|
|
135
|
+
* - Optimized for very large lists through virtualization
|
|
136
|
+
* - Modular architecture with extracted utility functions
|
|
125
137
|
* - Bi-directional support: mode="topToBottom" or "bottomToTop"
|
|
126
138
|
* - Designed for extensibility and easy debugging
|
|
127
139
|
*
|
|
128
140
|
* =============================
|
|
129
141
|
* == For Contributors ==
|
|
130
142
|
* =============================
|
|
131
|
-
* -
|
|
143
|
+
* - Complex logic is extracted to dedicated utility files in src/lib/utils/
|
|
144
|
+
* - Scroll positioning logic is in scrollCalculation.ts (well-tested)
|
|
132
145
|
* - Add new features behind feature flags or as optional props
|
|
133
146
|
* - Write tests for all new features (see /test and /tests/scroll)
|
|
134
147
|
* - Use TypeScript and Svelte 5 runes for all new code
|
|
@@ -75,4 +75,6 @@ export declare const calculateAverageHeightDebounced: (isCalculatingHeight: bool
|
|
|
75
75
|
newLastMeasuredIndex: number;
|
|
76
76
|
updatedHeightCache: Record<number, number>;
|
|
77
77
|
clearedDirtyItems: Set<number>;
|
|
78
|
-
|
|
78
|
+
newTotalHeight: number;
|
|
79
|
+
newValidCount: number;
|
|
80
|
+
}) => void, debounceTime: number, dirtyItems: Set<number>, currentTotalHeight?: number, currentValidCount?: number) => NodeJS.Timeout | null;
|
|
@@ -71,7 +71,7 @@ import { BROWSER } from 'esm-env';
|
|
|
71
71
|
*/
|
|
72
72
|
export const calculateAverageHeightDebounced = (isCalculatingHeight, heightUpdateTimeout, visibleItemsGetter, itemElements, heightCache, lastMeasuredIndex, calculatedItemHeight,
|
|
73
73
|
/* trunk-ignore(eslint/no-unused-vars) */
|
|
74
|
-
onUpdate, debounceTime, dirtyItems) => {
|
|
74
|
+
onUpdate, debounceTime, dirtyItems, currentTotalHeight = 0, currentValidCount = 0) => {
|
|
75
75
|
if (!BROWSER || isCalculatingHeight)
|
|
76
76
|
return null;
|
|
77
77
|
const visibleRange = visibleItemsGetter();
|
|
@@ -81,13 +81,15 @@ onUpdate, debounceTime, dirtyItems) => {
|
|
|
81
81
|
if (heightUpdateTimeout)
|
|
82
82
|
clearTimeout(heightUpdateTimeout);
|
|
83
83
|
return setTimeout(() => {
|
|
84
|
-
const { newHeight, newLastMeasuredIndex, updatedHeightCache, clearedDirtyItems } = calculateAverageHeight(itemElements, visibleRange, heightCache, calculatedItemHeight, dirtyItems);
|
|
84
|
+
const { newHeight, newLastMeasuredIndex, updatedHeightCache, clearedDirtyItems, newTotalHeight, newValidCount } = calculateAverageHeight(itemElements, visibleRange, heightCache, calculatedItemHeight, dirtyItems, currentTotalHeight, currentValidCount);
|
|
85
85
|
if (Math.abs(newHeight - calculatedItemHeight) > 1 || dirtyItems.size > 0) {
|
|
86
86
|
onUpdate({
|
|
87
87
|
newHeight,
|
|
88
88
|
newLastMeasuredIndex,
|
|
89
89
|
updatedHeightCache,
|
|
90
|
-
clearedDirtyItems
|
|
90
|
+
clearedDirtyItems,
|
|
91
|
+
newTotalHeight,
|
|
92
|
+
newValidCount
|
|
91
93
|
});
|
|
92
94
|
}
|
|
93
95
|
}, debounceTime);
|
|
@@ -86,11 +86,13 @@ export declare const updateHeightAndScroll: (state: VirtualListState, setters: V
|
|
|
86
86
|
*/
|
|
87
87
|
export declare const calculateAverageHeight: (itemElements: HTMLElement[], visibleRange: {
|
|
88
88
|
start: number;
|
|
89
|
-
}, heightCache: Record<number, number>, currentItemHeight: number, dirtyItems: Set<number
|
|
89
|
+
}, heightCache: Record<number, number>, currentItemHeight: number, dirtyItems: Set<number>, currentTotalHeight?: number, currentValidCount?: number) => {
|
|
90
90
|
newHeight: number;
|
|
91
91
|
newLastMeasuredIndex: number;
|
|
92
92
|
updatedHeightCache: Record<number, number>;
|
|
93
93
|
clearedDirtyItems: Set<number>;
|
|
94
|
+
newTotalHeight: number;
|
|
95
|
+
newValidCount: number;
|
|
94
96
|
};
|
|
95
97
|
/**
|
|
96
98
|
* Processes large arrays in chunks to prevent UI blocking.
|
|
@@ -158,28 +158,23 @@ export const updateHeightAndScroll = (state, setters, immediate = false) => {
|
|
|
158
158
|
* 40
|
|
159
159
|
* )
|
|
160
160
|
*/
|
|
161
|
-
export const calculateAverageHeight = (itemElements, visibleRange, heightCache, currentItemHeight, dirtyItems) => {
|
|
161
|
+
export const calculateAverageHeight = (itemElements, visibleRange, heightCache, currentItemHeight, dirtyItems, currentTotalHeight = 0, currentValidCount = 0) => {
|
|
162
162
|
const validElements = itemElements.filter((el) => el);
|
|
163
163
|
if (validElements.length === 0) {
|
|
164
164
|
return {
|
|
165
165
|
newHeight: currentItemHeight,
|
|
166
166
|
newLastMeasuredIndex: visibleRange.start,
|
|
167
167
|
updatedHeightCache: heightCache,
|
|
168
|
-
clearedDirtyItems: new Set()
|
|
168
|
+
clearedDirtyItems: new Set(),
|
|
169
|
+
newTotalHeight: currentTotalHeight,
|
|
170
|
+
newValidCount: currentValidCount
|
|
169
171
|
};
|
|
170
172
|
}
|
|
171
173
|
const newHeightCache = { ...heightCache };
|
|
172
174
|
const clearedDirtyItems = new Set();
|
|
173
|
-
//
|
|
174
|
-
let totalValidHeight =
|
|
175
|
-
let validHeightCount =
|
|
176
|
-
// Calculate initial totals from existing cache
|
|
177
|
-
for (const height of Object.values(heightCache)) {
|
|
178
|
-
if (Number.isFinite(height) && height > 0) {
|
|
179
|
-
totalValidHeight += height;
|
|
180
|
-
validHeightCount++;
|
|
181
|
-
}
|
|
182
|
-
}
|
|
175
|
+
// Start with current running totals (O(1) instead of O(n))
|
|
176
|
+
let totalValidHeight = currentTotalHeight;
|
|
177
|
+
let validHeightCount = currentValidCount;
|
|
183
178
|
// Process only dirty items if they exist, otherwise process all visible items
|
|
184
179
|
if (dirtyItems.size > 0) {
|
|
185
180
|
// Process only dirty items
|
|
@@ -240,7 +235,9 @@ export const calculateAverageHeight = (itemElements, visibleRange, heightCache,
|
|
|
240
235
|
newHeight: validHeightCount > 0 ? totalValidHeight / validHeightCount : currentItemHeight,
|
|
241
236
|
newLastMeasuredIndex: visibleRange.start,
|
|
242
237
|
updatedHeightCache: newHeightCache,
|
|
243
|
-
clearedDirtyItems
|
|
238
|
+
clearedDirtyItems,
|
|
239
|
+
newTotalHeight: totalValidHeight,
|
|
240
|
+
newValidCount: validHeightCount
|
|
244
241
|
};
|
|
245
242
|
};
|
|
246
243
|
/**
|
|
@@ -40,9 +40,9 @@ export declare function shouldShowDebugInfo(prevRange: {
|
|
|
40
40
|
*
|
|
41
41
|
* This utility function generates a structured debug object that captures the complete
|
|
42
42
|
* state of a virtual list at any given moment. It includes critical metrics such as
|
|
43
|
-
* visible item count, viewport boundaries, total items,
|
|
44
|
-
* height calculations. This information is essential for performance
|
|
45
|
-
* debugging scroll behavior, and optimizing virtual list configurations.
|
|
43
|
+
* visible item count, viewport boundaries, total items, processed items with measured
|
|
44
|
+
* heights, and height calculations. This information is essential for performance
|
|
45
|
+
* monitoring, debugging scroll behavior, and optimizing virtual list configurations.
|
|
46
46
|
*
|
|
47
47
|
* Performance considerations:
|
|
48
48
|
* - All calculations are O(1)
|
|
@@ -51,7 +51,7 @@ export declare function shouldShowDebugInfo(prevRange: {
|
|
|
51
51
|
*
|
|
52
52
|
* @param visibleRange - Current visible range object containing start and end indices
|
|
53
53
|
* @param totalItems - Total number of items in the virtual list
|
|
54
|
-
* @param processedItems - Number of items
|
|
54
|
+
* @param processedItems - Number of items with measured heights (heightCache.length)
|
|
55
55
|
* @param averageItemHeight - Current calculated average height per item in pixels
|
|
56
56
|
* @returns {SvelteVirtualListDebugInfo} A structured debug information object
|
|
57
57
|
*
|
|
@@ -59,8 +59,8 @@ export declare function shouldShowDebugInfo(prevRange: {
|
|
|
59
59
|
* const debugInfo = createDebugInfo(
|
|
60
60
|
* { start: 0, end: 10 },
|
|
61
61
|
* 1000,
|
|
62
|
-
*
|
|
63
|
-
*
|
|
62
|
+
* 50,
|
|
63
|
+
* 45
|
|
64
64
|
* );
|
|
65
65
|
* console.log('Virtual List State:', debugInfo);
|
|
66
66
|
*
|
|
@@ -39,9 +39,9 @@ export function shouldShowDebugInfo(prevRange, currentRange, prevHeight, current
|
|
|
39
39
|
*
|
|
40
40
|
* This utility function generates a structured debug object that captures the complete
|
|
41
41
|
* state of a virtual list at any given moment. It includes critical metrics such as
|
|
42
|
-
* visible item count, viewport boundaries, total items,
|
|
43
|
-
* height calculations. This information is essential for performance
|
|
44
|
-
* debugging scroll behavior, and optimizing virtual list configurations.
|
|
42
|
+
* visible item count, viewport boundaries, total items, processed items with measured
|
|
43
|
+
* heights, and height calculations. This information is essential for performance
|
|
44
|
+
* monitoring, debugging scroll behavior, and optimizing virtual list configurations.
|
|
45
45
|
*
|
|
46
46
|
* Performance considerations:
|
|
47
47
|
* - All calculations are O(1)
|
|
@@ -50,7 +50,7 @@ export function shouldShowDebugInfo(prevRange, currentRange, prevHeight, current
|
|
|
50
50
|
*
|
|
51
51
|
* @param visibleRange - Current visible range object containing start and end indices
|
|
52
52
|
* @param totalItems - Total number of items in the virtual list
|
|
53
|
-
* @param processedItems - Number of items
|
|
53
|
+
* @param processedItems - Number of items with measured heights (heightCache.length)
|
|
54
54
|
* @param averageItemHeight - Current calculated average height per item in pixels
|
|
55
55
|
* @returns {SvelteVirtualListDebugInfo} A structured debug information object
|
|
56
56
|
*
|
|
@@ -58,8 +58,8 @@ export function shouldShowDebugInfo(prevRange, currentRange, prevHeight, current
|
|
|
58
58
|
* const debugInfo = createDebugInfo(
|
|
59
59
|
* { start: 0, end: 10 },
|
|
60
60
|
* 1000,
|
|
61
|
-
*
|
|
62
|
-
*
|
|
61
|
+
* 50,
|
|
62
|
+
* 45
|
|
63
63
|
* );
|
|
64
64
|
* console.log('Virtual List State:', debugInfo);
|
|
65
65
|
*
|
|
@@ -71,7 +71,7 @@ export function createDebugInfo(visibleRange, totalItems, processedItems, averag
|
|
|
71
71
|
startIndex: visibleRange.start,
|
|
72
72
|
endIndex: visibleRange.end,
|
|
73
73
|
totalItems,
|
|
74
|
-
processedItems,
|
|
74
|
+
processedItems, // Number of items with measured heights in heightCache
|
|
75
75
|
averageItemHeight
|
|
76
76
|
};
|
|
77
77
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@humanspeak/svelte-virtual-list",
|
|
3
|
-
"version": "0.2.6-beta.
|
|
3
|
+
"version": "0.2.6-beta.4",
|
|
4
4
|
"description": "A lightweight, high-performance virtual list component for Svelte 5 that renders large datasets with minimal memory usage. Features include dynamic height support, smooth scrolling, TypeScript support, and efficient DOM recycling. Ideal for infinite scrolling lists, data tables, chat interfaces, and any application requiring the rendering of thousands of items without compromising performance. Zero dependencies and fully customizable.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"svelte",
|
|
@@ -1,103 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Configuration for virtual list initialization
|
|
3
|
-
*/
|
|
4
|
-
export interface InitializationConfig {
|
|
5
|
-
/** Array of items to initialize */
|
|
6
|
-
items: unknown[];
|
|
7
|
-
/** Number of items to process in each chunk */
|
|
8
|
-
chunkSize: number;
|
|
9
|
-
/** Threshold above which to use chunked initialization */
|
|
10
|
-
chunkThreshold?: number;
|
|
11
|
-
/** Callback called with progress updates during chunked initialization */
|
|
12
|
-
onProgress?: (processedItems: number, totalItems: number) => void;
|
|
13
|
-
/** Callback called when initialization is complete */
|
|
14
|
-
onComplete?: () => void;
|
|
15
|
-
}
|
|
16
|
-
/**
|
|
17
|
-
* Determines whether to use chunked initialization based on item count and threshold.
|
|
18
|
-
*
|
|
19
|
-
* @param itemCount - Number of items to initialize
|
|
20
|
-
* @param threshold - Threshold above which chunked initialization is used (default: 1000)
|
|
21
|
-
* @returns True if chunked initialization should be used
|
|
22
|
-
*
|
|
23
|
-
* @example
|
|
24
|
-
* ```typescript
|
|
25
|
-
* const useChunked = shouldUseChunkedInitialization(5000) // true
|
|
26
|
-
* const useImmediate = shouldUseChunkedInitialization(500) // false
|
|
27
|
-
* ```
|
|
28
|
-
*/
|
|
29
|
-
export declare const shouldUseChunkedInitialization: (itemCount: number, threshold?: number) => boolean;
|
|
30
|
-
/**
|
|
31
|
-
* Initializes a virtual list with items, using chunked processing for large datasets.
|
|
32
|
-
*
|
|
33
|
-
* This function automatically determines whether to use immediate or chunked initialization
|
|
34
|
-
* based on the number of items. For large datasets, it processes items in chunks to
|
|
35
|
-
* prevent UI blocking, yielding to the main thread between chunks.
|
|
36
|
-
*
|
|
37
|
-
* @param config - Configuration object for initialization
|
|
38
|
-
* @returns Promise that resolves when initialization is complete
|
|
39
|
-
*
|
|
40
|
-
* @example
|
|
41
|
-
* ```typescript
|
|
42
|
-
* import { initializeVirtualList } from './initialization.js'
|
|
43
|
-
*
|
|
44
|
-
* // Initialize with progress tracking
|
|
45
|
-
* await initializeVirtualList({
|
|
46
|
-
* items: largeDataset,
|
|
47
|
-
* chunkSize: 50,
|
|
48
|
-
* onProgress: (processed, total) => {
|
|
49
|
-
* console.log(`Progress: ${processed}/${total}`)
|
|
50
|
-
* },
|
|
51
|
-
* onComplete: () => {
|
|
52
|
-
* console.log('Initialization complete!')
|
|
53
|
-
* }
|
|
54
|
-
* })
|
|
55
|
-
* ```
|
|
56
|
-
*/
|
|
57
|
-
export declare const initializeVirtualList: (config: InitializationConfig) => Promise<void>;
|
|
58
|
-
/**
|
|
59
|
-
* Calculates the optimal chunk size for initialization based on item count and device capabilities.
|
|
60
|
-
*
|
|
61
|
-
* This function provides a heuristic for determining an appropriate chunk size that balances
|
|
62
|
-
* performance and responsiveness. It considers both the total number of items and the
|
|
63
|
-
* estimated processing time per item.
|
|
64
|
-
*
|
|
65
|
-
* @param itemCount - Total number of items to process
|
|
66
|
-
* @param baseChunkSize - Base chunk size to use as a starting point (default: 50)
|
|
67
|
-
* @returns Recommended chunk size
|
|
68
|
-
*
|
|
69
|
-
* @example
|
|
70
|
-
* ```typescript
|
|
71
|
-
* const chunkSize = calculateOptimalChunkSize(10000) // Returns optimized chunk size
|
|
72
|
-
* const smallChunkSize = calculateOptimalChunkSize(100) // Returns smaller chunk size
|
|
73
|
-
* ```
|
|
74
|
-
*/
|
|
75
|
-
export declare const calculateOptimalChunkSize: (itemCount: number, baseChunkSize?: number) => number;
|
|
76
|
-
/**
|
|
77
|
-
* Progress information for initialization
|
|
78
|
-
*/
|
|
79
|
-
export interface InitializationProgress {
|
|
80
|
-
/** Number of items processed */
|
|
81
|
-
processed: number;
|
|
82
|
-
/** Total number of items */
|
|
83
|
-
total: number;
|
|
84
|
-
/** Percentage complete (0-100) */
|
|
85
|
-
percentage: number;
|
|
86
|
-
/** Whether initialization is complete */
|
|
87
|
-
isComplete: boolean;
|
|
88
|
-
}
|
|
89
|
-
/**
|
|
90
|
-
* Creates a progress tracking object for initialization.
|
|
91
|
-
*
|
|
92
|
-
* @param processed - Number of items processed
|
|
93
|
-
* @param total - Total number of items
|
|
94
|
-
* @returns Progress information object
|
|
95
|
-
*
|
|
96
|
-
* @example
|
|
97
|
-
* ```typescript
|
|
98
|
-
* const progress = createProgressInfo(750, 1000)
|
|
99
|
-
* console.log(progress.percentage) // 75
|
|
100
|
-
* console.log(progress.isComplete) // false
|
|
101
|
-
* ```
|
|
102
|
-
*/
|
|
103
|
-
export declare const createProgressInfo: (processed: number, total: number) => InitializationProgress;
|
|
@@ -1,114 +0,0 @@
|
|
|
1
|
-
import { processChunked } from './virtualList.js';
|
|
2
|
-
/**
|
|
3
|
-
* Determines whether to use chunked initialization based on item count and threshold.
|
|
4
|
-
*
|
|
5
|
-
* @param itemCount - Number of items to initialize
|
|
6
|
-
* @param threshold - Threshold above which chunked initialization is used (default: 1000)
|
|
7
|
-
* @returns True if chunked initialization should be used
|
|
8
|
-
*
|
|
9
|
-
* @example
|
|
10
|
-
* ```typescript
|
|
11
|
-
* const useChunked = shouldUseChunkedInitialization(5000) // true
|
|
12
|
-
* const useImmediate = shouldUseChunkedInitialization(500) // false
|
|
13
|
-
* ```
|
|
14
|
-
*/
|
|
15
|
-
export const shouldUseChunkedInitialization = (itemCount, threshold = 1000) => {
|
|
16
|
-
return itemCount > threshold;
|
|
17
|
-
};
|
|
18
|
-
/**
|
|
19
|
-
* Initializes a virtual list with items, using chunked processing for large datasets.
|
|
20
|
-
*
|
|
21
|
-
* This function automatically determines whether to use immediate or chunked initialization
|
|
22
|
-
* based on the number of items. For large datasets, it processes items in chunks to
|
|
23
|
-
* prevent UI blocking, yielding to the main thread between chunks.
|
|
24
|
-
*
|
|
25
|
-
* @param config - Configuration object for initialization
|
|
26
|
-
* @returns Promise that resolves when initialization is complete
|
|
27
|
-
*
|
|
28
|
-
* @example
|
|
29
|
-
* ```typescript
|
|
30
|
-
* import { initializeVirtualList } from './initialization.js'
|
|
31
|
-
*
|
|
32
|
-
* // Initialize with progress tracking
|
|
33
|
-
* await initializeVirtualList({
|
|
34
|
-
* items: largeDataset,
|
|
35
|
-
* chunkSize: 50,
|
|
36
|
-
* onProgress: (processed, total) => {
|
|
37
|
-
* console.log(`Progress: ${processed}/${total}`)
|
|
38
|
-
* },
|
|
39
|
-
* onComplete: () => {
|
|
40
|
-
* console.log('Initialization complete!')
|
|
41
|
-
* }
|
|
42
|
-
* })
|
|
43
|
-
* ```
|
|
44
|
-
*/
|
|
45
|
-
export const initializeVirtualList = async (config) => {
|
|
46
|
-
const { items, chunkSize, chunkThreshold = 1000, onProgress, onComplete } = config;
|
|
47
|
-
if (!items.length) {
|
|
48
|
-
onComplete?.();
|
|
49
|
-
return;
|
|
50
|
-
}
|
|
51
|
-
if (shouldUseChunkedInitialization(items.length, chunkThreshold)) {
|
|
52
|
-
await processChunked(items, chunkSize, (processedItems) => onProgress?.(processedItems, items.length), () => onComplete?.());
|
|
53
|
-
}
|
|
54
|
-
else {
|
|
55
|
-
// Immediate initialization for small datasets
|
|
56
|
-
onProgress?.(items.length, items.length);
|
|
57
|
-
onComplete?.();
|
|
58
|
-
}
|
|
59
|
-
};
|
|
60
|
-
/**
|
|
61
|
-
* Calculates the optimal chunk size for initialization based on item count and device capabilities.
|
|
62
|
-
*
|
|
63
|
-
* This function provides a heuristic for determining an appropriate chunk size that balances
|
|
64
|
-
* performance and responsiveness. It considers both the total number of items and the
|
|
65
|
-
* estimated processing time per item.
|
|
66
|
-
*
|
|
67
|
-
* @param itemCount - Total number of items to process
|
|
68
|
-
* @param baseChunkSize - Base chunk size to use as a starting point (default: 50)
|
|
69
|
-
* @returns Recommended chunk size
|
|
70
|
-
*
|
|
71
|
-
* @example
|
|
72
|
-
* ```typescript
|
|
73
|
-
* const chunkSize = calculateOptimalChunkSize(10000) // Returns optimized chunk size
|
|
74
|
-
* const smallChunkSize = calculateOptimalChunkSize(100) // Returns smaller chunk size
|
|
75
|
-
* ```
|
|
76
|
-
*/
|
|
77
|
-
export const calculateOptimalChunkSize = (itemCount, baseChunkSize = 50) => {
|
|
78
|
-
// For very large datasets, use smaller chunks to maintain responsiveness
|
|
79
|
-
if (itemCount > 50000) {
|
|
80
|
-
return Math.max(25, baseChunkSize / 2);
|
|
81
|
-
}
|
|
82
|
-
// For medium datasets, use base chunk size
|
|
83
|
-
if (itemCount > 5000) {
|
|
84
|
-
return baseChunkSize;
|
|
85
|
-
}
|
|
86
|
-
// For smaller datasets, we can use larger chunks
|
|
87
|
-
if (itemCount > 1000) {
|
|
88
|
-
return Math.min(100, baseChunkSize * 2);
|
|
89
|
-
}
|
|
90
|
-
// For very small datasets, process all at once
|
|
91
|
-
return itemCount;
|
|
92
|
-
};
|
|
93
|
-
/**
|
|
94
|
-
* Creates a progress tracking object for initialization.
|
|
95
|
-
*
|
|
96
|
-
* @param processed - Number of items processed
|
|
97
|
-
* @param total - Total number of items
|
|
98
|
-
* @returns Progress information object
|
|
99
|
-
*
|
|
100
|
-
* @example
|
|
101
|
-
* ```typescript
|
|
102
|
-
* const progress = createProgressInfo(750, 1000)
|
|
103
|
-
* console.log(progress.percentage) // 75
|
|
104
|
-
* console.log(progress.isComplete) // false
|
|
105
|
-
* ```
|
|
106
|
-
*/
|
|
107
|
-
export const createProgressInfo = (processed, total) => {
|
|
108
|
-
return {
|
|
109
|
-
processed,
|
|
110
|
-
total,
|
|
111
|
-
percentage: total > 0 ? Math.round((processed / total) * 100) : 100,
|
|
112
|
-
isComplete: processed >= total
|
|
113
|
-
};
|
|
114
|
-
};
|