UNPKG

@pdfme/schemas

Version:

TypeScript base PDF generator and React base UI. Open source, developed by the community, and completely free to use under the MIT license!

89 lines (74 loc) 3.02 kB
import { Schema, BasePdf, BlankPdf, CommonOptions, isBlankPdf } from '@pdfme/common'; import { createSingleTable } from './tableHelper.js'; import { getBodyWithRange, getBody } from './helper.js'; import { TableSchema } from './types.js'; export const getDynamicHeightsForTable = async ( value: string, args: { schema: Schema; basePdf: BasePdf; options: CommonOptions; _cache: Map<string | number, unknown>; }, ): Promise<number[]> => { if (args.schema.type !== 'table') return Promise.resolve([args.schema.height]); const schema = args.schema as TableSchema; const body = schema.__bodyRange?.start === 0 ? getBody(value) : getBodyWithRange(value, schema.__bodyRange); const table = await createSingleTable(body, args); const baseHeights = schema.showHead ? table.allRows().map((row) => row.height) : [0].concat(table.body.map((row) => row.height)); const headerHeight = schema.showHead ? table.getHeadHeight() : 0; const shouldRepeatHeader = schema.repeatHead && isBlankPdf(args.basePdf) && headerHeight > 0; if (!shouldRepeatHeader) { return baseHeights; } const basePdf = args.basePdf as BlankPdf; const [paddingTop, , paddingBottom] = basePdf.padding; const pageContentHeight = basePdf.height - paddingTop - paddingBottom; const getPageStartY = (pageIndex: number) => pageIndex * pageContentHeight + paddingTop; const initialPageIndex = Math.max( 0, Math.floor((schema.position.y - paddingTop) / pageContentHeight), ); const headRowCount = schema.showHead ? table.head.length : 0; const SAFETY_MARGIN = 0.5; let currentPageIndex = initialPageIndex; let currentPageY = schema.position.y; let rowsOnCurrentPage = 0; const result: number[] = []; for (let i = 0; i < baseHeights.length; i++) { const isBodyRow = i >= headRowCount; const rowHeight = baseHeights[i]; while (true) { const currentPageStartY = getPageStartY(currentPageIndex); const remainingHeight = currentPageStartY + pageContentHeight - currentPageY; const needsHeader = isBodyRow && rowsOnCurrentPage === 0 && currentPageIndex > initialPageIndex; const totalRowHeight = rowHeight + (needsHeader ? headerHeight : 0); if (totalRowHeight > remainingHeight - SAFETY_MARGIN) { if (rowsOnCurrentPage === 0 && Math.abs(currentPageY - currentPageStartY) < SAFETY_MARGIN) { result.push(totalRowHeight); currentPageY += totalRowHeight; rowsOnCurrentPage++; break; } currentPageIndex++; currentPageY = getPageStartY(currentPageIndex); rowsOnCurrentPage = 0; continue; } result.push(totalRowHeight); currentPageY += totalRowHeight; rowsOnCurrentPage++; if (currentPageY >= currentPageStartY + pageContentHeight - SAFETY_MARGIN) { currentPageIndex++; currentPageY = getPageStartY(currentPageIndex); rowsOnCurrentPage = 0; } break; } } return result; };