44 lines
1.8 KiB
TypeScript
44 lines
1.8 KiB
TypeScript
/**
|
|
* Pure selection/filtering helpers for the shared TableMultiSelect UI.
|
|
*
|
|
* These are framework-agnostic (no Vue state) so the behavior of the shared
|
|
* multi-table selector can be unit-tested independently of any component
|
|
* mount infrastructure, and so the same logic backs both Data Compare and
|
|
* Schema Diff table selection.
|
|
*/
|
|
|
|
/** Case-insensitive substring filter over table names. An empty/whitespace query returns all tables. */
|
|
export function filterTableNames(tables: string[], query: string): string[] {
|
|
const trimmed = query.trim().toLowerCase();
|
|
if (!trimmed) return tables;
|
|
return tables.filter((table) => table.toLowerCase().includes(trimmed));
|
|
}
|
|
|
|
/** Toggle a single table name within a selection list (preserves order, no duplicates). */
|
|
export function toggleTableName(selected: string[], table: string): string[] {
|
|
if (selected.includes(table)) {
|
|
return selected.filter((name) => name !== table);
|
|
}
|
|
return [...selected, table];
|
|
}
|
|
|
|
/** True when every entry of `filtered` is already present in `selected`. */
|
|
export function isEveryFilteredSelected(selected: string[], filtered: string[]): boolean {
|
|
return filtered.length > 0 && filtered.every((table) => selected.includes(table));
|
|
}
|
|
|
|
/**
|
|
* Select every table in `filtered` if not all are selected; otherwise deselect them all.
|
|
* Only tables within `filtered` are touched — the rest of `selected` is preserved, so
|
|
* selecting-all after a search only affects the current filtered subset.
|
|
*/
|
|
export function toggleSelectFiltered(selected: string[], filtered: string[]): string[] {
|
|
const next = new Set(selected);
|
|
if (isEveryFilteredSelected(selected, filtered)) {
|
|
filtered.forEach((table) => next.delete(table));
|
|
} else {
|
|
filtered.forEach((table) => next.add(table));
|
|
}
|
|
return [...next];
|
|
}
|