feature/responsive #22
@@ -202,6 +202,16 @@ export function createVirtualizer<T>(
|
||||
});
|
||||
}
|
||||
|
||||
// console.log('🎯 Virtual Items Calculation:', {
|
||||
// scrollOffset,
|
||||
// containerHeight,
|
||||
// viewportEnd,
|
||||
// startIdx,
|
||||
// endIdx,
|
||||
// withOverscan: { start, end },
|
||||
// itemCount: end - start,
|
||||
// });
|
||||
|
||||
return result;
|
||||
});
|
||||
// Svelte Actions (The DOM Interface)
|
||||
@@ -225,32 +235,48 @@ export function createVirtualizer<T>(
|
||||
return rect.top + window.scrollY;
|
||||
};
|
||||
|
||||
let cachedOffsetTop = getElementOffset();
|
||||
let cachedOffsetTop = 0;
|
||||
let rafId: number | null = null;
|
||||
containerHeight = window.innerHeight;
|
||||
|
||||
const handleScroll = () => {
|
||||
// Use cached offset for scroll calculations
|
||||
scrollOffset = Math.max(0, window.scrollY - cachedOffsetTop);
|
||||
if (rafId !== null) return;
|
||||
|
||||
rafId = requestAnimationFrame(() => {
|
||||
// Get current position of element relative to viewport
|
||||
const rect = node.getBoundingClientRect();
|
||||
// Calculate how much of the element has scrolled past the top of viewport
|
||||
// When element.top is 0, element is at top of viewport
|
||||
// When element.top is -100, element has scrolled up 100px past viewport top
|
||||
const scrolledPastTop = Math.max(0, -rect.top);
|
||||
scrollOffset = scrolledPastTop;
|
||||
rafId = null;
|
||||
});
|
||||
|
||||
// 🔍 DIAGNOSTIC
|
||||
// console.log('📜 Scroll Event:', {
|
||||
// windowScrollY: window.scrollY,
|
||||
// elementRectTop: rect.top,
|
||||
// scrolledPastTop,
|
||||
// containerHeight
|
||||
// });
|
||||
};
|
||||
|
||||
const handleResize = () => {
|
||||
const oldHeight = containerHeight;
|
||||
containerHeight = window.innerHeight;
|
||||
|
||||
// Recalculate offset on resize (layout may have shifted)
|
||||
const newOffsetTop = getElementOffset();
|
||||
if (Math.abs(newOffsetTop - cachedOffsetTop) > 0.5) {
|
||||
cachedOffsetTop = newOffsetTop;
|
||||
handleScroll(); // Recalculate scroll position
|
||||
}
|
||||
cachedOffsetTop = getElementOffset();
|
||||
handleScroll();
|
||||
};
|
||||
|
||||
// Initial setup
|
||||
requestAnimationFrame(() => {
|
||||
cachedOffsetTop = getElementOffset();
|
||||
handleScroll();
|
||||
});
|
||||
|
||||
window.addEventListener('scroll', handleScroll, { passive: true });
|
||||
window.addEventListener('resize', handleResize);
|
||||
|
||||
// Initial calculation
|
||||
handleScroll();
|
||||
|
||||
return {
|
||||
destroy() {
|
||||
window.removeEventListener('scroll', handleScroll);
|
||||
@@ -259,6 +285,10 @@ export function createVirtualizer<T>(
|
||||
cancelAnimationFrame(frameId);
|
||||
frameId = null;
|
||||
}
|
||||
if (rafId !== null) {
|
||||
cancelAnimationFrame(rafId);
|
||||
rafId = null;
|
||||
}
|
||||
elementRef = null;
|
||||
},
|
||||
};
|
||||
@@ -366,6 +396,12 @@ export function createVirtualizer<T>(
|
||||
}
|
||||
|
||||
return {
|
||||
get scrollOffset() {
|
||||
return scrollOffset;
|
||||
},
|
||||
get containerHeight() {
|
||||
return containerHeight;
|
||||
},
|
||||
/** Computed array of visible items to render (reactive) */
|
||||
get items() {
|
||||
return items;
|
||||
|
||||
Reference in New Issue
Block a user