@humanspeak/svelte-virtual-list 0.2.6-beta.6 → 0.2.6-beta.7
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 +461 -130
- package/dist/SvelteVirtualList.svelte.d.ts +2 -2
- package/dist/reactive-height-manager/INTEGRATION_EXAMPLE.md +136 -0
- package/dist/reactive-height-manager/README.md +324 -0
- package/dist/reactive-height-manager/ReactiveHeightManager.svelte.d.ts +116 -0
- package/dist/reactive-height-manager/ReactiveHeightManager.svelte.js +200 -0
- package/dist/reactive-height-manager/benchmark.d.ts +5 -0
- package/dist/reactive-height-manager/benchmark.js +25 -0
- package/dist/reactive-height-manager/index.d.ts +50 -0
- package/dist/reactive-height-manager/index.js +55 -0
- package/dist/reactive-height-manager/types.d.ts +41 -0
- package/dist/reactive-height-manager/types.js +1 -0
- package/dist/utils/heightCalculation.d.ts +8 -1
- package/dist/utils/heightCalculation.js +5 -4
- package/dist/utils/heightChangeDetection.d.ts +12 -0
- package/dist/utils/heightChangeDetection.js +20 -0
- package/dist/utils/resizeObserver.d.ts +0 -33
- package/dist/utils/resizeObserver.js +0 -57
- package/dist/utils/scrollCalculation.d.ts +2 -2
- package/dist/utils/scrollCalculation.js +34 -21
- package/dist/utils/throttle.d.ts +95 -0
- package/dist/utils/throttle.js +155 -0
- package/dist/utils/virtualList.d.ts +11 -14
- package/dist/utils/virtualList.js +100 -53
- package/dist/utils/virtualListDebug.d.ts +1 -1
- package/dist/utils/virtualListDebug.js +1 -2
- package/package.json +21 -20
|
@@ -40,7 +40,8 @@ export const calculateScrollTarget = (params) => {
|
|
|
40
40
|
height,
|
|
41
41
|
scrollTop,
|
|
42
42
|
firstVisibleIndex,
|
|
43
|
-
lastVisibleIndex
|
|
43
|
+
lastVisibleIndex,
|
|
44
|
+
heightCache
|
|
44
45
|
});
|
|
45
46
|
}
|
|
46
47
|
else {
|
|
@@ -60,31 +61,26 @@ export const calculateScrollTarget = (params) => {
|
|
|
60
61
|
* Calculates scroll target for bottom-to-top mode
|
|
61
62
|
*/
|
|
62
63
|
const calculateBottomToTopScrollTarget = (params) => {
|
|
63
|
-
const { align, targetIndex, itemsLength, calculatedItemHeight, height, scrollTop, firstVisibleIndex, lastVisibleIndex } = params;
|
|
64
|
-
|
|
65
|
-
const
|
|
64
|
+
const { align, targetIndex, itemsLength, calculatedItemHeight, height, scrollTop, firstVisibleIndex, lastVisibleIndex, heightCache } = params;
|
|
65
|
+
// Use getScrollOffsetForIndex for accurate positioning with height cache
|
|
66
|
+
const totalHeight = getScrollOffsetForIndex(heightCache, calculatedItemHeight, itemsLength);
|
|
67
|
+
const itemOffset = getScrollOffsetForIndex(heightCache, calculatedItemHeight, targetIndex);
|
|
66
68
|
const itemHeight = calculatedItemHeight;
|
|
67
69
|
if (align === 'auto') {
|
|
68
70
|
// If item is above the viewport, align to top
|
|
69
71
|
if (targetIndex < firstVisibleIndex) {
|
|
70
72
|
return Math.max(0, totalHeight - (itemOffset + itemHeight));
|
|
71
73
|
}
|
|
72
|
-
// If item is below the viewport, align to bottom
|
|
73
74
|
else if (targetIndex > lastVisibleIndex - 1) {
|
|
75
|
+
// In bottomToTop, "below" means higher indices that need HIGHER scrollTop
|
|
74
76
|
return Math.max(0, totalHeight - itemOffset - height);
|
|
75
77
|
}
|
|
76
78
|
else {
|
|
77
|
-
// Item is visible but not aligned: align to nearest edge
|
|
78
79
|
const itemTop = totalHeight - (itemOffset + itemHeight);
|
|
79
80
|
const itemBottom = totalHeight - itemOffset;
|
|
80
81
|
const distanceToTop = Math.abs(scrollTop - itemTop);
|
|
81
82
|
const distanceToBottom = Math.abs(scrollTop + height - itemBottom);
|
|
82
|
-
|
|
83
|
-
return itemTop;
|
|
84
|
-
}
|
|
85
|
-
else {
|
|
86
|
-
return Math.max(0, itemBottom - height);
|
|
87
|
-
}
|
|
83
|
+
return distanceToTop < distanceToBottom ? itemTop : Math.max(0, itemBottom - height);
|
|
88
84
|
}
|
|
89
85
|
}
|
|
90
86
|
else if (align === 'top') {
|
|
@@ -100,12 +96,7 @@ const calculateBottomToTopScrollTarget = (params) => {
|
|
|
100
96
|
// Not visible, align to nearest edge
|
|
101
97
|
const distanceToTop = Math.abs(scrollTop - itemTop);
|
|
102
98
|
const distanceToBottom = Math.abs(scrollTop + height - itemBottom);
|
|
103
|
-
|
|
104
|
-
return itemTop;
|
|
105
|
-
}
|
|
106
|
-
else {
|
|
107
|
-
return Math.max(0, itemBottom - height);
|
|
108
|
-
}
|
|
99
|
+
return distanceToTop < distanceToBottom ? itemTop : Math.max(0, itemBottom - height);
|
|
109
100
|
}
|
|
110
101
|
else {
|
|
111
102
|
// Already visible, do nothing
|
|
@@ -119,15 +110,29 @@ const calculateBottomToTopScrollTarget = (params) => {
|
|
|
119
110
|
*/
|
|
120
111
|
const calculateTopToBottomScrollTarget = (params) => {
|
|
121
112
|
const { align, targetIndex, calculatedItemHeight, height, scrollTop, firstVisibleIndex, lastVisibleIndex, heightCache } = params;
|
|
113
|
+
console.log('[DEBUG] calculateTopToBottomScrollTarget:', {
|
|
114
|
+
align,
|
|
115
|
+
targetIndex,
|
|
116
|
+
calculatedItemHeight,
|
|
117
|
+
height,
|
|
118
|
+
scrollTop,
|
|
119
|
+
firstVisibleIndex,
|
|
120
|
+
lastVisibleIndex,
|
|
121
|
+
heightCacheKeys: Object.keys(heightCache).length
|
|
122
|
+
});
|
|
122
123
|
if (align === 'auto') {
|
|
123
124
|
// If item is above the viewport, align to top
|
|
124
125
|
if (targetIndex < firstVisibleIndex) {
|
|
125
|
-
|
|
126
|
+
const scrollTarget = getScrollOffsetForIndex(heightCache, calculatedItemHeight, targetIndex);
|
|
127
|
+
console.log(`[DEBUG] Item ${targetIndex} above viewport (${firstVisibleIndex}), scrolling to top:`, scrollTarget);
|
|
128
|
+
return scrollTarget;
|
|
126
129
|
}
|
|
127
130
|
// If item is below the viewport, align to bottom
|
|
128
131
|
else if (targetIndex > lastVisibleIndex - 1) {
|
|
129
132
|
const itemBottom = getScrollOffsetForIndex(heightCache, calculatedItemHeight, targetIndex + 1);
|
|
130
|
-
|
|
133
|
+
const scrollTarget = Math.max(0, itemBottom - height);
|
|
134
|
+
console.log(`[DEBUG] Item ${targetIndex} below viewport (${lastVisibleIndex}), scrolling to bottom:`, scrollTarget);
|
|
135
|
+
return scrollTarget;
|
|
131
136
|
}
|
|
132
137
|
else {
|
|
133
138
|
// Item is visible but not aligned: align to nearest edge
|
|
@@ -135,6 +140,12 @@ const calculateTopToBottomScrollTarget = (params) => {
|
|
|
135
140
|
const itemBottom = getScrollOffsetForIndex(heightCache, calculatedItemHeight, targetIndex + 1);
|
|
136
141
|
const distanceToTop = Math.abs(scrollTop - itemTop);
|
|
137
142
|
const distanceToBottom = Math.abs(scrollTop + height - itemBottom);
|
|
143
|
+
console.log(`[DEBUG] Item ${targetIndex} visible, choosing nearest edge:`, {
|
|
144
|
+
itemTop,
|
|
145
|
+
itemBottom,
|
|
146
|
+
distanceToTop,
|
|
147
|
+
distanceToBottom
|
|
148
|
+
});
|
|
138
149
|
if (distanceToTop < distanceToBottom) {
|
|
139
150
|
return itemTop;
|
|
140
151
|
}
|
|
@@ -144,7 +155,9 @@ const calculateTopToBottomScrollTarget = (params) => {
|
|
|
144
155
|
}
|
|
145
156
|
}
|
|
146
157
|
else if (align === 'top') {
|
|
147
|
-
|
|
158
|
+
const scrollTarget = getScrollOffsetForIndex(heightCache, calculatedItemHeight, targetIndex);
|
|
159
|
+
console.log(`[DEBUG] Align to top for index ${targetIndex}:`, scrollTarget);
|
|
160
|
+
return scrollTarget;
|
|
148
161
|
}
|
|
149
162
|
else if (align === 'bottom') {
|
|
150
163
|
const itemBottom = getScrollOffsetForIndex(heightCache, calculatedItemHeight, targetIndex + 1);
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Throttling utilities for performance optimization.
|
|
3
|
+
*
|
|
4
|
+
* @fileoverview Provides throttling functions to limit execution frequency of callbacks,
|
|
5
|
+
* particularly useful for preventing excessive reactive effect triggers and debounced function calls.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Time provider abstraction that can be mocked in tests.
|
|
9
|
+
* Uses performance.now() in production for high precision timing,
|
|
10
|
+
* but can fallback to Date.now() for testing environments.
|
|
11
|
+
*/
|
|
12
|
+
export declare const timeProvider: {
|
|
13
|
+
now: () => number;
|
|
14
|
+
};
|
|
15
|
+
/**
|
|
16
|
+
* Creates a throttled version of a callback function that limits execution frequency.
|
|
17
|
+
*
|
|
18
|
+
* The throttled function will execute immediately on first call, then ignore subsequent
|
|
19
|
+
* calls until the specified delay has elapsed. This is different from debouncing, which
|
|
20
|
+
* delays execution until after calls stop coming.
|
|
21
|
+
*
|
|
22
|
+
* @template T - The type of the callback function
|
|
23
|
+
* @param callback - The function to throttle
|
|
24
|
+
* @param delay - Minimum time between executions in milliseconds (default: 16ms ≈ 60fps)
|
|
25
|
+
* @returns A throttled version of the callback function
|
|
26
|
+
*
|
|
27
|
+
* @example
|
|
28
|
+
* ```typescript
|
|
29
|
+
* // Basic usage
|
|
30
|
+
* const throttledLog = createThrottledCallback(
|
|
31
|
+
* (message: string) => console.log(message),
|
|
32
|
+
* 100
|
|
33
|
+
* );
|
|
34
|
+
*
|
|
35
|
+
* // Called immediately
|
|
36
|
+
* throttledLog("First call");
|
|
37
|
+
*
|
|
38
|
+
* // Ignored (within 100ms)
|
|
39
|
+
* throttledLog("Second call");
|
|
40
|
+
*
|
|
41
|
+
* // After 100ms, this would execute
|
|
42
|
+
* setTimeout(() => throttledLog("Third call"), 150);
|
|
43
|
+
* ```
|
|
44
|
+
*
|
|
45
|
+
* @example
|
|
46
|
+
* ```typescript
|
|
47
|
+
* // Throttling reactive effects in Svelte
|
|
48
|
+
* const throttledUpdate = createThrottledCallback(() => {
|
|
49
|
+
* if (BROWSER && dirtyItemsCount > 0) {
|
|
50
|
+
* updateHeight();
|
|
51
|
+
* }
|
|
52
|
+
* }, 16); // ~60fps
|
|
53
|
+
*
|
|
54
|
+
* $effect(() => {
|
|
55
|
+
* throttledUpdate();
|
|
56
|
+
* });
|
|
57
|
+
* ```
|
|
58
|
+
*/
|
|
59
|
+
export declare const createThrottledCallback: <T extends (..._args: unknown[]) => void>(callback: T, delay?: number) => T;
|
|
60
|
+
/**
|
|
61
|
+
* Creates a throttled callback with leading and trailing execution options.
|
|
62
|
+
*
|
|
63
|
+
* Unlike the basic throttle, this version allows control over whether the function
|
|
64
|
+
* executes on the leading edge (immediately) and/or trailing edge (after delay).
|
|
65
|
+
*
|
|
66
|
+
* @template T - The type of the callback function
|
|
67
|
+
* @param callback - The function to throttle
|
|
68
|
+
* @param delay - Minimum time between executions in milliseconds
|
|
69
|
+
* @param options - Configuration options
|
|
70
|
+
* @param options.leading - Execute on the leading edge (default: true)
|
|
71
|
+
* @param options.trailing - Execute on the trailing edge (default: false)
|
|
72
|
+
* @returns A throttled version of the callback function
|
|
73
|
+
*
|
|
74
|
+
* @example
|
|
75
|
+
* ```typescript
|
|
76
|
+
* // Execute immediately and after delay
|
|
77
|
+
* const throttledWithTrailing = createAdvancedThrottledCallback(
|
|
78
|
+
* () => console.log("Throttled call"),
|
|
79
|
+
* 100,
|
|
80
|
+
* { leading: true, trailing: true }
|
|
81
|
+
* );
|
|
82
|
+
* ```
|
|
83
|
+
*/
|
|
84
|
+
export declare const createAdvancedThrottledCallback: <T extends (..._args: unknown[]) => void>(callback: T, delay: number, options?: {
|
|
85
|
+
leading?: boolean;
|
|
86
|
+
trailing?: boolean;
|
|
87
|
+
}) => T;
|
|
88
|
+
/**
|
|
89
|
+
* Type definitions for throttle utilities
|
|
90
|
+
*/
|
|
91
|
+
export type ThrottledCallback<T extends (..._args: unknown[]) => void> = T;
|
|
92
|
+
export type ThrottleOptions = {
|
|
93
|
+
leading?: boolean;
|
|
94
|
+
trailing?: boolean;
|
|
95
|
+
};
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Throttling utilities for performance optimization.
|
|
3
|
+
*
|
|
4
|
+
* @fileoverview Provides throttling functions to limit execution frequency of callbacks,
|
|
5
|
+
* particularly useful for preventing excessive reactive effect triggers and debounced function calls.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Time provider abstraction that can be mocked in tests.
|
|
9
|
+
* Uses performance.now() in production for high precision timing,
|
|
10
|
+
* but can fallback to Date.now() for testing environments.
|
|
11
|
+
*/
|
|
12
|
+
export const timeProvider = {
|
|
13
|
+
now: () => {
|
|
14
|
+
// Use performance.now() for high precision in production
|
|
15
|
+
if (typeof performance !== 'undefined' && performance.now) {
|
|
16
|
+
return performance.now();
|
|
17
|
+
}
|
|
18
|
+
// Fallback to Date.now() (mainly for testing or older environments)
|
|
19
|
+
return Date.now();
|
|
20
|
+
}
|
|
21
|
+
};
|
|
22
|
+
/**
|
|
23
|
+
* Creates a throttled version of a callback function that limits execution frequency.
|
|
24
|
+
*
|
|
25
|
+
* The throttled function will execute immediately on first call, then ignore subsequent
|
|
26
|
+
* calls until the specified delay has elapsed. This is different from debouncing, which
|
|
27
|
+
* delays execution until after calls stop coming.
|
|
28
|
+
*
|
|
29
|
+
* @template T - The type of the callback function
|
|
30
|
+
* @param callback - The function to throttle
|
|
31
|
+
* @param delay - Minimum time between executions in milliseconds (default: 16ms ≈ 60fps)
|
|
32
|
+
* @returns A throttled version of the callback function
|
|
33
|
+
*
|
|
34
|
+
* @example
|
|
35
|
+
* ```typescript
|
|
36
|
+
* // Basic usage
|
|
37
|
+
* const throttledLog = createThrottledCallback(
|
|
38
|
+
* (message: string) => console.log(message),
|
|
39
|
+
* 100
|
|
40
|
+
* );
|
|
41
|
+
*
|
|
42
|
+
* // Called immediately
|
|
43
|
+
* throttledLog("First call");
|
|
44
|
+
*
|
|
45
|
+
* // Ignored (within 100ms)
|
|
46
|
+
* throttledLog("Second call");
|
|
47
|
+
*
|
|
48
|
+
* // After 100ms, this would execute
|
|
49
|
+
* setTimeout(() => throttledLog("Third call"), 150);
|
|
50
|
+
* ```
|
|
51
|
+
*
|
|
52
|
+
* @example
|
|
53
|
+
* ```typescript
|
|
54
|
+
* // Throttling reactive effects in Svelte
|
|
55
|
+
* const throttledUpdate = createThrottledCallback(() => {
|
|
56
|
+
* if (BROWSER && dirtyItemsCount > 0) {
|
|
57
|
+
* updateHeight();
|
|
58
|
+
* }
|
|
59
|
+
* }, 16); // ~60fps
|
|
60
|
+
*
|
|
61
|
+
* $effect(() => {
|
|
62
|
+
* throttledUpdate();
|
|
63
|
+
* });
|
|
64
|
+
* ```
|
|
65
|
+
*/
|
|
66
|
+
export const createThrottledCallback = (callback, delay = 16 // ~60fps default for smooth UI updates
|
|
67
|
+
) => {
|
|
68
|
+
let lastExecutionTime = 0;
|
|
69
|
+
let isFirstCall = true;
|
|
70
|
+
return ((...args) => {
|
|
71
|
+
const now = timeProvider.now();
|
|
72
|
+
if (isFirstCall || now - lastExecutionTime >= delay) {
|
|
73
|
+
isFirstCall = false;
|
|
74
|
+
lastExecutionTime = now;
|
|
75
|
+
callback(...args);
|
|
76
|
+
}
|
|
77
|
+
});
|
|
78
|
+
};
|
|
79
|
+
/**
|
|
80
|
+
* Creates a throttled callback with leading and trailing execution options.
|
|
81
|
+
*
|
|
82
|
+
* Unlike the basic throttle, this version allows control over whether the function
|
|
83
|
+
* executes on the leading edge (immediately) and/or trailing edge (after delay).
|
|
84
|
+
*
|
|
85
|
+
* @template T - The type of the callback function
|
|
86
|
+
* @param callback - The function to throttle
|
|
87
|
+
* @param delay - Minimum time between executions in milliseconds
|
|
88
|
+
* @param options - Configuration options
|
|
89
|
+
* @param options.leading - Execute on the leading edge (default: true)
|
|
90
|
+
* @param options.trailing - Execute on the trailing edge (default: false)
|
|
91
|
+
* @returns A throttled version of the callback function
|
|
92
|
+
*
|
|
93
|
+
* @example
|
|
94
|
+
* ```typescript
|
|
95
|
+
* // Execute immediately and after delay
|
|
96
|
+
* const throttledWithTrailing = createAdvancedThrottledCallback(
|
|
97
|
+
* () => console.log("Throttled call"),
|
|
98
|
+
* 100,
|
|
99
|
+
* { leading: true, trailing: true }
|
|
100
|
+
* );
|
|
101
|
+
* ```
|
|
102
|
+
*/
|
|
103
|
+
export const createAdvancedThrottledCallback = (callback, delay, options = {}) => {
|
|
104
|
+
const { leading = true, trailing = false } = options;
|
|
105
|
+
let lastExecutionTime = 0;
|
|
106
|
+
let trailingTimeoutId = null;
|
|
107
|
+
let lastArgs = null;
|
|
108
|
+
let isFirstCall = true;
|
|
109
|
+
const execute = (args) => {
|
|
110
|
+
lastExecutionTime = timeProvider.now();
|
|
111
|
+
callback(...args);
|
|
112
|
+
};
|
|
113
|
+
return ((...args) => {
|
|
114
|
+
const now = timeProvider.now();
|
|
115
|
+
const timeSinceLastExecution = isFirstCall ? delay : now - lastExecutionTime;
|
|
116
|
+
lastArgs = args;
|
|
117
|
+
// Clear any pending trailing execution
|
|
118
|
+
if (trailingTimeoutId) {
|
|
119
|
+
clearTimeout(trailingTimeoutId);
|
|
120
|
+
trailingTimeoutId = null;
|
|
121
|
+
}
|
|
122
|
+
if (timeSinceLastExecution >= delay) {
|
|
123
|
+
// Can execute immediately
|
|
124
|
+
if (leading) {
|
|
125
|
+
isFirstCall = false;
|
|
126
|
+
execute(args);
|
|
127
|
+
}
|
|
128
|
+
// Schedule trailing if needed
|
|
129
|
+
if (trailing && !leading) {
|
|
130
|
+
trailingTimeoutId = setTimeout(() => {
|
|
131
|
+
if (lastArgs) {
|
|
132
|
+
execute(lastArgs);
|
|
133
|
+
}
|
|
134
|
+
trailingTimeoutId = null;
|
|
135
|
+
}, delay);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
else {
|
|
139
|
+
// Still within throttle window, but handle first call
|
|
140
|
+
if (isFirstCall && leading) {
|
|
141
|
+
isFirstCall = false;
|
|
142
|
+
execute(args);
|
|
143
|
+
}
|
|
144
|
+
else if (trailing) {
|
|
145
|
+
const remainingTime = delay - timeSinceLastExecution;
|
|
146
|
+
trailingTimeoutId = setTimeout(() => {
|
|
147
|
+
if (lastArgs) {
|
|
148
|
+
execute(lastArgs);
|
|
149
|
+
}
|
|
150
|
+
trailingTimeoutId = null;
|
|
151
|
+
}, remainingTime);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
});
|
|
155
|
+
};
|
|
@@ -28,7 +28,7 @@ export declare const calculateScrollPosition: (totalItems: number, itemHeight: n
|
|
|
28
28
|
* @param {SvelteVirtualListMode} mode - Scroll direction mode
|
|
29
29
|
* @returns {SvelteVirtualListPreviousVisibleRange} Range of indices to render
|
|
30
30
|
*/
|
|
31
|
-
export declare const calculateVisibleRange: (scrollTop: number, viewportHeight: number, itemHeight: number, totalItems: number, bufferSize: number, mode: SvelteVirtualListMode) => SvelteVirtualListPreviousVisibleRange;
|
|
31
|
+
export declare const calculateVisibleRange: (scrollTop: number, viewportHeight: number, itemHeight: number, totalItems: number, bufferSize: number, mode: SvelteVirtualListMode, atBottom: boolean, wasAtBottomBeforeHeightChange: boolean, lastVisibleRange: SvelteVirtualListPreviousVisibleRange | null, totalContentHeight?: number) => SvelteVirtualListPreviousVisibleRange;
|
|
32
32
|
/**
|
|
33
33
|
* Calculates the CSS transform value for positioning the virtual list items.
|
|
34
34
|
*
|
|
@@ -41,9 +41,10 @@ export declare const calculateVisibleRange: (scrollTop: number, viewportHeight:
|
|
|
41
41
|
* @param {number} visibleEnd - Index of the last visible item
|
|
42
42
|
* @param {number} visibleStart - Index of the first visible item
|
|
43
43
|
* @param {number} itemHeight - Height of each list item in pixels
|
|
44
|
+
* @param {number} viewportHeight - Height of the viewport in pixels
|
|
44
45
|
* @returns {number} The calculated transform Y value in pixels
|
|
45
46
|
*/
|
|
46
|
-
export declare const calculateTransformY: (mode: SvelteVirtualListMode, totalItems: number, visibleEnd: number, visibleStart: number, itemHeight: number) => number;
|
|
47
|
+
export declare const calculateTransformY: (mode: SvelteVirtualListMode, totalItems: number, visibleEnd: number, visibleStart: number, itemHeight: number, viewportHeight: number, totalContentHeight?: number) => number;
|
|
47
48
|
/**
|
|
48
49
|
* Updates the virtual list's height and scroll position when necessary.
|
|
49
50
|
*
|
|
@@ -86,13 +87,20 @@ export declare const updateHeightAndScroll: (state: VirtualListState, setters: V
|
|
|
86
87
|
*/
|
|
87
88
|
export declare const calculateAverageHeight: (itemElements: HTMLElement[], visibleRange: {
|
|
88
89
|
start: number;
|
|
89
|
-
|
|
90
|
+
end: number;
|
|
91
|
+
}, heightCache: Record<number, number>, currentItemHeight: number, dirtyItems: Set<number>, currentTotalHeight?: number, currentValidCount?: number, mode?: SvelteVirtualListMode) => {
|
|
90
92
|
newHeight: number;
|
|
91
93
|
newLastMeasuredIndex: number;
|
|
92
94
|
updatedHeightCache: Record<number, number>;
|
|
93
95
|
clearedDirtyItems: Set<number>;
|
|
94
96
|
newTotalHeight: number;
|
|
95
97
|
newValidCount: number;
|
|
98
|
+
heightChanges: Array<{
|
|
99
|
+
index: number;
|
|
100
|
+
oldHeight: number;
|
|
101
|
+
newHeight: number;
|
|
102
|
+
delta: number;
|
|
103
|
+
}>;
|
|
96
104
|
};
|
|
97
105
|
/**
|
|
98
106
|
* Processes large arrays in chunks to prevent UI blocking.
|
|
@@ -121,17 +129,6 @@ export declare const calculateAverageHeight: (itemElements: HTMLElement[], visib
|
|
|
121
129
|
export declare const processChunked: (items: any[], // eslint-disable-line @typescript-eslint/no-explicit-any
|
|
122
130
|
chunkSize: number, onProgress: (processed: number) => void, // eslint-disable-line no-unused-vars
|
|
123
131
|
onComplete: () => void) => Promise<void>;
|
|
124
|
-
/**
|
|
125
|
-
* Builds a block sum array for fast offset calculation in large virtual lists.
|
|
126
|
-
* Each entry in the array is the total height up to the end of that block (exclusive).
|
|
127
|
-
*
|
|
128
|
-
* @param {HeightCache} heightCache - Map of measured item heights with dirty tracking
|
|
129
|
-
* @param {number} calculatedItemHeight - Estimated height for unmeasured items
|
|
130
|
-
* @param {number} totalItems - Total number of items in the list
|
|
131
|
-
* @param {number} blockSize - Number of items per block
|
|
132
|
-
* @returns {number[]} Array of prefix sums at each block boundary
|
|
133
|
-
*/
|
|
134
|
-
export declare const buildBlockSums: (heightCache: Record<number, number>, calculatedItemHeight: number, totalItems: number, blockSize?: number) => number[];
|
|
135
132
|
/**
|
|
136
133
|
* Calculates the scroll offset (in pixels) needed to bring a specific item into view in a virtual list.
|
|
137
134
|
*
|