Skip to content

Commit 9706ae6

Browse files
committed
⚡️(frontend) improve fallback width calculation
Sometimes we do not have the width of some columns in a table. In such cases, we need to calculate a fallback width to ensure the table is rendered correctly. We were previously using 120 points as the fallback width, but this has been improved to better fit the content. We now check the size left and distribute it among the unknown columns.
1 parent 814eb1f commit 9706ae6

File tree

2 files changed

+99
-9
lines changed

2 files changed

+99
-9
lines changed
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
import { describe, expect, it } from 'vitest';
2+
3+
import { utilTable } from '../blocks-mapping/tablePDF';
4+
5+
/**
6+
* Tests for utilTable utility.
7+
* Scenarios covered:
8+
* - All widths specified and below full width
9+
* - Mix of known / unknown widths (fallback distribution)
10+
* - All widths unknown
11+
* - Widths exceeding full table width (clamping & scale=100)
12+
* - Sum exceeding full width without unknowns (no division by zero side-effects)
13+
*/
14+
15+
describe('utilTable', () => {
16+
it('returns unchanged widths and correct scale when all widths are known and below full width', () => {
17+
const input = [165, 200];
18+
const { columnWidths, tableScale } = utilTable(730, input);
19+
expect(columnWidths).toEqual(input); // unchanged
20+
expect(tableScale).toBe(50);
21+
});
22+
23+
it('distributes fallback width equally among unknown columns', () => {
24+
const input: (number | undefined)[] = [100, undefined, 200, undefined];
25+
const { columnWidths, tableScale } = utilTable(730, input);
26+
expect(columnWidths).toEqual([100, 215, 200, 215]);
27+
expect(tableScale).toBe(100); // fills full width exactly
28+
});
29+
30+
it('handles all columns unknown', () => {
31+
const input: (number | undefined)[] = [undefined, undefined];
32+
const { columnWidths, tableScale } = utilTable(730, input);
33+
expect(columnWidths).toEqual([365, 365]);
34+
expect(tableScale).toBe(100);
35+
});
36+
37+
it('clamps total width to full width when sum exceeds it (single large column)', () => {
38+
const input = [800];
39+
const { columnWidths, tableScale } = utilTable(730, input);
40+
expect(columnWidths).toEqual([800]);
41+
expect(tableScale).toBe(100);
42+
});
43+
44+
it('clamps total width to full width when multiple columns exceed it', () => {
45+
const input = [500, 300]; // sum = 800 > 730
46+
const { columnWidths, tableScale } = utilTable(730, input);
47+
expect(columnWidths).toEqual([500, 300]);
48+
expect(tableScale).toBe(100);
49+
});
50+
51+
it('does not assign fallback when there are no unknown widths (avoid division by zero impact)', () => {
52+
const input = [400, 400];
53+
const { columnWidths, tableScale } = utilTable(730, input);
54+
expect(columnWidths).toEqual([400, 400]);
55+
expect(tableScale).toBe(100);
56+
});
57+
58+
it('computes proportional scale with custom fullWidth', () => {
59+
const input = [100, 200]; // total 300
60+
const { columnWidths, tableScale } = utilTable(1000, input);
61+
expect(columnWidths).toEqual([100, 200]);
62+
expect(tableScale).toBe(30);
63+
});
64+
});

src/frontend/apps/impress/src/features/docs/doc-export/blocks-mapping/tablePDF.tsx

Lines changed: 35 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import { StyleSheet, Text } from '@react-pdf/renderer';
1313

1414
import { DocsExporterPDF } from '../types';
1515
const PIXELS_PER_POINT = 0.75;
16+
const FULL_WIDTH = 730;
1617
const styles = StyleSheet.create({
1718
tableContainer: {
1819
border: '1px solid #ddd',
@@ -47,16 +48,10 @@ export const blockMappingTablePDF: DocsExporterPDF['mappings']['blockMapping']['
4748
true,
4849
) as boolean[];
4950

50-
/**
51-
* Calculate the table scale based on the column widths.
52-
*/
53-
const columnWidths = blockContent.columnWidths.map((w) => w || 120);
54-
const fullWidth = 730;
55-
const totalWidth = Math.min(
56-
columnWidths.reduce((sum, w) => sum + w, 0),
57-
fullWidth,
51+
const { columnWidths, tableScale } = utilTable(
52+
FULL_WIDTH,
53+
blockContent.columnWidths,
5854
);
59-
const tableScale = (totalWidth * 100) / fullWidth;
6055

6156
return (
6257
<Table style={[styles.tableContainer, { width: `${tableScale}%` }]}>
@@ -124,3 +119,34 @@ export const blockMappingTablePDF: DocsExporterPDF['mappings']['blockMapping']['
124119
</Table>
125120
);
126121
};
122+
123+
/**
124+
* Utility function to calculate the table column widths and scale.
125+
* @param columnWidths - Array of column widths.
126+
* @returns An object containing the resized column widths and the table scale.
127+
*/
128+
export const utilTable = (
129+
fullWidth: number,
130+
columnWidths: (number | undefined)[],
131+
) => {
132+
const totalColumnWidthKnown = columnWidths.reduce(
133+
(sum: number, w) => sum + (w ?? 0),
134+
0,
135+
);
136+
const nbColumnWidthUnknown = columnWidths.filter((w) => !w).length;
137+
138+
const fallbackWidth =
139+
(fullWidth - totalColumnWidthKnown) / nbColumnWidthUnknown;
140+
141+
const columnWidthsResized = columnWidths.map((w) => w || fallbackWidth);
142+
const totalWidth = Math.min(
143+
columnWidthsResized.reduce((sum: number, w) => sum + w, 0),
144+
fullWidth,
145+
);
146+
const tableScale = Math.round(((totalWidth * 100) / fullWidth) * 1000) / 1000;
147+
148+
return {
149+
columnWidths: columnWidthsResized,
150+
tableScale,
151+
};
152+
};

0 commit comments

Comments
 (0)