import { dataGridLayoutSignature, dataGridWidthsForLayout, distributeDataGridResizeAmount, effectiveDataGridColumnMinWidth, fitDataGridColumns, type DataGridSizingColumn } from "../src/components/table/dataGridSizing"; function assertEqual(actual: T, expected: T, message: string): void { if (actual !== expected) throw new Error(`${message}: expected ${String(expected)}, got ${String(actual)}`); } function assertWidths( actual: Record, expected: Record, message: string ): void { for (const [columnId, width] of Object.entries(expected)) { assertEqual(actual[columnId], width, `${message} (${columnId})`); } } const minmaxColumn: DataGridSizingColumn = { id: "recipients", width: "minmax(320px, 1.4fr)", resizable: true, sortable: true, filterable: true }; assertEqual( effectiveDataGridColumnMinWidth(minmaxColumn), 320, "a minmax lower bound remains the resize minimum" ); const weightedColumns: DataGridSizingColumn[] = [ { id: "fixed", width: 100 }, { id: "primary", width: "minmax(100px, 1fr)", minWidth: 100, maxWidth: 500 }, { id: "secondary", width: "minmax(100px, 2fr)", minWidth: 100, maxWidth: 500 } ]; const weightedLayout = fitDataGridColumns(weightedColumns, 600); assertWidths( weightedLayout.widths, { fixed: 100, primary: 200, secondary: 300 }, "fraction tracks receive residual width by declared weight" ); assertEqual(weightedLayout.bufferWidth, 0, "fraction tracks cover the available container"); const boundedLayout = fitDataGridColumns([ { id: "fixed", width: 100 }, { id: "primary", width: "minmax(100px, 1fr)", minWidth: 100, maxWidth: 150 }, { id: "secondary", width: "minmax(100px, 2fr)", minWidth: 100, maxWidth: 200 } ], 600); assertWidths( boundedLayout.widths, { fixed: 100, primary: 150, secondary: 200 }, "fraction tracks stop at their declared maxima" ); assertEqual(boundedLayout.bufferWidth, 150, "space beyond column maxima becomes the synthetic buffer"); const overflowLayout = fitDataGridColumns([ { id: "fixed", width: 200 }, { id: "primary", width: "minmax(320px, 1fr)", resizable: true }, { id: "secondary", width: "minmax(260px, 1fr)", resizable: true } ], 600); assertWidths( overflowLayout.widths, { fixed: 200, primary: 320, secondary: 260 }, "columns never shrink below declared minima" ); assertEqual(overflowLayout.overflowWidth, 180, "minimum-width excess remains horizontal overflow"); const percentageLayout = fitDataGridColumns([ { id: "fixed", width: 100 }, { id: "primary", width: "30%", minWidth: 100 }, { id: "secondary", width: "20%", minWidth: 100 } ], 1000); assertWidths( percentageLayout.widths, { fixed: 100, primary: 300, secondary: 200 }, "percentage tracks retain their preferred container share" ); assertEqual(percentageLayout.bufferWidth, 400, "unused percentage space remains a neutral buffer"); const overriddenLayout = fitDataGridColumns(weightedColumns, 800, {}, { primary: 450 }); assertWidths( overriddenLayout.widths, { fixed: 100, primary: 450, secondary: 250 }, "a user-resized track stays fixed while responsive peers absorb container changes" ); const overriddenOverflowLayout = fitDataGridColumns(weightedColumns, 500, {}, { primary: 450 }); assertWidths( overriddenOverflowLayout.widths, { fixed: 100, primary: 450, secondary: 100 }, "a narrow viewport preserves the user override without squashing peers below their minima" ); assertEqual( overriddenOverflowLayout.overflowWidth, 150, "a user override that cannot fit becomes horizontal overflow" ); const clampedOverrideLayout = fitDataGridColumns(weightedColumns, 800, {}, { primary: 900 }); assertEqual( clampedOverrideLayout.widths.primary, 500, "user overrides remain bounded by the column maximum" ); const redistributedGrowth = distributeDataGridResizeAmount(300, [ { columnId: "bounded", startWidth: 100, minWidth: 100, maxWidth: 150, weight: 1 }, { columnId: "remaining", startWidth: 100, minWidth: 100, maxWidth: 500, weight: 1 } ]); assertWidths( redistributedGrowth.amounts, { bounded: 50, remaining: 250 }, "unused growth is redistributed after a peer reaches its maximum" ); assertEqual(redistributedGrowth.applied, 300, "bounded weighted growth applies the complete available amount"); const boundedShrink = distributeDataGridResizeAmount(-300, [ { columnId: "primary", startWidth: 300, minWidth: 200, maxWidth: 500, weight: 1 }, { columnId: "secondary", startWidth: 300, minWidth: 250, maxWidth: 500, weight: 1 } ]); assertWidths( boundedShrink.amounts, { primary: -100, secondary: -50 }, "shrink distribution stops every peer at its minimum" ); assertEqual(boundedShrink.applied, -150, "unavailable shrink remains unapplied instead of squashing columns"); const legacyFillLayout = fitDataGridColumns([ { id: "fixed", width: 100 }, { id: "fill", width: 200, minWidth: 120, maxWidth: 450, fill: true } ], 500); assertWidths( legacyFillLayout.widths, { fixed: 100, fill: 400 }, "legacy fill columns remain stable under the explicit sizing contract" ); const originalSignature = dataGridLayoutSignature(weightedColumns, "container", "cover"); const changedSignature = dataGridLayoutSignature( weightedColumns.map((column) => column.id === "primary" ? { ...column, maxWidth: 420 } : column), "container", "cover" ); assertEqual( dataGridWidthsForLayout(originalSignature, originalSignature, { primary: 450 })?.primary, 450, "matching layout signatures restore user widths" ); assertEqual( dataGridWidthsForLayout(originalSignature, changedSignature, { primary: 450 }), undefined, "stale layout signatures discard user widths" ); assertEqual( dataGridLayoutSignature(weightedColumns, "container", "free") === originalSignature, false, "free and cover layouts keep independent user overrides" );