paginateflow-sdk
v0.1.0
Published
EU Infinite Scrolling Compliance SDK - Drop-in React pagination for GDPR compliance
Maintainers
Readme
@vibecaas/paginate-flow
EU Infinite Scrolling Compliance SDK - A drop-in React pagination library for GDPR/DSA compliance with virtual scrolling for high-performance rendering.
🌍 Why PaginateFlow?
The EU's Digital Services Act (DSA) bans manipulative infinite scrolling on social platforms. PaginateFlow provides a compliant alternative with:
- ✅ GDPR/DSA Compliant - Explicit pagination replaces infinite scrolling
- ✅ Virtual Scrolling - Renders only visible items (10,000+ items without lag)
- ✅ Auto Load Detection - Triggers 500px before end of list
- ✅ Analytics Hooks - Track page loads, scroll depth, and user engagement
- ✅ Zero Runtime Dependencies - Only TanStack Virtual as peer dependency
- ✅ Small Bundle - ~23KB unzipped (6.88KB gzipped)
📦 Installation
npm install @vibecaas/paginate-flow @tanstack/react-virtualor
yarn add @vibecaas/paginate-flow @tanstack/react-virtualor
pnpm add @vibecaas/paginate-flow @tanstack/react-virtual🚀 Quick Start
import { VirtualizedList } from '@vibecaas/paginate-flow';
function App() {
const [items, setItems] = useState([]);
const [hasMore, setHasMore] = useState(true);
const fetchNextPage = async () => {
const newItems = await fetch('/api/items?page=' + currentPage);
setItems(prev => [...prev, ...newItems]);
setHasMore(newItems.length > 0);
};
return (
<VirtualizedList
items={items}
renderItem={(item) => <Card key={item.id} {...item} />}
onLoadMore={fetchNextPage}
hasMore={hasMore}
estimatedItemHeight={150}
height="100vh"
/>
);
}📚 Components
VirtualizedList
The main component for efficient list rendering with pagination.
<VirtualizedList<T>
items={T[]}
renderItem={(item: T, index: number) => ReactNode}
getItemKey?: (item: T, index: number) => string | number
estimatedItemHeight?: number // Default: 80px
height?: number | string // Default: "100vh"
onLoadMore?: () => void | Promise<void>
hasMore?: boolean
loadMoreThreshold?: number // Default: 500px
analytics?: AnalyticsHandlers
loadingComponent?: ReactNode
showComplianceBadge?: boolean // Default: true
footer?: ReactNode
/>LoadMoreButton
A standalone button component for manual load more triggers.
<LoadMoreButton
hasMore={boolean}
isLoading?: boolean
onLoadMore={() => void | Promise<void>}
loadingLabel?: string
idleLabel?: string
disabled?: boolean
className?: string
/>ComplianceBadge
GDPR compliance badge component.
<ComplianceBadge
position?: 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right'
label?: string
className?: string
showTooltip?: boolean
tooltipText?: string
/>🪝 Hooks
usePagination
Manage pagination state.
const { state, nextPage, prevPage, goToPage, reset } = usePagination({
itemsPerPage: 20,
initialPage: 1,
totalItems: 100,
fetchPage: async (page: number) => { ... }
});
// State: { currentPage, totalPages, itemsPerPage, totalItems, isLoading, hasMore }useScrollAnalytics
Track scroll events for analytics.
const { scrollDepth, handleScroll, resetTracking, trackPageLoad, trackItemRender } = useScrollAnalytics({
analytics: {
onPageLoad: (page) => Analytics.track('page_loaded', { page }),
onScrollDepth: (depth) => Analytics.track('scroll_depth', { depth }),
onItemRender: (item, index) => Analytics.track('item_rendered', { index })
},
throttleMs: 100
});📊 Analytics Integration
PaginateFlow provides hooks for tracking user engagement:
<VirtualizedList
items={items}
renderItem={renderItem}
onLoadMore={fetchNextPage}
hasMore={hasMore}
analytics={{
onPageLoad: (page) => {
// Fire when a new page loads
console.log('Page loaded:', page);
Analytics.track('page_loaded', { page });
},
onItemRender: (item, index) => {
// Fire when an item is rendered
console.log('Item rendered:', index);
Analytics.track('item_rendered', { index });
},
onScrollDepth: (depth) => {
// Fire when scroll depth changes
console.log('Scroll depth:', depth);
Analytics.track('scroll_depth', {
page: depth.page,
percentage: depth.percentage,
visibleItems: depth.visibleItems,
totalItems: depth.totalItems,
});
},
}}
/>🎨 Styling
PaginateFlow is styled with Tailwind CSS classes. The components expose className props for customization:
<LoadMoreButton className="w-full max-w-md mx-auto" />
<ComplianceBadge className="top-4 right-4" />🔧 TypeScript
Full TypeScript support with exported types:
import type {
VirtualizedListProps,
AnalyticsHandlers,
ScrollDepth,
PaginationState,
UsePaginationOptions
} from '@vibecaas/paginate-flow';📝 Example Usage
See the demo app for a complete implementation or visit the live demo at:
Mock Data Example
const generatePosts = (startId: number, count: number) => {
return Array.from({ length: count }, (_, i) => ({
id: startId + i,
title: `Post #${startId + i}`,
content: '...',
}));
};
<VirtualizedList
items={posts}
renderItem={(post) => <PostCard key={post.id} {...post} />}
onLoadMore={() => {
const newPosts = generatePosts(posts.length, 20);
setPosts(prev => [...prev, ...newPosts]);
}}
hasMore={posts.length < 200}
analytics={analytics}
/>🧪 Performance
- ✅ Renders 10,000+ items without lag
- ✅ Only renders visible items (virtual scrolling)
- ✅ Debounced scroll events (100ms default)
- ✅ Optimized re-rendering with React.memo
🛡️ GDPR/DSA Compliance
PaginateFlow helps you comply with:
- EU Digital Services Act (DSA) - Article 25 bans dark patterns like infinite scrolling
- GDPR Article 25 (Data Protection by Design) - Explicit user control over content consumption
The compliance badge signals to users that your app respects EU regulations.
📦 Bundle Size
dist/index.js 22.84 kB │ gzip: 6.88 kBUnder 4 MB constraint (achieved ✅)
🔗 Dependencies
Peer Dependencies (must be installed separately):
react^18.0.0 || ^19.0.0react-dom^18.0.0 || ^19.0.0
Runtime Dependencies:
@tanstack/virtual-core^3.10.7@tanstack/react-virtual^3.10.7
📄 License
MIT © 2026 VibeCaaS
🤝 Contributing
Contributions welcome! Please read our contributing guidelines.
📮 Support
- GitHub Issues: github.com/vibecaas/paginate-flow/issues
- Demo: demo.paginateflow.dev
Built with ❤️ for EU compliance ⚖️️🇪🇺
