import { cellText } from "./contextActions"; export const RESULT_BATCH = 500; export function filterRows(rows: Record[], columns: string[], query: string) { const q = query.trim().toLocaleLowerCase(); return q ? rows.filter((row) => columns.some((col) => cellText(row[col]).toLocaleLowerCase().includes(q))) : rows; } /** 大整数文本不经 Number 转换,避免精度丢失后排序相等。 */ export function compareCells(a: unknown, b: unknown): number { if (a == null || b == null) return a == null ? (b == null ? 0 : -1) : 1; if (typeof a === "number" && typeof b === "number") return a - b; const sa = cellText(a), sb = cellText(b); if (/^-?\d+$/.test(sa) && /^-?\d+$/.test(sb)) { const ia = BigInt(sa), ib = BigInt(sb); return ia < ib ? -1 : ia > ib ? 1 : 0; } const numeric = /^[+-]?(?:\d+(?:\.\d*)?|\.\d+)(?:e[+-]?\d+)?$/i; if (numeric.test(sa) && numeric.test(sb) && Number.isFinite(Number(sa)) && Number.isFinite(Number(sb))) return Number(sa) - Number(sb); return sa.localeCompare(sb, undefined, { numeric: true, sensitivity: "base" }); } export function cellPreview(value: unknown, max = 120): string { const text = cellText(value); return text.length > max ? `${text.slice(0, max)}…` : text; } export function suggestedColumnWidth(name: string, rows: Record[]): number { // 有界采样;宽字符按两个单位估算,长 JSON 不撑满窗口。 const units = (s: string) => Array.from(s).reduce((n, ch) => n + (ch.charCodeAt(0) > 255 ? 2 : 1), 0); const count = Math.max(units(name), ...rows.slice(0, 100).map((r) => units(cellPreview(r[name], 60)))); return Math.min(480, Math.max(88, count * 7 + 28)); }