Files
FliesentischKingandDevin d6e578dac8 Tighter pagination reserve in page size calculation
The reserve was ~24px larger than the actual pagination block,
which could cost the grid a full row at boundary viewport heights.

Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-10-04 03:06:48 +02:00

42 lines
1.8 KiB
TypeScript

import type { Ref } from 'vue'
import { useWindowSize } from '@vueuse/core'
// Spiegelt das Upload-Grid aus index.vue:
// grid-cols-4 sm:6 md:8 lg:12, auto-rows 6.5rem / sm:7rem / lg:7.5rem, gap-2
const PAGINATION_RESERVE_PX = 60 // Pagination (~36px) + pt-4, knapp bemessen damit die letzte Zeile nicht wegfällt
const FALLBACK_TOP_PX = 150 // SSR-Schätzung: Header + Padding + Filterzeile
interface PageSizeOptions {
// [base, sm (>=640px), lg (>=1024px)] — Zeilenhöhe in rem ohne Grid-Gap
rowHeights?: [number, number, number]
// Abstand zwischen Anker-Unterkante und Grid-Oberkante in px (mb-* der Zeile)
gapBelowAnchorPx?: number
}
export function usePageSize(anchor: Ref<HTMLElement | null | undefined>, options: PageSizeOptions = {}) {
const { rowHeights = [6.5, 7, 7.5], gapBelowAnchorPx = 8 } = options
const { width, height } = useWindowSize()
const cols = computed(() => {
const w = Number.isFinite(width.value) ? width.value : 1280
return w >= 1024 ? 12 : w >= 768 ? 8 : w >= 640 ? 6 : 4
})
// Zell-Budget: Wie viele 1x1-Zellen passen ohne Scrollen in den Viewport.
// Die Grid-Oberkante wird am DOM-Element (Filterzeile) gemessen statt
// Header/Padding zu schätzen.
const cells = computed(() => {
const w = Number.isFinite(width.value) ? width.value : 1280
const h = Number.isFinite(height.value) ? height.value : 800
const rem = import.meta.client
? Number.parseFloat(getComputedStyle(document.documentElement).fontSize) || 16
: 16
const rowH = (w >= 1024 ? rowHeights[2] : w >= 640 ? rowHeights[1] : rowHeights[0]) * rem + 8 // + grid gap
const top = (anchor.value?.getBoundingClientRect().bottom ?? FALLBACK_TOP_PX) + gapBelowAnchorPx
const rows = Math.max(1, Math.floor((h - top - PAGINATION_RESERVE_PX) / rowH))
return cols.value * rows
})
return { cells, cols }
}