Skip to content
Draft
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
2664082
clone original Table Comp
iamfaran Aug 5, 2025
9ff640d
register table lite comp
iamfaran Aug 5, 2025
491782f
remove expansion data layer
iamfaran Aug 5, 2025
b43d31e
remove expansion functionality from table
iamfaran Aug 6, 2025
13cdeff
fix imports for table lite comp
iamfaran Aug 6, 2025
966c4df
remove edit functionality
iamfaran Aug 6, 2025
4d75755
remove filter modal / table toolbar unnecessary code
iamfaran Aug 8, 2025
d03a02d
remove search filter and fix css issue
iamfaran Aug 11, 2025
5d6301e
remove edit / insert functions
iamfaran Aug 11, 2025
714e6cc
remove row context
iamfaran Aug 11, 2025
d4afdb4
split down tableComp.tsx
iamfaran Aug 12, 2025
8b492c2
refactor tableCompView
iamfaran Aug 13, 2025
a909c64
refactor / add virtualization
iamfaran Aug 15, 2025
18a93cf
remove edit functionality from columns
iamfaran Aug 18, 2025
6b34a8d
remove remaining edit functionality from the columns
iamfaran Aug 18, 2025
38c8653
remove change value props
iamfaran Aug 18, 2025
c82279e
refactor columnToAntd function
iamfaran Aug 18, 2025
29f29b3
remove more edit related code from columns
iamfaran Aug 18, 2025
c406bb5
add basic filters in headers
iamfaran Aug 19, 2025
f09e36f
add dynamic virtualization
iamfaran Aug 20, 2025
07abda7
remove unnecssory code for virtualization
iamfaran Aug 20, 2025
5a6ac32
fix x scrolling
iamfaran Aug 20, 2025
3af069a
scroll fixes
iamfaran Aug 20, 2025
1e1b61e
fix virtualization toolbar bottom
iamfaran Aug 20, 2025
e98b05c
hide horizontal scroll virtualization
iamfaran Aug 20, 2025
fed09b1
fix y scroll
iamfaran Aug 20, 2025
58f13b2
delete rc-virtual-list
iamfaran Aug 20, 2025
b8c7586
fix infinite re renders / unnecessary logic
iamfaran Aug 21, 2025
c84c902
add styling structure / refactor styles
iamfaran Aug 22, 2025
67f9952
add custom Hook to calculate table height / body
iamfaran Aug 25, 2025
26f6b10
Add Base Table component
iamfaran Aug 25, 2025
4fd3e12
Add auto / fixed tables
iamfaran Aug 25, 2025
37d494a
basic refactor complete
iamfaran Aug 25, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
add basic filters in headers
  • Loading branch information
iamfaran committed Aug 19, 2025
commit c406bb557fed6762c719507862da1d896b9649e1
Original file line number Diff line number Diff line change
Expand Up @@ -70,10 +70,31 @@ export function buildSortedDataNode(comp: TableImplComp) {
export function buildFilteredDataNode(comp: TableImplComp) {
const nodes = {
data: buildSortedDataNode(comp),
// Add filter state node
headerFilters: comp.children.headerFilters.node(),
};
const filteredDataNode = withFunction(fromRecord(nodes), ({ data }) => {
// No pre-filtering here; AntD header filters are handled internally by Table
return data.map((row) => tranToTableRecord(row, (row as any)[OB_ROW_ORI_INDEX]));
const filteredDataNode = withFunction(fromRecord(nodes), ({ data, headerFilters }) => {
let filteredData = data;

// Apply ANTD header filters if any exist
if (headerFilters && Object.keys(headerFilters).length > 0) {
filteredData = data.filter((record) => {
return Object.entries(headerFilters).every(([columnKey, filterValues]) => {
if (!filterValues || !Array.isArray(filterValues) || filterValues.length === 0) {
return true; // No filter applied for this column
}

const cellValue = record[columnKey];
// Check if cell value matches any of the selected filter values
return filterValues.some(filterValue => {
if (cellValue == null) return filterValue == null;
return String(cellValue) === String(filterValue);
});
});
});
}

return filteredData.map((row) => tranToTableRecord(row, (row as any)[OB_ROW_ORI_INDEX]));
});
return lastValueIfEqual(comp, "filteredDataNode", [filteredDataNode, nodes] as const, (a, b) =>
shallowEqual(a[1], b[1])
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,6 @@ export type ResizeableTableProps<RecordType> = Omit<TableProps<RecordType>, "com
rowAutoHeight?: boolean;
customLoading?: boolean;
onCellClick: (columnName: string, dataIndex: string) => void;
virtualEnabled?: boolean;
virtualBodyHeight?: number;
};

/**
Expand All @@ -34,8 +32,6 @@ function ResizeableTableComp<RecordType extends object>(props: ResizeableTablePr
rowAutoHeight,
customLoading,
onCellClick,
virtualEnabled,
virtualBodyHeight,
...restProps
} = props;
const [resizeData, setResizeData] = useState({ index: -1, width: -1 });
Expand Down Expand Up @@ -111,14 +107,6 @@ function ResizeableTableComp<RecordType extends object>(props: ResizeableTablePr
});
}, [columns, resizeData, createCellHandler, createHeaderCellHandler]);

// Ensure scroll.x is preserved and inject scroll.y when virtualization is enabled
const mergedScroll = useMemo(() => {
const xScroll = { x: COL_MIN_WIDTH * columns.length } as any;
const incoming = (restProps as any).scroll || {};
const y = virtualEnabled ? (virtualBodyHeight ?? incoming.y ?? 480) : incoming.y;
return { ...xScroll, ...incoming, ...(y ? { y } : {}) };
}, [columns.length, restProps, virtualEnabled, virtualBodyHeight]);

return (
<Table<RecordType>
components={{
Expand All @@ -130,11 +118,8 @@ function ResizeableTableComp<RecordType extends object>(props: ResizeableTablePr
},
}}
{...(restProps as any)}
// Enable AntD virtual rendering when requested (AntD will ignore if unsupported)
{...(virtualEnabled ? { virtual: true } : {})}
pagination={false}
columns={memoizedColumns}
scroll={mergedScroll}
/>
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ export const TableCompView = React.memo((props: {
[compChildren.dynamicColumnConfig]
);
const columnsAggrData = comp.columnAggrData;
const headerFilters = useMemo(() => compChildren.headerFilters.getView(), [compChildren.headerFilters]);
const antdColumns = useMemo(
() =>
columnsToAntdFormat(
Expand All @@ -53,6 +54,7 @@ export const TableCompView = React.memo((props: {
dynamicColumnConfig,
columnsAggrData,
onEvent,
headerFilters,
),
[
columnViews,
Expand All @@ -62,6 +64,7 @@ export const TableCompView = React.memo((props: {
dynamicColumn,
dynamicColumnConfig,
columnsAggrData,
headerFilters,
]
);

Expand Down Expand Up @@ -146,11 +149,6 @@ export const TableCompView = React.memo((props: {
((showDataLoadingIndicators) && (compChildren.data as any).isLoading()) ||
compChildren.loading.getView();

// Virtualization: keep pagination, virtualize within the visible body
const virtualEnabled = true; // enable by default for lite table
// Estimate a sensible body height. If table auto-height is enabled, fallback to 480.
const virtualBodyHeight = 480;

return (
<>
{toolbar.position === "above" && !hideToolbar && toolbarView}
Expand All @@ -174,8 +172,6 @@ export const TableCompView = React.memo((props: {
columnsStyle={columnsStyle}
rowAutoHeight={compChildren.rowAutoHeight.getView()}
customLoading={showTableLoading}
virtualEnabled={virtualEnabled}
virtualBodyHeight={virtualBodyHeight}
onCellClick={(columnName: string, dataIndex: string) => {
comp.children.selectedCell.dispatchChangeValueAction({
name: columnName,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,8 @@ const tableChildrenMap = {
selection: SelectionControl,
pagination: PaginationControl,
sort: valueComp<Array<SortValue>>([]),
// Header filters state for ANTD column header filters
headerFilters: stateComp<Record<string, any[]>>({}),
toolbar: TableToolbarComp,
showSummary: BoolControl,
summaryRows: dropdownControl(summarRowsOptions, "1"),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -373,17 +373,33 @@ function buildFilterProps(
filterable: boolean,
candidateTags: any[],
uniqueValues: any[],
headerFilters: Record<string, any[]> = {},
) {
if (!filterable) return {};

const candidates = (Array.isArray(candidateTags) && candidateTags.length > 0
? candidateTags
: Array.isArray(uniqueValues) && uniqueValues.length > 0
? uniqueValues
: [])
.slice(0, 100);

if (candidates.length === 0) return {};

return {
filters: candidates.map((v) => ({ text: String(v), value: v })),
onFilter: (value: any, record: any) => String(record[dataIndex] ?? "") === String(value ?? ""),
filters: candidates.map((v) => ({
text: String(v ?? 'null'),
value: v
})),
filteredValue: headerFilters[dataIndex] || null,
// Enable search within the filter dropdown (AntD)
filterSearch: true,
// Use tree mode for better UX on long lists (AntD)
filterMode: 'tree',
// Allow selecting multiple values per column by default
filterMultiple: true,
// Remove onFilter as we handle filtering in buildFilteredDataNode
// ANTD will call onChange with filters parameter instead
} as const;
}

Expand Down Expand Up @@ -489,6 +505,7 @@ export function columnsToAntdFormat(
dynamicColumnConfig: Array<string>,
columnsAggrData: ColumnsAggrData,
onTableEvent: (eventName: any) => void,
headerFilters: Record<string, any[]> = {},
): Array<CustomColumnType<RecordType>> {
const customColumns = columns.filter(col => col.isCustom).map(col => col.dataIndex);
const initialColumns = getInitialColumns(columnsAggrData, customColumns);
Expand All @@ -504,7 +521,7 @@ export function columnsToAntdFormat(

const { candidateTags, candidateStatus, uniqueValues } = extractAggrForColumn(column.dataIndex, columnsAggrData);
const title = renderTitle({ title: column.title, tooltip: column.titleTooltip });
const filterProps = buildFilterProps(column.dataIndex, column.filterable, candidateTags, uniqueValues);
const filterProps = buildFilterProps(column.dataIndex, column.filterable, candidateTags, uniqueValues, headerFilters);
const { style, linkStyle } = buildStyleProps(column);
const multiplePriority = (sortedColumns.length - mIndex) + 1;
const sorterProps = buildSorterProps(column, sortMap.get(column.dataIndex), multiplePriority);
Expand Down Expand Up @@ -572,6 +589,16 @@ export function onTableChange(
onEvent("sortChange");
}
if (extra.action === "filter") {
// Convert filters to a format suitable for our filter state
const headerFilters: Record<string, any[]> = {};
Object.entries(filters).forEach(([columnKey, filterValues]) => {
if (filterValues && Array.isArray(filterValues) && filterValues.length > 0) {
headerFilters[columnKey] = filterValues;
}
});

// Dispatch action to update header filters state
dispatch(changeChildAction("headerFilters", headerFilters, true));
onEvent("filterChange");
}
}
Expand Down
Loading