import { PDFDocument, PDFPage } from "pdf-lib"; import { drawTable, DrawTableError, DrawTableOptions, CellContent } from "./index"; interface TableData { rows: CellContent[][]; options?: DrawTableOptions; } interface DrawTableWithOverflowOptions { allowCreateNewPageOnOverflow: boolean; startYOnNewPage?: number; getNextPage?: (currentPage: PDFPage, pdfDoc: PDFDocument) => PDFPage; maxPages: number; bottomMargin?: number; } export async function drawTableWithOverflow( pdfDoc: PDFDocument, page: PDFPage, tableData: TableData, startX: number, startY: number, overflowOptions: DrawTableWithOverflowOptions ) { let currentPage = page; let currentY = startY; let pageNumber = 1; let rowsToDraw = [...tableData.rows]; let headers: CellContent[] | null = tableData.options?.header?.hasHeaderRow ? (rowsToDraw.shift() as CellContent[]) : null; const drawPage = async (rows: CellContent[][]) => { try { await drawTable( pdfDoc, currentPage, headers ? [headers, ...rows] : rows, startX, currentY, tableData.options || {} ); } catch (error) { if (error instanceof DrawTableError && error.code === "ERR_TABLE_HEIGHT_OVERFLOW") { return error.rowHeights; } else { throw error; } } }; do { console.log('Rows remaining:', rowsToDraw.length); if (pageNumber > overflowOptions.maxPages) { throw new Error("Maximum page limit reached."); } const rowHeights = await drawPage(rowsToDraw); if (rowHeights) { if (!overflowOptions.allowCreateNewPageOnOverflow || pageNumber >= overflowOptions.maxPages) { throw new Error("Page limit reached or new pages not allowed."); } pageNumber !=1 && pageNumber++; currentPage = getNextPageForOverflow(pdfDoc, currentPage, overflowOptions); currentY = overflowOptions.startYOnNewPage ?? startY; //headers = null; // Only draw headers on the first page let availableSpace = currentY - (overflowOptions.bottomMargin ?? 50); console.log('Available space:', availableSpace, 'Row heights:', rowHeights); let index = 0; let accumulatedHeight = 0; while (index < rowHeights.length) { if (accumulatedHeight + rowHeights[index] > availableSpace) { break; } accumulatedHeight += rowHeights[index]; index++; } console.log('Rows fitting on the page:', index); const rowsForNextPage = rowsToDraw.slice(0, index); rowsToDraw = rowsToDraw.slice(index); if (index < rowHeights.length) { await drawPage(rowsForNextPage); } } // If no overflow error and rows remain, draw them on a new page if (!rowHeights && rowsToDraw.length > 0) { pageNumber++; currentPage = getNextPageForOverflow(pdfDoc, currentPage, overflowOptions); currentY = overflowOptions.startYOnNewPage ?? startY; headers = null; // Headers are only for the first page await drawPage(rowsToDraw); break; // After drawing the remaining rows, exit the loop } } while (rowsToDraw.length > 0); } function getNextPageForOverflow( pdfDoc: PDFDocument, currentPage: PDFPage, overflowOptions: DrawTableWithOverflowOptions ): PDFPage { return overflowOptions.getNextPage ? overflowOptions.getNextPage(currentPage, pdfDoc) : pdfDoc.addPage(); }