lazy-render-virtual-scroll 1.0.6 → 1.0.8
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/README.md +14 -1
- package/dist/cjs/adapters/angular/lazy-scroll.component.d.ts +28 -0
- package/dist/cjs/adapters/angular/lazy-scroll.component.d.ts.map +1 -0
- package/dist/cjs/adapters/angular/lazy-scroll.directive.d.ts +21 -0
- package/dist/cjs/adapters/angular/lazy-scroll.directive.d.ts.map +1 -0
- package/dist/cjs/adapters/index.d.ts +7 -0
- package/dist/cjs/adapters/index.d.ts.map +1 -0
- package/dist/cjs/adapters/svelte/lazyScrollAction.d.ts +13 -0
- package/dist/cjs/adapters/svelte/lazyScrollAction.d.ts.map +1 -0
- package/dist/cjs/adapters/vue/useLazyScroll.d.ts +13 -0
- package/dist/cjs/adapters/vue/useLazyScroll.d.ts.map +1 -0
- package/dist/cjs/core/AdaptiveBufferCalculator.d.ts +46 -0
- package/dist/cjs/core/AdaptiveBufferCalculator.d.ts.map +1 -0
- package/dist/cjs/core/ContentComplexityAnalyzer.d.ts +13 -0
- package/dist/cjs/core/ContentComplexityAnalyzer.d.ts.map +1 -0
- package/dist/cjs/core/DevicePerformanceMonitor.d.ts +22 -0
- package/dist/cjs/core/DevicePerformanceMonitor.d.ts.map +1 -0
- package/dist/cjs/core/Engine.d.ts +5 -1
- package/dist/cjs/core/Engine.d.ts.map +1 -1
- package/dist/cjs/core/GPUAccelerator.d.ts +23 -0
- package/dist/cjs/core/GPUAccelerator.d.ts.map +1 -0
- package/dist/cjs/core/MemoryManager.d.ts +33 -0
- package/dist/cjs/core/MemoryManager.d.ts.map +1 -0
- package/dist/cjs/core/PerformanceOptimizer.d.ts +39 -0
- package/dist/cjs/core/PerformanceOptimizer.d.ts.map +1 -0
- package/dist/cjs/index.d.ts +12 -0
- package/dist/cjs/index.d.ts.map +1 -1
- package/dist/cjs/index.js +1486 -14
- package/dist/cjs/index.js.map +1 -1
- package/dist/esm/adapters/angular/lazy-scroll.component.d.ts +28 -0
- package/dist/esm/adapters/angular/lazy-scroll.component.d.ts.map +1 -0
- package/dist/esm/adapters/angular/lazy-scroll.directive.d.ts +21 -0
- package/dist/esm/adapters/angular/lazy-scroll.directive.d.ts.map +1 -0
- package/dist/esm/adapters/index.d.ts +7 -0
- package/dist/esm/adapters/index.d.ts.map +1 -0
- package/dist/esm/adapters/svelte/lazyScrollAction.d.ts +13 -0
- package/dist/esm/adapters/svelte/lazyScrollAction.d.ts.map +1 -0
- package/dist/esm/adapters/vue/useLazyScroll.d.ts +13 -0
- package/dist/esm/adapters/vue/useLazyScroll.d.ts.map +1 -0
- package/dist/esm/core/AdaptiveBufferCalculator.d.ts +46 -0
- package/dist/esm/core/AdaptiveBufferCalculator.d.ts.map +1 -0
- package/dist/esm/core/ContentComplexityAnalyzer.d.ts +13 -0
- package/dist/esm/core/ContentComplexityAnalyzer.d.ts.map +1 -0
- package/dist/esm/core/DevicePerformanceMonitor.d.ts +22 -0
- package/dist/esm/core/DevicePerformanceMonitor.d.ts.map +1 -0
- package/dist/esm/core/Engine.d.ts +5 -1
- package/dist/esm/core/Engine.d.ts.map +1 -1
- package/dist/esm/core/GPUAccelerator.d.ts +23 -0
- package/dist/esm/core/GPUAccelerator.d.ts.map +1 -0
- package/dist/esm/core/MemoryManager.d.ts +33 -0
- package/dist/esm/core/MemoryManager.d.ts.map +1 -0
- package/dist/esm/core/PerformanceOptimizer.d.ts +39 -0
- package/dist/esm/core/PerformanceOptimizer.d.ts.map +1 -0
- package/dist/esm/index.d.ts +12 -0
- package/dist/esm/index.d.ts.map +1 -1
- package/dist/esm/index.js +1474 -15
- package/dist/esm/index.js.map +1 -1
- package/dist/index.d.ts +531 -2
- package/package.json +3 -1
package/dist/index.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { OnInit, OnDestroy, ElementRef, AfterViewInit, TemplateRef } from '@angular/core';
|
|
1
2
|
import React from 'react';
|
|
2
3
|
|
|
3
4
|
interface EngineConfig {
|
|
@@ -37,6 +38,10 @@ declare class Engine {
|
|
|
37
38
|
private networkDetector;
|
|
38
39
|
private networkAwarePrefetchManager;
|
|
39
40
|
private networkAwareRequestQueue;
|
|
41
|
+
private adaptiveBufferCalculator;
|
|
42
|
+
private performanceOptimizer;
|
|
43
|
+
private memoryManager;
|
|
44
|
+
private gpuAccelerator;
|
|
40
45
|
private state;
|
|
41
46
|
private fetchMoreCallback;
|
|
42
47
|
private totalItems;
|
|
@@ -44,7 +49,7 @@ declare class Engine {
|
|
|
44
49
|
/**
|
|
45
50
|
* Update scroll position and recalculate visible range with intelligent detection
|
|
46
51
|
*/
|
|
47
|
-
updateScrollPosition(scrollTop: number): void
|
|
52
|
+
updateScrollPosition(scrollTop: number): Promise<void>;
|
|
48
53
|
/**
|
|
49
54
|
* Get the current visible range
|
|
50
55
|
*/
|
|
@@ -204,6 +209,530 @@ declare class NetworkAwareRequestQueue {
|
|
|
204
209
|
clear(): void;
|
|
205
210
|
}
|
|
206
211
|
|
|
212
|
+
declare class AdaptiveBufferCalculator {
|
|
213
|
+
private scrollFactor;
|
|
214
|
+
private networkFactor;
|
|
215
|
+
private performanceFactor;
|
|
216
|
+
private contentFactor;
|
|
217
|
+
private performanceMonitor;
|
|
218
|
+
private contentAnalyzer;
|
|
219
|
+
constructor();
|
|
220
|
+
calculateOptimalBuffer(params: {
|
|
221
|
+
scrollVelocity: number;
|
|
222
|
+
networkQuality: 'excellent' | 'good' | 'poor' | 'offline';
|
|
223
|
+
baseBuffer: number;
|
|
224
|
+
visibleItems: any[];
|
|
225
|
+
}): Promise<number>;
|
|
226
|
+
private calculateScrollBuffer;
|
|
227
|
+
private calculateNetworkAdjustment;
|
|
228
|
+
private calculatePerformanceAdjustment;
|
|
229
|
+
private calculateContentAdjustment;
|
|
230
|
+
getAdaptiveInsights(params: {
|
|
231
|
+
scrollVelocity: number;
|
|
232
|
+
networkQuality: 'excellent' | 'good' | 'poor' | 'offline';
|
|
233
|
+
baseBuffer: number;
|
|
234
|
+
visibleItems: any[];
|
|
235
|
+
}): Promise<{
|
|
236
|
+
currentBuffer: number;
|
|
237
|
+
performance: {
|
|
238
|
+
frameRate: number;
|
|
239
|
+
score: number;
|
|
240
|
+
};
|
|
241
|
+
network: {
|
|
242
|
+
quality: string;
|
|
243
|
+
adjustment: number;
|
|
244
|
+
};
|
|
245
|
+
complexity: {
|
|
246
|
+
score: number;
|
|
247
|
+
breakdown: any;
|
|
248
|
+
};
|
|
249
|
+
factors: {
|
|
250
|
+
scroll: number;
|
|
251
|
+
network: number;
|
|
252
|
+
performance: number;
|
|
253
|
+
content: number;
|
|
254
|
+
};
|
|
255
|
+
}>;
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
declare class DevicePerformanceMonitor {
|
|
259
|
+
private frameRateHistory;
|
|
260
|
+
private memoryUsageHistory;
|
|
261
|
+
private gcMonitoring;
|
|
262
|
+
private readonly HISTORY_SIZE;
|
|
263
|
+
constructor();
|
|
264
|
+
getFrameRate(): Promise<number>;
|
|
265
|
+
getAverageFrameRate(): number;
|
|
266
|
+
getMemoryInfo(): {
|
|
267
|
+
used: number;
|
|
268
|
+
total: number;
|
|
269
|
+
} | null;
|
|
270
|
+
assessPerformance(): Promise<number>;
|
|
271
|
+
private setupPerformanceMonitoring;
|
|
272
|
+
getPerformanceInsights(): {
|
|
273
|
+
frameRate: number;
|
|
274
|
+
performanceScore: number;
|
|
275
|
+
memoryUsed: number | null;
|
|
276
|
+
memoryTotal: number | null;
|
|
277
|
+
};
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
declare class ContentComplexityAnalyzer {
|
|
281
|
+
analyzeContentComplexity(items: any[]): number;
|
|
282
|
+
private analyzeTextComplexity;
|
|
283
|
+
private analyzeMediaComplexity;
|
|
284
|
+
private analyzeComponentComplexity;
|
|
285
|
+
getComplexityInsights(items: any[]): {
|
|
286
|
+
averageComplexity: number;
|
|
287
|
+
textComplexity: number;
|
|
288
|
+
mediaComplexity: number;
|
|
289
|
+
componentComplexity: number;
|
|
290
|
+
};
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
declare class PerformanceOptimizer {
|
|
294
|
+
private frameBudget;
|
|
295
|
+
private lastFrameTime;
|
|
296
|
+
private animationFrameId;
|
|
297
|
+
private isOptimizing;
|
|
298
|
+
private lastUpdate;
|
|
299
|
+
private minUpdateInterval;
|
|
300
|
+
private updateQueue;
|
|
301
|
+
private isProcessingQueue;
|
|
302
|
+
private cleanupThreshold;
|
|
303
|
+
private gcInterval;
|
|
304
|
+
constructor();
|
|
305
|
+
scheduleOptimizedUpdate(updateFn: () => void): void;
|
|
306
|
+
private processUpdateQueue;
|
|
307
|
+
private getTimeRemaining;
|
|
308
|
+
optimizeMemory(cleanupFn: (startIndex: number, endIndex: number) => void, visibleRange: {
|
|
309
|
+
start: number;
|
|
310
|
+
end: number;
|
|
311
|
+
}): void;
|
|
312
|
+
enableGPUCssAcceleration(element: HTMLElement): void;
|
|
313
|
+
disableGPUCssAcceleration(element: HTMLElement): void;
|
|
314
|
+
getOptimizationProfile(): {
|
|
315
|
+
frameRate: number;
|
|
316
|
+
batchSize: number;
|
|
317
|
+
bufferMultiplier: number;
|
|
318
|
+
updateInterval: number;
|
|
319
|
+
};
|
|
320
|
+
private isLowEndDevice;
|
|
321
|
+
private setupPerformanceMonitoring;
|
|
322
|
+
getPerformanceInsights(): {
|
|
323
|
+
frameRate: number;
|
|
324
|
+
memoryUsage: number | null;
|
|
325
|
+
updateFrequency: number;
|
|
326
|
+
optimizationActive: boolean;
|
|
327
|
+
};
|
|
328
|
+
private getMemoryUsage;
|
|
329
|
+
cleanup(): void;
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
declare class MemoryManager {
|
|
333
|
+
private itemCache;
|
|
334
|
+
private maxCacheSize;
|
|
335
|
+
private cleanupThreshold;
|
|
336
|
+
private visibleRange;
|
|
337
|
+
private totalItems;
|
|
338
|
+
constructor(maxCacheSize?: number);
|
|
339
|
+
setVisibleRange(range: {
|
|
340
|
+
start: number;
|
|
341
|
+
end: number;
|
|
342
|
+
}): void;
|
|
343
|
+
setTotalItems(total: number): void;
|
|
344
|
+
get(key: number): any | null;
|
|
345
|
+
set(key: number, value: any): void;
|
|
346
|
+
has(key: number): boolean;
|
|
347
|
+
delete(key: number): boolean;
|
|
348
|
+
clear(): void;
|
|
349
|
+
cleanupCache(): void;
|
|
350
|
+
private getDistanceFromVisible;
|
|
351
|
+
getStats(): {
|
|
352
|
+
size: number;
|
|
353
|
+
maxCacheSize: number;
|
|
354
|
+
visibleItems: number;
|
|
355
|
+
offScreenItems: number;
|
|
356
|
+
memoryEstimate: number;
|
|
357
|
+
};
|
|
358
|
+
private estimateObjectSize;
|
|
359
|
+
pruneEssential(): void;
|
|
360
|
+
private isEssential;
|
|
361
|
+
getSize(): number;
|
|
362
|
+
getKeys(): number[];
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
declare class GPUAccelerator {
|
|
366
|
+
private gpuAccelerationEnabled;
|
|
367
|
+
private gpuElements;
|
|
368
|
+
private animationFrameId;
|
|
369
|
+
constructor();
|
|
370
|
+
private isGPUSupported;
|
|
371
|
+
enableForElement(element: HTMLElement): void;
|
|
372
|
+
disableForElement(element: HTMLElement): void;
|
|
373
|
+
enableForElements(elements: HTMLElement[]): void;
|
|
374
|
+
batchUpdate(elements: HTMLElement[], enable: boolean): void;
|
|
375
|
+
optimizeScrollContainer(container: HTMLElement): void;
|
|
376
|
+
optimizeItem(item: HTMLElement): void;
|
|
377
|
+
getStatus(): {
|
|
378
|
+
enabled: boolean;
|
|
379
|
+
supported: boolean;
|
|
380
|
+
elementCount: number;
|
|
381
|
+
};
|
|
382
|
+
optimizeForScenario(scenario: 'scrolling' | 'animation' | 'static'): void;
|
|
383
|
+
cleanup(): void;
|
|
384
|
+
isAccelerated(element: HTMLElement): boolean;
|
|
385
|
+
getRecommendations(): string[];
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
interface LazyScrollConfig$1 extends EngineConfig {
|
|
389
|
+
fetchMore: FetchMoreCallback;
|
|
390
|
+
}
|
|
391
|
+
declare const useLazyScroll: (config: LazyScrollConfig$1) => {
|
|
392
|
+
visibleRange: any;
|
|
393
|
+
loadedItems: any;
|
|
394
|
+
isLoading: any;
|
|
395
|
+
containerRef: any;
|
|
396
|
+
refresh: () => void;
|
|
397
|
+
};
|
|
398
|
+
|
|
399
|
+
declare class LazyScrollDirective implements OnInit, OnDestroy {
|
|
400
|
+
private el;
|
|
401
|
+
items: any[];
|
|
402
|
+
itemHeight: number;
|
|
403
|
+
viewportHeight: number;
|
|
404
|
+
bufferSize: number;
|
|
405
|
+
fetchMore: FetchMoreCallback;
|
|
406
|
+
visibleRangeChange: any;
|
|
407
|
+
loadingChange: any;
|
|
408
|
+
private engine;
|
|
409
|
+
private scrollListener;
|
|
410
|
+
constructor(el: ElementRef);
|
|
411
|
+
ngOnInit(): void;
|
|
412
|
+
ngOnDestroy(): void;
|
|
413
|
+
private onScroll;
|
|
414
|
+
refresh(): void;
|
|
415
|
+
getVisibleRange(): VisibleRange;
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
declare class LazyScrollComponent implements AfterViewInit, OnDestroy {
|
|
419
|
+
items: any[];
|
|
420
|
+
itemHeight: number;
|
|
421
|
+
viewportHeight: number;
|
|
422
|
+
bufferSize: number;
|
|
423
|
+
fetchMore: () => Promise<any>;
|
|
424
|
+
visibleRangeChange: any;
|
|
425
|
+
loadingChange: any;
|
|
426
|
+
itemTemplate: TemplateRef<any>;
|
|
427
|
+
visibleRange: {
|
|
428
|
+
start: number;
|
|
429
|
+
end: number;
|
|
430
|
+
};
|
|
431
|
+
isLoading: boolean;
|
|
432
|
+
get topPadding(): number;
|
|
433
|
+
get bottomPadding(): number;
|
|
434
|
+
get visibleItems(): any[];
|
|
435
|
+
ngAfterViewInit(): void;
|
|
436
|
+
ngOnDestroy(): void;
|
|
437
|
+
onVisibleRangeChange(range: {
|
|
438
|
+
start: number;
|
|
439
|
+
end: number;
|
|
440
|
+
}): void;
|
|
441
|
+
onLoadingChange(loading: boolean): void;
|
|
442
|
+
trackByFn(index: number, item: any): any;
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
interface LazyScrollConfig {
|
|
446
|
+
itemHeight: number;
|
|
447
|
+
viewportHeight: number;
|
|
448
|
+
bufferSize?: number;
|
|
449
|
+
fetchMore: FetchMoreCallback;
|
|
450
|
+
}
|
|
451
|
+
declare function lazyScroll(node: HTMLElement, config: LazyScrollConfig): {
|
|
452
|
+
update(newConfig: LazyScrollConfig): void;
|
|
453
|
+
destroy(): void;
|
|
454
|
+
};
|
|
455
|
+
|
|
456
|
+
class LazyScroll {
|
|
457
|
+
constructor(container, config) {
|
|
458
|
+
this.container = container;
|
|
459
|
+
this.config = {
|
|
460
|
+
itemHeight: config.itemHeight || 50,
|
|
461
|
+
viewportHeight: config.viewportHeight || 400,
|
|
462
|
+
bufferSize: config.bufferSize || 5,
|
|
463
|
+
fetchMore: config.fetchMore || (() => Promise.resolve([]))
|
|
464
|
+
};
|
|
465
|
+
|
|
466
|
+
this.engine = new Engine(this.config);
|
|
467
|
+
this.engine.setFetchMoreCallback(this.config.fetchMore);
|
|
468
|
+
|
|
469
|
+
this.visibleRange = { start: 0, end: 0 };
|
|
470
|
+
this.isLoading = false;
|
|
471
|
+
this.items = [];
|
|
472
|
+
this.visibleItems = [];
|
|
473
|
+
|
|
474
|
+
this.scrollHandler = this.onScroll.bind(this);
|
|
475
|
+
this.container.addEventListener('scroll', this.scrollHandler, { passive: true });
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
onScroll() {
|
|
479
|
+
const scrollTop = this.container.scrollTop;
|
|
480
|
+
this.engine.updateScrollPosition(scrollTop);
|
|
481
|
+
|
|
482
|
+
const state = this.engine.getState();
|
|
483
|
+
this.visibleRange = state.visibleRange;
|
|
484
|
+
this.isLoading = state.isLoading;
|
|
485
|
+
|
|
486
|
+
this.render();
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
setItems(items) {
|
|
490
|
+
this.items = items;
|
|
491
|
+
this.render();
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
render() {
|
|
495
|
+
// Calculate paddings
|
|
496
|
+
const topPadding = this.visibleRange.start * this.config.itemHeight;
|
|
497
|
+
const bottomPadding = Math.max(0, (this.items.length - this.visibleRange.end) * this.config.itemHeight);
|
|
498
|
+
|
|
499
|
+
// Get visible items
|
|
500
|
+
this.visibleItems = this.items.slice(this.visibleRange.start, this.visibleRange.end);
|
|
501
|
+
|
|
502
|
+
// Clear container except for paddings and content
|
|
503
|
+
const existingContent = this.container.querySelector('.lazy-scroll-content');
|
|
504
|
+
if (existingContent) {
|
|
505
|
+
existingContent.remove();
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
// Create content wrapper
|
|
509
|
+
const contentWrapper = document.createElement('div');
|
|
510
|
+
contentWrapper.className = 'lazy-scroll-content';
|
|
511
|
+
|
|
512
|
+
// Add top padding
|
|
513
|
+
const topPaddingDiv = document.createElement('div');
|
|
514
|
+
topPaddingDiv.style.height = `${topPadding}px`;
|
|
515
|
+
contentWrapper.appendChild(topPaddingDiv);
|
|
516
|
+
|
|
517
|
+
// Add visible items
|
|
518
|
+
this.visibleItems.forEach((item, index) => {
|
|
519
|
+
const itemElement = this.createItemElement(item, this.visibleRange.start + index);
|
|
520
|
+
contentWrapper.appendChild(itemElement);
|
|
521
|
+
});
|
|
522
|
+
|
|
523
|
+
// Add bottom padding
|
|
524
|
+
const bottomPaddingDiv = document.createElement('div');
|
|
525
|
+
bottomPaddingDiv.style.height = `${bottomPadding}px`;
|
|
526
|
+
contentWrapper.appendChild(bottomPaddingDiv);
|
|
527
|
+
|
|
528
|
+
// Add loading indicator if needed
|
|
529
|
+
if (this.isLoading) {
|
|
530
|
+
const loadingElement = document.createElement('div');
|
|
531
|
+
loadingElement.className = 'lazy-loading';
|
|
532
|
+
loadingElement.textContent = 'Loading more items...';
|
|
533
|
+
contentWrapper.appendChild(loadingElement);
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
this.container.appendChild(contentWrapper);
|
|
537
|
+
}
|
|
538
|
+
|
|
539
|
+
createItemElement(item, index) {
|
|
540
|
+
const itemElement = document.createElement('div');
|
|
541
|
+
itemElement.style.height = `${this.config.itemHeight}px`;
|
|
542
|
+
itemElement.className = 'lazy-item';
|
|
543
|
+
|
|
544
|
+
// Default content - can be customized
|
|
545
|
+
itemElement.textContent = `Item ${index}: ${item.text || item.id || 'Content'}`;
|
|
546
|
+
|
|
547
|
+
return itemElement;
|
|
548
|
+
}
|
|
549
|
+
|
|
550
|
+
updateConfig(newConfig) {
|
|
551
|
+
if (newConfig.itemHeight !== undefined) this.config.itemHeight = newConfig.itemHeight;
|
|
552
|
+
if (newConfig.viewportHeight !== undefined) this.config.viewportHeight = newConfig.viewportHeight;
|
|
553
|
+
if (newConfig.bufferSize !== undefined) this.config.bufferSize = newConfig.bufferSize;
|
|
554
|
+
if (newConfig.fetchMore !== undefined) {
|
|
555
|
+
this.config.fetchMore = newConfig.fetchMore;
|
|
556
|
+
this.engine.setFetchMoreCallback(newConfig.fetchMore);
|
|
557
|
+
}
|
|
558
|
+
|
|
559
|
+
// Re-render with new config
|
|
560
|
+
this.render();
|
|
561
|
+
}
|
|
562
|
+
|
|
563
|
+
destroy() {
|
|
564
|
+
this.container.removeEventListener('scroll', this.scrollHandler);
|
|
565
|
+
this.engine.cleanup();
|
|
566
|
+
}
|
|
567
|
+
|
|
568
|
+
// Public methods
|
|
569
|
+
getVisibleRange() {
|
|
570
|
+
return { ...this.visibleRange };
|
|
571
|
+
}
|
|
572
|
+
|
|
573
|
+
refresh() {
|
|
574
|
+
this.onScroll();
|
|
575
|
+
}
|
|
576
|
+
}
|
|
577
|
+
|
|
578
|
+
// Factory function for easier usage
|
|
579
|
+
function createLazyScroll(container, config) {
|
|
580
|
+
return new LazyScroll(container, config);
|
|
581
|
+
}
|
|
582
|
+
|
|
583
|
+
class LazyScrollElement extends HTMLElement {
|
|
584
|
+
constructor() {
|
|
585
|
+
super();
|
|
586
|
+
this.shadow = this.attachShadow({ mode: 'open' });
|
|
587
|
+
|
|
588
|
+
// Default values
|
|
589
|
+
this.itemHeight = 50;
|
|
590
|
+
this.viewportHeight = 400;
|
|
591
|
+
this.bufferSize = 5;
|
|
592
|
+
this.items = [];
|
|
593
|
+
|
|
594
|
+
// Styles
|
|
595
|
+
const style = document.createElement('style');
|
|
596
|
+
style.textContent = `
|
|
597
|
+
:host {
|
|
598
|
+
display: block;
|
|
599
|
+
}
|
|
600
|
+
|
|
601
|
+
.lazy-scroll-container {
|
|
602
|
+
position: relative;
|
|
603
|
+
overflow-y: auto;
|
|
604
|
+
}
|
|
605
|
+
|
|
606
|
+
.lazy-item {
|
|
607
|
+
width: 100%;
|
|
608
|
+
}
|
|
609
|
+
|
|
610
|
+
.lazy-loading {
|
|
611
|
+
text-align: center;
|
|
612
|
+
padding: 20px;
|
|
613
|
+
color: #666;
|
|
614
|
+
}
|
|
615
|
+
`;
|
|
616
|
+
|
|
617
|
+
this.shadow.appendChild(style);
|
|
618
|
+
}
|
|
619
|
+
|
|
620
|
+
static get observedAttributes() {
|
|
621
|
+
return ['item-height', 'viewport-height', 'buffer-size'];
|
|
622
|
+
}
|
|
623
|
+
|
|
624
|
+
attributeChangedCallback(name, oldValue, newValue) {
|
|
625
|
+
switch (name) {
|
|
626
|
+
case 'item-height':
|
|
627
|
+
this.itemHeight = parseInt(newValue) || 50;
|
|
628
|
+
break;
|
|
629
|
+
case 'viewport-height':
|
|
630
|
+
this.viewportHeight = parseInt(newValue) || 400;
|
|
631
|
+
break;
|
|
632
|
+
case 'buffer-size':
|
|
633
|
+
this.bufferSize = parseInt(newValue) || 5;
|
|
634
|
+
break;
|
|
635
|
+
}
|
|
636
|
+
|
|
637
|
+
if (this.lazyScrollInstance) {
|
|
638
|
+
this.lazyScrollInstance.updateConfig({
|
|
639
|
+
itemHeight: this.itemHeight,
|
|
640
|
+
viewportHeight: this.viewportHeight,
|
|
641
|
+
bufferSize: this.bufferSize
|
|
642
|
+
});
|
|
643
|
+
}
|
|
644
|
+
}
|
|
645
|
+
|
|
646
|
+
connectedCallback() {
|
|
647
|
+
// Create container
|
|
648
|
+
this.container = document.createElement('div');
|
|
649
|
+
this.container.className = 'lazy-scroll-container';
|
|
650
|
+
this.container.style.height = `${this.viewportHeight}px`;
|
|
651
|
+
this.container.style.overflowY = 'auto';
|
|
652
|
+
|
|
653
|
+
this.shadow.appendChild(this.container);
|
|
654
|
+
|
|
655
|
+
// Get fetchMore function from attribute or slot
|
|
656
|
+
const fetchMoreAttr = this.getAttribute('fetch-more');
|
|
657
|
+
let fetchMoreFn = () => Promise.resolve([]);
|
|
658
|
+
|
|
659
|
+
if (fetchMoreAttr) {
|
|
660
|
+
try {
|
|
661
|
+
// If fetchMore is a function name in global scope
|
|
662
|
+
fetchMoreFn = window[fetchMoreAttr] || (() => Promise.resolve([]));
|
|
663
|
+
} catch (e) {
|
|
664
|
+
console.warn('Could not find fetchMore function:', fetchMoreAttr);
|
|
665
|
+
}
|
|
666
|
+
}
|
|
667
|
+
|
|
668
|
+
// Initialize lazy scroll
|
|
669
|
+
this.lazyScrollInstance = createLazyScroll(this.container, {
|
|
670
|
+
itemHeight: this.itemHeight,
|
|
671
|
+
viewportHeight: this.viewportHeight,
|
|
672
|
+
bufferSize: this.bufferSize,
|
|
673
|
+
fetchMore: fetchMoreFn
|
|
674
|
+
});
|
|
675
|
+
|
|
676
|
+
// Handle items from light DOM
|
|
677
|
+
this.updateItemsFromSlot();
|
|
678
|
+
|
|
679
|
+
// Observe child changes
|
|
680
|
+
this.mutationObserver = new MutationObserver(() => {
|
|
681
|
+
this.updateItemsFromSlot();
|
|
682
|
+
});
|
|
683
|
+
|
|
684
|
+
this.mutationObserver.observe(this, { childList: true, subtree: true });
|
|
685
|
+
}
|
|
686
|
+
|
|
687
|
+
disconnectedCallback() {
|
|
688
|
+
if (this.lazyScrollInstance) {
|
|
689
|
+
this.lazyScrollInstance.destroy();
|
|
690
|
+
}
|
|
691
|
+
|
|
692
|
+
if (this.mutationObserver) {
|
|
693
|
+
this.mutationObserver.disconnect();
|
|
694
|
+
}
|
|
695
|
+
}
|
|
696
|
+
|
|
697
|
+
updateItemsFromSlot() {
|
|
698
|
+
// Get items from light DOM or data attribute
|
|
699
|
+
const itemsData = this.getAttribute('items');
|
|
700
|
+
if (itemsData) {
|
|
701
|
+
try {
|
|
702
|
+
const items = JSON.parse(itemsData);
|
|
703
|
+
if (this.lazyScrollInstance) {
|
|
704
|
+
this.lazyScrollInstance.setItems(items);
|
|
705
|
+
}
|
|
706
|
+
} catch (e) {
|
|
707
|
+
console.warn('Could not parse items data:', itemsData);
|
|
708
|
+
}
|
|
709
|
+
}
|
|
710
|
+
}
|
|
711
|
+
|
|
712
|
+
// Public methods
|
|
713
|
+
setItems(items) {
|
|
714
|
+
if (this.lazyScrollInstance) {
|
|
715
|
+
this.lazyScrollInstance.setItems(items);
|
|
716
|
+
}
|
|
717
|
+
}
|
|
718
|
+
|
|
719
|
+
refresh() {
|
|
720
|
+
if (this.lazyScrollInstance) {
|
|
721
|
+
this.lazyScrollInstance.refresh();
|
|
722
|
+
}
|
|
723
|
+
}
|
|
724
|
+
|
|
725
|
+
getVisibleRange() {
|
|
726
|
+
if (this.lazyScrollInstance) {
|
|
727
|
+
return this.lazyScrollInstance.getVisibleRange();
|
|
728
|
+
}
|
|
729
|
+
return { start: 0, end: 0 };
|
|
730
|
+
}
|
|
731
|
+
}
|
|
732
|
+
|
|
733
|
+
// Register the custom element
|
|
734
|
+
customElements.define('lazy-scroll-element', LazyScrollElement);
|
|
735
|
+
|
|
207
736
|
declare class ScrollObserver {
|
|
208
737
|
private container;
|
|
209
738
|
private callback;
|
|
@@ -268,5 +797,5 @@ declare function debounce<T extends (...args: any[]) => any>(func: T, wait: numb
|
|
|
268
797
|
*/
|
|
269
798
|
declare function throttle<T extends (...args: any[]) => any>(func: T, limit: number): (...args: Parameters<T>) => void;
|
|
270
799
|
|
|
271
|
-
export { Engine, IntelligentScrollDetector, LazyList, NetworkAwarePrefetchManager, NetworkAwareRequestQueue, NetworkSpeedDetector, PrefetchManager, RequestQueue, ScrollObserver, WindowManager, debounce, throttle, useLazyList };
|
|
800
|
+
export { AdaptiveBufferCalculator, ContentComplexityAnalyzer, DevicePerformanceMonitor, Engine, GPUAccelerator, IntelligentScrollDetector, LazyList, LazyScroll, LazyScrollComponent, LazyScrollDirective, LazyScrollElement, MemoryManager, NetworkAwarePrefetchManager, NetworkAwareRequestQueue, NetworkSpeedDetector, PerformanceOptimizer, PrefetchManager, RequestQueue, ScrollObserver, WindowManager, createLazyScroll, debounce, lazyScroll, throttle, useLazyList, useLazyScroll };
|
|
272
801
|
export type { EngineConfig, EngineState, FetchMoreCallback, ScrollAnalysis, VisibleRange };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "lazy-render-virtual-scroll",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.8",
|
|
4
4
|
"description": "A framework-agnostic virtual scrolling and lazy rendering solution",
|
|
5
5
|
"main": "dist/cjs/index.js",
|
|
6
6
|
"module": "dist/esm/index.js",
|
|
@@ -25,6 +25,8 @@
|
|
|
25
25
|
"performance",
|
|
26
26
|
"react",
|
|
27
27
|
"vue",
|
|
28
|
+
"Lazy",
|
|
29
|
+
"Lazy-loader",
|
|
28
30
|
"angular",
|
|
29
31
|
"scrolling",
|
|
30
32
|
"infinite-scroll",
|