mirror of
https://github.com/t8y2/dbx.git
synced 2026-10-28 00:06:50 +00:00
String() on objects produces [object Object]. Use JSON.stringify() consistently wherever cell values are converted to strings.
97 lines
3.1 KiB
TypeScript
97 lines
3.1 KiB
TypeScript
export type GridCellValue = string | number | boolean | null;
|
|
|
|
export interface CellPosition {
|
|
rowIndex: number;
|
|
colIndex: number;
|
|
}
|
|
|
|
export interface CellSelectionRange {
|
|
startRow: number;
|
|
endRow: number;
|
|
startCol: number;
|
|
endCol: number;
|
|
}
|
|
|
|
export interface SelectionData {
|
|
columns: string[];
|
|
rows: GridCellValue[][];
|
|
}
|
|
|
|
export function normalizeSelectionRange(anchor: CellPosition, focus: CellPosition): CellSelectionRange {
|
|
return {
|
|
startRow: Math.min(anchor.rowIndex, focus.rowIndex),
|
|
endRow: Math.max(anchor.rowIndex, focus.rowIndex),
|
|
startCol: Math.min(anchor.colIndex, focus.colIndex),
|
|
endCol: Math.max(anchor.colIndex, focus.colIndex),
|
|
};
|
|
}
|
|
|
|
export function isCellInSelection(rowIndex: number, colIndex: number, range: CellSelectionRange | null): boolean {
|
|
if (!range) return false;
|
|
return (
|
|
rowIndex >= range.startRow && rowIndex <= range.endRow && colIndex >= range.startCol && colIndex <= range.endCol
|
|
);
|
|
}
|
|
|
|
export function extractSelection(
|
|
columns: readonly string[],
|
|
rows: readonly GridCellValue[][],
|
|
range: CellSelectionRange | null,
|
|
): SelectionData {
|
|
if (!range) return { columns: [], rows: [] };
|
|
|
|
const selectedColumns = columns.slice(range.startCol, range.endCol + 1);
|
|
const selectedRows = rows
|
|
.slice(range.startRow, range.endRow + 1)
|
|
.map((row) => row.slice(range.startCol, range.endCol + 1));
|
|
|
|
return { columns: selectedColumns, rows: selectedRows };
|
|
}
|
|
|
|
function displayValue(value: GridCellValue): string {
|
|
if (value === null) return "NULL";
|
|
if (typeof value === "boolean") return value ? "true" : "false";
|
|
if (typeof value === "object") return JSON.stringify(value);
|
|
return String(value);
|
|
}
|
|
|
|
function csvValue(value: GridCellValue | string): string {
|
|
const text = typeof value === "string" ? value : displayValue(value);
|
|
return `"${text.replace(/"/g, '""')}"`;
|
|
}
|
|
|
|
function sqlValue(value: GridCellValue): string {
|
|
if (value === null) return "NULL";
|
|
if (typeof value === "boolean") return value ? "TRUE" : "FALSE";
|
|
if (typeof value === "number" && Number.isFinite(value)) return String(value);
|
|
return `'${String(value).replace(/'/g, "''")}'`;
|
|
}
|
|
|
|
export function formatSelectionAsTsv(selection: SelectionData): string {
|
|
const header = selection.columns.join("\t");
|
|
const body = selection.rows.map((row) => row.map(displayValue).join("\t")).join("\n");
|
|
return [header, body].filter(Boolean).join("\n");
|
|
}
|
|
|
|
export function formatSelectionAsCsv(selection: SelectionData): string {
|
|
const header = selection.columns.map(csvValue).join(",");
|
|
const body = selection.rows.map((row) => row.map(csvValue).join(",")).join("\n");
|
|
return [header, body].filter(Boolean).join("\n");
|
|
}
|
|
|
|
export function formatSelectionAsJson(selection: SelectionData): string {
|
|
const objects = selection.rows.map((row) => {
|
|
const item: Record<string, GridCellValue> = {};
|
|
selection.columns.forEach((column, index) => {
|
|
item[column] = row[index] ?? null;
|
|
});
|
|
return item;
|
|
});
|
|
return JSON.stringify(objects, null, 2);
|
|
}
|
|
|
|
export function formatSelectionAsSqlInList(selection: SelectionData): string {
|
|
const values = selection.rows.flat().map(sqlValue);
|
|
return `(${values.join(", ")})`;
|
|
}
|