fix(grid): expand auto-fit column width

This commit is contained in:
t8y2 2026-06-29 01:44:35 +08:00
parent 2d2284a0ef
commit ca30e8ff2d
3 changed files with 46 additions and 6 deletions

View File

@ -1,6 +1,6 @@
import { ref, computed, watch, type ComputedRef, type Ref } from "vue";
import { useElementSize } from "@vueuse/core";
import { calculateDataGridColumnWidth, DATA_GRID_COL_MIN_WIDTH, DATA_GRID_SAMPLE_ROWS } from "@/lib/dataGridColumnWidth";
import { calculateDataGridColumnWidth, DATA_GRID_AUTO_FIT_VALUE_TEXT_LIMIT, DATA_GRID_COL_AUTO_FIT_MAX_WIDTH, DATA_GRID_COL_MIN_WIDTH, DATA_GRID_SAMPLE_ROWS } from "@/lib/dataGridColumnWidth";
type CellValue = string | number | boolean | null;
@ -78,6 +78,8 @@ export function useDataGridColumnResize(options: UseDataGridColumnResizeOptions)
columnWidths.value[colIdx] = calculateDataGridColumnWidth({
columnName: colName,
sampleValues: sampleColumnValues(colIdx),
maxWidth: DATA_GRID_COL_AUTO_FIT_MAX_WIDTH,
valueTextLimit: DATA_GRID_AUTO_FIT_VALUE_TEXT_LIMIT,
});
}

View File

@ -2,10 +2,13 @@ type CellValue = string | number | boolean | null;
export const DATA_GRID_COL_MIN_WIDTH = 60;
export const DATA_GRID_COL_MAX_WIDTH = 400;
export const DATA_GRID_COL_AUTO_FIT_MAX_WIDTH = 1200;
export const DATA_GRID_CHAR_WIDTH = 8;
export const DATA_GRID_HEADER_CONTROL_WIDTH = 80;
export const DATA_GRID_CELL_PADDING = 28;
export const DATA_GRID_SAMPLE_ROWS = 50;
export const DATA_GRID_VALUE_TEXT_LIMIT = 60;
export const DATA_GRID_AUTO_FIT_VALUE_TEXT_LIMIT = 160;
function estimateTextWidth(text: string, padding: number): number {
return text.length * DATA_GRID_CHAR_WIDTH + padding;
@ -16,16 +19,18 @@ function displaySampleValue(value: CellValue): string | null {
return typeof value === "object" ? JSON.stringify(value) : String(value);
}
export function calculateDataGridColumnWidth(options: { columnName: string; sampleValues: readonly CellValue[] }): number {
let maxWidth = estimateTextWidth(options.columnName, DATA_GRID_HEADER_CONTROL_WIDTH);
export function calculateDataGridColumnWidth(options: { columnName: string; sampleValues: readonly CellValue[]; maxWidth?: number; valueTextLimit?: number }): number {
const maxAllowedWidth = options.maxWidth ?? DATA_GRID_COL_MAX_WIDTH;
const valueTextLimit = options.valueTextLimit ?? DATA_GRID_VALUE_TEXT_LIMIT;
let maxContentWidth = estimateTextWidth(options.columnName, DATA_GRID_HEADER_CONTROL_WIDTH);
for (const value of options.sampleValues.slice(0, DATA_GRID_SAMPLE_ROWS)) {
const text = displaySampleValue(value);
if (text == null) continue;
const displayLen = Math.min(text.length, 60);
const displayLen = Math.min(text.length, valueTextLimit);
const width = displayLen * DATA_GRID_CHAR_WIDTH + DATA_GRID_CELL_PADDING;
if (width > maxWidth) maxWidth = width;
if (width > maxContentWidth) maxContentWidth = width;
}
return Math.max(DATA_GRID_COL_MIN_WIDTH, Math.min(DATA_GRID_COL_MAX_WIDTH, Math.round(maxWidth)));
return Math.max(DATA_GRID_COL_MIN_WIDTH, Math.min(maxAllowedWidth, Math.round(maxContentWidth)));
}

View File

@ -0,0 +1,33 @@
import { expect, test } from "vitest";
import { calculateDataGridColumnWidth, DATA_GRID_AUTO_FIT_VALUE_TEXT_LIMIT, DATA_GRID_COL_AUTO_FIT_MAX_WIDTH, DATA_GRID_COL_MAX_WIDTH } from "../../apps/desktop/src/lib/dataGridColumnWidth.ts";
test("default data grid column width remains compact for long values", () => {
const width = calculateDataGridColumnWidth({
columnName: "description",
sampleValues: ["x".repeat(120)],
});
expect(width).toBe(DATA_GRID_COL_MAX_WIDTH);
});
test("auto-fit data grid column width expands long values beyond default width", () => {
const width = calculateDataGridColumnWidth({
columnName: "description",
sampleValues: ["x".repeat(120)],
maxWidth: DATA_GRID_COL_AUTO_FIT_MAX_WIDTH,
valueTextLimit: DATA_GRID_AUTO_FIT_VALUE_TEXT_LIMIT,
});
expect(width).toBeGreaterThan(DATA_GRID_COL_MAX_WIDTH);
});
test("auto-fit data grid column width stays bounded for very long values", () => {
const width = calculateDataGridColumnWidth({
columnName: "description",
sampleValues: ["x".repeat(1000)],
maxWidth: DATA_GRID_COL_AUTO_FIT_MAX_WIDTH,
valueTextLimit: DATA_GRID_AUTO_FIT_VALUE_TEXT_LIMIT,
});
expect(width).toBe(DATA_GRID_COL_AUTO_FIT_MAX_WIDTH);
});