79 lines
2.3 KiB
TypeScript
79 lines
2.3 KiB
TypeScript
|
import type { Column, TDisplayFunction } from './types.js';
|
||
|
|
||
|
export function computeColumnsFromDisplayFunction<T>(
|
||
|
displayFunction: TDisplayFunction<T>,
|
||
|
data: T[]
|
||
|
): Column<T>[] {
|
||
|
if (!data || data.length === 0) return [];
|
||
|
const firstTransformedItem = displayFunction(data[0]);
|
||
|
const keys: string[] = Object.keys(firstTransformedItem);
|
||
|
return keys.map((key) => ({
|
||
|
key,
|
||
|
header: key,
|
||
|
value: (row: T) => displayFunction(row)[key],
|
||
|
}));
|
||
|
}
|
||
|
|
||
|
export function computeEffectiveColumns<T>(
|
||
|
columns: Column<T>[] | undefined,
|
||
|
augmentFromDisplayFunction: boolean,
|
||
|
displayFunction: TDisplayFunction<T>,
|
||
|
data: T[]
|
||
|
): Column<T>[] {
|
||
|
const base = (columns || []).slice();
|
||
|
if (!augmentFromDisplayFunction) return base;
|
||
|
const fromDisplay = computeColumnsFromDisplayFunction(displayFunction, data);
|
||
|
const existingKeys = new Set(base.map((c) => String(c.key)));
|
||
|
for (const col of fromDisplay) {
|
||
|
if (!existingKeys.has(String(col.key))) {
|
||
|
base.push(col);
|
||
|
}
|
||
|
}
|
||
|
return base;
|
||
|
}
|
||
|
|
||
|
export function getCellValue<T>(row: T, col: Column<T>, displayFunction?: TDisplayFunction<T>): any {
|
||
|
return col.value ? col.value(row) : (row as any)[col.key as any];
|
||
|
}
|
||
|
|
||
|
export function getViewData<T>(
|
||
|
data: T[],
|
||
|
effectiveColumns: Column<T>[],
|
||
|
sortKey?: string,
|
||
|
sortDir?: 'asc' | 'desc' | null,
|
||
|
filterText?: string
|
||
|
): T[] {
|
||
|
let arr = data.slice();
|
||
|
const ft = (filterText || '').trim().toLowerCase();
|
||
|
if (ft) {
|
||
|
arr = arr.filter((row) => {
|
||
|
for (const col of effectiveColumns) {
|
||
|
if (col.hidden) continue;
|
||
|
const val = getCellValue(row, col);
|
||
|
const s = String(val ?? '').toLowerCase();
|
||
|
if (s.includes(ft)) return true;
|
||
|
}
|
||
|
return false;
|
||
|
});
|
||
|
}
|
||
|
if (!sortKey || !sortDir) return arr;
|
||
|
const col = effectiveColumns.find((c) => String(c.key) === sortKey);
|
||
|
if (!col) return arr;
|
||
|
const dir = sortDir === 'asc' ? 1 : -1;
|
||
|
arr.sort((a, b) => {
|
||
|
const va = getCellValue(a, col);
|
||
|
const vb = getCellValue(b, col);
|
||
|
if (va == null && vb == null) return 0;
|
||
|
if (va == null) return -1 * dir;
|
||
|
if (vb == null) return 1 * dir;
|
||
|
if (typeof va === 'number' && typeof vb === 'number') return (va - vb) * dir;
|
||
|
const sa = String(va).toLowerCase();
|
||
|
const sb = String(vb).toLowerCase();
|
||
|
if (sa < sb) return -1 * dir;
|
||
|
if (sa > sb) return 1 * dir;
|
||
|
return 0;
|
||
|
});
|
||
|
return arr;
|
||
|
}
|
||
|
|