refactor(advancedSearch): reorder exports and improve type definitions
refactor(types): reorganize SearchCondition and AdvancedSearchState interfaces refactor(filterPresets): streamline useFilterPresets hook and localStorage handling refactor(filtering): clean up ColumnFilterButton and ColumnFilterPopover components refactor(loading): separate GriddyLoadingOverlay from GriddyLoadingSkeleton refactor(searchHistory): enhance useSearchHistory hook with persistence refactor(index): update exports for adapters and core components refactor(rendering): improve EditableCell and TableCell components for clarity refactor(rendering): enhance TableHeader and VirtualBody components for better readability
This commit is contained in:
@@ -1,22 +1,85 @@
|
||||
import type { ColumnDef } from '@tanstack/react-table'
|
||||
import type { ColumnDef } from '@tanstack/react-table';
|
||||
|
||||
import type { GriddyColumn, SelectionConfig } from './types'
|
||||
import type { GriddyColumn, SelectionConfig } from './types';
|
||||
|
||||
import { createOperatorFilter } from '../features/filtering'
|
||||
import { DEFAULTS, SELECTION_COLUMN_ID, SELECTION_COLUMN_SIZE } from './constants'
|
||||
import { createOperatorFilter } from '../features/filtering';
|
||||
import { DEFAULTS, SELECTION_COLUMN_ID, SELECTION_COLUMN_SIZE } from './constants';
|
||||
|
||||
/**
|
||||
* Retrieves the original GriddyColumn from a TanStack column's meta.
|
||||
*/
|
||||
export function getGriddyColumn<T>(column: { columnDef: ColumnDef<T> }): GriddyColumn<T> | undefined {
|
||||
return (column.columnDef.meta as { griddy?: GriddyColumn<T> })?.griddy
|
||||
export function getGriddyColumn<T>(column: {
|
||||
columnDef: ColumnDef<T>;
|
||||
}): GriddyColumn<T> | undefined {
|
||||
return (column.columnDef.meta as { griddy?: GriddyColumn<T> })?.griddy;
|
||||
}
|
||||
|
||||
/**
|
||||
* Maps Griddy's user-facing GriddyColumn<T> definitions to TanStack Table ColumnDef<T>[].
|
||||
* Supports header grouping and optionally prepends a selection checkbox column.
|
||||
*/
|
||||
export function mapColumns<T>(
|
||||
columns: GriddyColumn<T>[],
|
||||
selection?: SelectionConfig
|
||||
): ColumnDef<T>[] {
|
||||
// Group columns by headerGroup
|
||||
const grouped = new Map<string, GriddyColumn<T>[]>();
|
||||
const ungrouped: GriddyColumn<T>[] = [];
|
||||
|
||||
columns.forEach((col) => {
|
||||
if (col.headerGroup) {
|
||||
const existing = grouped.get(col.headerGroup) || [];
|
||||
existing.push(col);
|
||||
grouped.set(col.headerGroup, existing);
|
||||
} else {
|
||||
ungrouped.push(col);
|
||||
}
|
||||
});
|
||||
|
||||
// Build column definitions
|
||||
const mapped: ColumnDef<T>[] = [];
|
||||
|
||||
// Add ungrouped columns first
|
||||
ungrouped.forEach((col) => {
|
||||
mapped.push(mapSingleColumn(col));
|
||||
});
|
||||
|
||||
// Add grouped columns
|
||||
grouped.forEach((groupColumns, groupName) => {
|
||||
const groupDef: ColumnDef<T> = {
|
||||
columns: groupColumns.map((col) => mapSingleColumn(col)),
|
||||
header: groupName,
|
||||
id: `group-${groupName}`,
|
||||
};
|
||||
mapped.push(groupDef);
|
||||
});
|
||||
|
||||
// Prepend checkbox column if selection is enabled
|
||||
if (selection && selection.mode !== 'none' && selection.showCheckbox !== false) {
|
||||
const checkboxCol: ColumnDef<T> = {
|
||||
cell: 'select-row', // Rendered by TableCell with actual checkbox
|
||||
enableColumnFilter: false,
|
||||
enableHiding: false,
|
||||
enableResizing: false,
|
||||
enableSorting: false,
|
||||
header:
|
||||
selection.mode === 'multi'
|
||||
? 'select-all' // Rendered by TableHeader with actual checkbox
|
||||
: '',
|
||||
id: SELECTION_COLUMN_ID,
|
||||
size: SELECTION_COLUMN_SIZE,
|
||||
};
|
||||
mapped.unshift(checkboxCol);
|
||||
}
|
||||
|
||||
return mapped;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a single GriddyColumn to a TanStack ColumnDef
|
||||
*/
|
||||
function mapSingleColumn<T>(col: GriddyColumn<T>): ColumnDef<T> {
|
||||
const isStringAccessor = typeof col.accessor !== 'function'
|
||||
const isStringAccessor = typeof col.accessor !== 'function';
|
||||
|
||||
const def: ColumnDef<T> = {
|
||||
id: col.id,
|
||||
@@ -37,92 +100,33 @@ function mapSingleColumn<T>(col: GriddyColumn<T>): ColumnDef<T> {
|
||||
meta: { griddy: col },
|
||||
minSize: col.minWidth ?? DEFAULTS.minColumnWidth,
|
||||
size: col.width,
|
||||
}
|
||||
};
|
||||
|
||||
// For function accessors, TanStack can't auto-detect the sort type, so provide a default
|
||||
if (col.sortFn) {
|
||||
def.sortingFn = col.sortFn
|
||||
def.sortingFn = col.sortFn;
|
||||
} else if (!isStringAccessor && col.sortable !== false) {
|
||||
// Use alphanumeric sorting for function accessors
|
||||
def.sortingFn = 'alphanumeric'
|
||||
def.sortingFn = 'alphanumeric';
|
||||
}
|
||||
|
||||
if (col.filterFn) {
|
||||
def.filterFn = col.filterFn
|
||||
def.filterFn = col.filterFn;
|
||||
} else if (col.filterable) {
|
||||
def.filterFn = createOperatorFilter()
|
||||
def.filterFn = createOperatorFilter();
|
||||
}
|
||||
|
||||
if (col.renderer) {
|
||||
const renderer = col.renderer
|
||||
def.cell = (info) => renderer({
|
||||
column: col,
|
||||
columnIndex: info.cell.column.getIndex(),
|
||||
row: info.row.original,
|
||||
rowIndex: info.row.index,
|
||||
value: info.getValue(),
|
||||
})
|
||||
const renderer = col.renderer;
|
||||
def.cell = (info) =>
|
||||
renderer({
|
||||
column: col,
|
||||
columnIndex: info.cell.column.getIndex(),
|
||||
row: info.row.original,
|
||||
rowIndex: info.row.index,
|
||||
value: info.getValue(),
|
||||
});
|
||||
}
|
||||
|
||||
return def
|
||||
}
|
||||
|
||||
/**
|
||||
* Maps Griddy's user-facing GriddyColumn<T> definitions to TanStack Table ColumnDef<T>[].
|
||||
* Supports header grouping and optionally prepends a selection checkbox column.
|
||||
*/
|
||||
export function mapColumns<T>(
|
||||
columns: GriddyColumn<T>[],
|
||||
selection?: SelectionConfig,
|
||||
): ColumnDef<T>[] {
|
||||
// Group columns by headerGroup
|
||||
const grouped = new Map<string, GriddyColumn<T>[]>()
|
||||
const ungrouped: GriddyColumn<T>[] = []
|
||||
|
||||
columns.forEach(col => {
|
||||
if (col.headerGroup) {
|
||||
const existing = grouped.get(col.headerGroup) || []
|
||||
existing.push(col)
|
||||
grouped.set(col.headerGroup, existing)
|
||||
} else {
|
||||
ungrouped.push(col)
|
||||
}
|
||||
})
|
||||
|
||||
// Build column definitions
|
||||
const mapped: ColumnDef<T>[] = []
|
||||
|
||||
// Add ungrouped columns first
|
||||
ungrouped.forEach(col => {
|
||||
mapped.push(mapSingleColumn(col))
|
||||
})
|
||||
|
||||
// Add grouped columns
|
||||
grouped.forEach((groupColumns, groupName) => {
|
||||
const groupDef: ColumnDef<T> = {
|
||||
header: groupName,
|
||||
id: `group-${groupName}`,
|
||||
columns: groupColumns.map(col => mapSingleColumn(col)),
|
||||
}
|
||||
mapped.push(groupDef)
|
||||
})
|
||||
|
||||
// Prepend checkbox column if selection is enabled
|
||||
if (selection && selection.mode !== 'none' && selection.showCheckbox !== false) {
|
||||
const checkboxCol: ColumnDef<T> = {
|
||||
cell: 'select-row', // Rendered by TableCell with actual checkbox
|
||||
enableColumnFilter: false,
|
||||
enableHiding: false,
|
||||
enableResizing: false,
|
||||
enableSorting: false,
|
||||
header: selection.mode === 'multi'
|
||||
? 'select-all' // Rendered by TableHeader with actual checkbox
|
||||
: '',
|
||||
id: SELECTION_COLUMN_ID,
|
||||
size: SELECTION_COLUMN_SIZE,
|
||||
}
|
||||
mapped.unshift(checkboxCol)
|
||||
}
|
||||
|
||||
return mapped
|
||||
return def;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user