@humanspeak/svelte-virtual-list 0.3.8 → 0.3.10
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 +174 -128
- package/dist/index.d.ts +2 -0
- package/dist/index.js +2 -0
- package/dist/reactive-list-manager/ReactiveListManager.svelte.d.ts +27 -0
- package/dist/reactive-list-manager/ReactiveListManager.svelte.js +72 -0
- package/dist/utils/perfMetrics.d.ts +114 -0
- package/dist/utils/perfMetrics.js +252 -0
- package/dist/utils/scrollCalculation.d.ts +35 -0
- package/dist/utils/scrollCalculation.js +81 -69
- package/dist/utils/virtualList.d.ts +36 -0
- package/dist/utils/virtualList.js +40 -13
- package/package.json +9 -9
|
@@ -1,3 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Validates a height value and returns it if valid, otherwise returns the fallback.
|
|
3
|
+
*
|
|
4
|
+
* A height is considered valid if it is a finite number greater than 0.
|
|
5
|
+
* This utility consolidates the repeated pattern of height validation
|
|
6
|
+
* found throughout the virtual list codebase.
|
|
7
|
+
*
|
|
8
|
+
* @param {unknown} height - The height value to validate
|
|
9
|
+
* @param {number} fallback - The fallback value to use if height is invalid
|
|
10
|
+
* @returns {number} The validated height or the fallback value
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* ```typescript
|
|
14
|
+
* const height = getValidHeight(heightCache[i], calculatedItemHeight)
|
|
15
|
+
* // Returns heightCache[i] if valid, otherwise calculatedItemHeight
|
|
16
|
+
* ```
|
|
17
|
+
*/
|
|
18
|
+
export const getValidHeight = (height, fallback) => Number.isFinite(height) && height > 0 ? height : fallback;
|
|
19
|
+
/**
|
|
20
|
+
* Clamps a numeric value to be within a specified range.
|
|
21
|
+
*
|
|
22
|
+
* This utility consolidates the repeated `Math.max(min, Math.min(max, value))`
|
|
23
|
+
* pattern used throughout scroll calculations and positioning logic.
|
|
24
|
+
*
|
|
25
|
+
* @param {number} value - The value to clamp
|
|
26
|
+
* @param {number} min - The minimum allowed value
|
|
27
|
+
* @param {number} max - The maximum allowed value
|
|
28
|
+
* @returns {number} The clamped value
|
|
29
|
+
*
|
|
30
|
+
* @example
|
|
31
|
+
* ```typescript
|
|
32
|
+
* const scrollTop = clampValue(targetScrollTop, 0, maxScrollTop)
|
|
33
|
+
* // Ensures scrollTop is between 0 and maxScrollTop
|
|
34
|
+
* ```
|
|
35
|
+
*/
|
|
36
|
+
export const clampValue = (value, min, max) => Math.max(min, Math.min(max, value));
|
|
1
37
|
/**
|
|
2
38
|
* Calculates the maximum scroll position for a virtual list.
|
|
3
39
|
*
|
|
@@ -68,10 +104,7 @@ export const calculateVisibleRange = (scrollTop, viewportHeight, itemHeight, tot
|
|
|
68
104
|
const adjustedEnd = totalItems;
|
|
69
105
|
let startCore = adjustedEnd;
|
|
70
106
|
let acc = 0;
|
|
71
|
-
const getH = (i) =>
|
|
72
|
-
const v = heightCache ? heightCache[i] : undefined;
|
|
73
|
-
return Number.isFinite(v) && v > 0 ? v : itemHeight;
|
|
74
|
-
};
|
|
107
|
+
const getH = (i) => getValidHeight(heightCache ? heightCache[i] : undefined, itemHeight);
|
|
75
108
|
while (startCore > 0 && acc < viewportHeight) {
|
|
76
109
|
const h = getH(startCore - 1);
|
|
77
110
|
acc += h;
|
|
@@ -366,9 +399,7 @@ export const getScrollOffsetForIndex = (heightCache, calculatedItemHeight, idx,
|
|
|
366
399
|
// Fallback: O(n) for a single query
|
|
367
400
|
let offset = 0;
|
|
368
401
|
for (let i = 0; i < safeIdx; i++) {
|
|
369
|
-
|
|
370
|
-
const height = Number.isFinite(raw) && raw > 0 ? raw : calculatedItemHeight;
|
|
371
|
-
offset += height;
|
|
402
|
+
offset += getValidHeight(heightCache[i], calculatedItemHeight);
|
|
372
403
|
}
|
|
373
404
|
return offset;
|
|
374
405
|
}
|
|
@@ -381,9 +412,7 @@ export const getScrollOffsetForIndex = (heightCache, calculatedItemHeight, idx,
|
|
|
381
412
|
let offset = offsetBase;
|
|
382
413
|
const start = blockIdx * blockSize;
|
|
383
414
|
for (let i = start; i < safeIdx; i++) {
|
|
384
|
-
|
|
385
|
-
const height = Number.isFinite(raw) && raw > 0 ? raw : calculatedItemHeight;
|
|
386
|
-
offset += height;
|
|
415
|
+
offset += getValidHeight(heightCache[i], calculatedItemHeight);
|
|
387
416
|
}
|
|
388
417
|
return offset;
|
|
389
418
|
};
|
|
@@ -422,9 +451,7 @@ export const buildBlockSums = (heightCache, calculatedItemHeight, totalItems, bl
|
|
|
422
451
|
const start = b * blockSize;
|
|
423
452
|
const end = start + blockSize;
|
|
424
453
|
for (let i = start; i < end; i++) {
|
|
425
|
-
|
|
426
|
-
const h = Number.isFinite(raw) && raw > 0 ? raw : calculatedItemHeight;
|
|
427
|
-
running += h;
|
|
454
|
+
running += getValidHeight(heightCache[i], calculatedItemHeight);
|
|
428
455
|
}
|
|
429
456
|
sums[b] = running;
|
|
430
457
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@humanspeak/svelte-virtual-list",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.10",
|
|
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",
|
|
@@ -59,19 +59,19 @@
|
|
|
59
59
|
"esm-env": "^1.2.2"
|
|
60
60
|
},
|
|
61
61
|
"devDependencies": {
|
|
62
|
-
"@eslint/compat": "^2.0.
|
|
62
|
+
"@eslint/compat": "^2.0.2",
|
|
63
63
|
"@eslint/js": "^9.39.2",
|
|
64
64
|
"@faker-js/faker": "^10.2.0",
|
|
65
|
-
"@playwright/test": "^1.58.
|
|
65
|
+
"@playwright/test": "^1.58.1",
|
|
66
66
|
"@sveltejs/adapter-auto": "^7.0.0",
|
|
67
|
-
"@sveltejs/kit": "^2.50.
|
|
67
|
+
"@sveltejs/kit": "^2.50.2",
|
|
68
68
|
"@sveltejs/package": "^2.5.7",
|
|
69
69
|
"@sveltejs/vite-plugin-svelte": "^6.2.4",
|
|
70
70
|
"@tailwindcss/vite": "^4.1.18",
|
|
71
71
|
"@testing-library/jest-dom": "^6.9.1",
|
|
72
72
|
"@testing-library/svelte": "^5.3.1",
|
|
73
73
|
"@testing-library/user-event": "^14.6.1",
|
|
74
|
-
"@types/node": "^25.
|
|
74
|
+
"@types/node": "^25.2.0",
|
|
75
75
|
"@typescript-eslint/eslint-plugin": "^8.54.0",
|
|
76
76
|
"@typescript-eslint/parser": "^8.54.0",
|
|
77
77
|
"@vitest/coverage-v8": "^4.0.18",
|
|
@@ -81,17 +81,17 @@
|
|
|
81
81
|
"eslint-plugin-import": "^2.32.0",
|
|
82
82
|
"eslint-plugin-svelte": "^3.14.0",
|
|
83
83
|
"eslint-plugin-unused-imports": "^4.3.0",
|
|
84
|
-
"globals": "^17.
|
|
84
|
+
"globals": "^17.3.0",
|
|
85
85
|
"husky": "^9.1.7",
|
|
86
|
-
"jsdom": "^
|
|
86
|
+
"jsdom": "^28.0.0",
|
|
87
87
|
"prettier": "^3.8.1",
|
|
88
88
|
"prettier-plugin-organize-imports": "^4.3.0",
|
|
89
89
|
"prettier-plugin-sort-json": "^4.2.0",
|
|
90
90
|
"prettier-plugin-svelte": "^3.4.1",
|
|
91
91
|
"prettier-plugin-tailwindcss": "^0.7.2",
|
|
92
92
|
"publint": "^0.3.17",
|
|
93
|
-
"svelte": "^5.
|
|
94
|
-
"svelte-check": "^4.3.
|
|
93
|
+
"svelte": "^5.49.1",
|
|
94
|
+
"svelte-check": "^4.3.6",
|
|
95
95
|
"tailwindcss": "^4.1.18",
|
|
96
96
|
"tw-animate-css": "^1.4.0",
|
|
97
97
|
"typescript": "^5.9.3",
|