feat(grid): show column comments in condition suggestions
This commit is contained in:
7 files changed
+174
-21
No files matched your search
+32
-1
@@ -1,6 +1,6 @@
|
||||
import { describe, expect, test } from "vitest";
|
||||
|
||||
import { getDataGridConditionSuggestionPosition } from "@/lib/dataGrid/dataGridConditionSuggestionPosition";
|
||||
import { getDataGridConditionSuggestionPosition, getDataGridConditionSuggestionPreferredWidth } from "@/lib/dataGrid/dataGridConditionSuggestionPosition";
|
||||
|
||||
describe("getDataGridConditionSuggestionPosition", () => {
|
||||
test("anchors the dropdown to the input instead of the caret", () => {
|
||||
@@ -21,4 +21,35 @@ describe("getDataGridConditionSuggestionPosition", () => {
|
||||
|
||||
expect(position.width).toBe(180);
|
||||
});
|
||||
|
||||
test("widens commented field suggestions within the configured maximum", () => {
|
||||
const preferredWidth = getDataGridConditionSuggestionPreferredWidth([
|
||||
{ value: "customer_external_identifier", kind: "column", comment: "客户外部系统唯一标识" },
|
||||
{ value: "customer_name", kind: "column", comment: "客户名称" },
|
||||
]);
|
||||
const position = getDataGridConditionSuggestionPosition({ left: 120, bottom: 40, width: 220 }, { viewportWidth: 1000, preferredWidth, maxWidth: 520 });
|
||||
|
||||
expect(preferredWidth).toBeGreaterThan(220);
|
||||
expect(position.width).toBe(preferredWidth);
|
||||
expect(position.width).toBeLessThanOrEqual(520);
|
||||
});
|
||||
|
||||
test("keeps normal width when suggestions have no comments or are history entries", () => {
|
||||
expect(
|
||||
getDataGridConditionSuggestionPreferredWidth([
|
||||
{ value: "customer_id", kind: "column", comment: "" },
|
||||
{ value: "status = 'active'", kind: "history" },
|
||||
]),
|
||||
).toBeUndefined();
|
||||
|
||||
const position = getDataGridConditionSuggestionPosition({ left: 120, bottom: 40, width: 220 }, { viewportWidth: 1000, preferredWidth: undefined, maxWidth: 520 });
|
||||
expect(position.width).toBe(220);
|
||||
});
|
||||
|
||||
test("caps commented suggestions to both the maximum and the viewport", () => {
|
||||
const position = getDataGridConditionSuggestionPosition({ left: 760, bottom: 40, width: 180 }, { viewportWidth: 420, preferredWidth: 800, maxWidth: 520 });
|
||||
|
||||
expect(position.width).toBe(404);
|
||||
expect(position.left + position.width).toBeLessThanOrEqual(412);
|
||||
});
|
||||
});
|
||||
@@ -7,6 +7,8 @@ export interface DataGridConditionSuggestionRect {
|
||||
export interface DataGridConditionSuggestionPositionOptions {
|
||||
viewportWidth: number;
|
||||
minWidth?: number;
|
||||
preferredWidth?: number;
|
||||
maxWidth?: number;
|
||||
viewportMargin?: number;
|
||||
topOffset?: number;
|
||||
}
|
||||
@@ -17,12 +19,33 @@ export interface DataGridConditionSuggestionPosition {
|
||||
width: number;
|
||||
}
|
||||
|
||||
export interface DataGridConditionSuggestionContent {
|
||||
value: string;
|
||||
kind: "column" | "history";
|
||||
comment?: string | null;
|
||||
}
|
||||
|
||||
const COMMENTED_SUGGESTION_MIN_WIDTH = 360;
|
||||
const COMMENTED_SUGGESTION_MAX_WIDTH = 520;
|
||||
|
||||
function textWidthUnits(value: string): number {
|
||||
return [...value].reduce((total, character) => total + (character.charCodeAt(0) > 0xff ? 2 : 1), 0);
|
||||
}
|
||||
|
||||
export function getDataGridConditionSuggestionPreferredWidth(suggestions: readonly DataGridConditionSuggestionContent[]): number | undefined {
|
||||
const hasComment = suggestions.some((suggestion) => suggestion.kind === "column" && !!suggestion.comment?.trim());
|
||||
if (!hasComment) return undefined;
|
||||
const longestFieldUnits = suggestions.reduce((longest, suggestion) => (suggestion.kind === "column" ? Math.max(longest, textWidthUnits(suggestion.value)) : longest), 0);
|
||||
return Math.min(COMMENTED_SUGGESTION_MAX_WIDTH, Math.max(COMMENTED_SUGGESTION_MIN_WIDTH, Math.ceil(longestFieldUnits * 7.5 + 208)));
|
||||
}
|
||||
|
||||
export function getDataGridConditionSuggestionPosition(inputRect: DataGridConditionSuggestionRect, options: DataGridConditionSuggestionPositionOptions): DataGridConditionSuggestionPosition {
|
||||
const minWidth = options.minWidth ?? 180;
|
||||
const viewportMargin = options.viewportMargin ?? 8;
|
||||
const topOffset = options.topOffset ?? 2;
|
||||
const availableWidth = Math.max(minWidth, options.viewportWidth - viewportMargin * 2);
|
||||
const width = Math.min(Math.max(inputRect.width, minWidth), availableWidth);
|
||||
const availableWidth = Math.max(0, options.viewportWidth - viewportMargin * 2);
|
||||
const widthLimit = Math.min(availableWidth, options.maxWidth ?? availableWidth);
|
||||
const width = Math.min(Math.max(inputRect.width, minWidth, options.preferredWidth ?? 0), widthLimit);
|
||||
const maxLeft = Math.max(viewportMargin, options.viewportWidth - viewportMargin - width);
|
||||
const left = Math.min(Math.max(inputRect.left, viewportMargin), maxLeft);
|
||||
|
||||
|
||||
Reference in new issue
Block a user