@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.
@@ -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
- - Supports chunked initialization for very large lists
45
- - All scrolling logic is centralized in the scroll() method
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
- - Please keep all scrolling logic in the scroll() method
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. Future Improvements (Planned)
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
- * - Chunked processing system for large datasets
138
- * - Separated debug utilities for better testing
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
- import { initializeVirtualList } from './utils/initialization.js'
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 for precise height calculation (only when significant changes)
246
- if (result.clearedDirtyItems.size > 10) {
247
- const heights = Object.values(heightCache)
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
- processedItems,
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. Future Improvements (Planned)
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
- * - Chunked processing system for large datasets
75
- * - Separated debug utilities for better testing
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
- * - Supports chunked initialization for very large lists
124
- * - All scrolling logic is centralized in the scroll() method
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
- * - Please keep all scrolling logic in the scroll() method
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
- }) => void, debounceTime: number, dirtyItems: Set<number>) => NodeJS.Timeout | null;
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
- // Initialize running totals for O(1) average calculation
174
- let totalValidHeight = 0;
175
- let validHeightCount = 0;
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, processing progress, and
44
- * height calculations. This information is essential for performance monitoring,
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 that have been processed/measured
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
- * 100,
63
- * 50
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, processing progress, and
43
- * height calculations. This information is essential for performance monitoring,
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 that have been processed/measured
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
- * 100,
62
- * 50
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.2",
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
- };