Skip to content

[In Progress] [Feat] Table Lite Component #1939

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 36 commits into
base: dev
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
36 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
d73a5ff
add styles
iamfaran Aug 26, 2025
3edaee4
fix header styles
iamfaran Aug 26, 2025
4590bfe
add remaining styles
iamfaran Aug 26, 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 custom Hook to calculate table height / body
  • Loading branch information
iamfaran committed Aug 25, 2025
commit 67f995289999bfc9f4c434fcfda4f30403d2c64e
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
// hooks/useTableConfiguration.ts
import { useMemo, useState, useEffect, useRef } from 'react';

// ============= HOOK 1: TABLE MODE =============
export function useTableMode(autoHeight: boolean) {
return useMemo(() => ({
mode: autoHeight ? 'AUTO' : 'FIXED' as const,
isAutoMode: autoHeight,
isFixedMode: !autoHeight
}), [autoHeight]);
}

// ============= HOOK 2: CONTAINER HEIGHT MEASUREMENT =============
export function useContainerHeight(enabled: boolean) {
const [containerHeight, setContainerHeight] = useState<number>(0);
const containerRef = useRef<HTMLDivElement>(null);

useEffect(() => {
if (!enabled || !containerRef.current) return;

const measureHeight = () => {
const element = containerRef.current;
if (element) {
// clientHeight gives us the inner height available for content
setContainerHeight(element.clientHeight);
}
};

// Initial measurement
measureHeight();

// Watch for size changes
const resizeObserver = new ResizeObserver(measureHeight);
resizeObserver.observe(containerRef.current);

return () => resizeObserver.disconnect();
}, [enabled]);

return { containerHeight, containerRef };
}

// ============= HOOK 3: HEIGHT CALCULATIONS =============
interface HeightConfig {
showToolbar: boolean;
showHeader: boolean;
toolbarHeight?: number;
headerHeight?: number;
containerPadding?: number;
}

export function useTableHeights(
mode: 'AUTO' | 'FIXED',
containerHeight: number,
config: HeightConfig
) {
return useMemo(() => {
if (mode === 'AUTO') {
return {
containerStyle: {
height: '100%',
display: 'flex',
flexDirection: 'column' as const
},
tableHeight: undefined,
bodyHeight: undefined,
scrollY: undefined,
canVirtualize: false
};
}

// FIXED mode calculations
const {
showToolbar = false,
showHeader = true,
toolbarHeight = 48,
headerHeight = 40,
containerPadding = 0
} = config;

const toolbarSpace = showToolbar ? toolbarHeight : 0;
const headerSpace = showHeader ? headerHeight : 0;
const totalUsedSpace = toolbarSpace + headerSpace + containerPadding;

// Calculate available height for table body
const bodyHeight = Math.max(0, containerHeight - totalUsedSpace);

return {
containerStyle: {
height: '100%',
display: 'flex',
flexDirection: 'column' as const
},
tableHeight: containerHeight,
bodyHeight,
scrollY: bodyHeight > 0 ? bodyHeight : undefined,
canVirtualize: bodyHeight > 100 // Reasonable minimum for virtualization
};
}, [mode, containerHeight, config]);
}

// ============= HOOK 4: VIRTUALIZATION CONFIG =============
export function useVirtualization(
canVirtualize: boolean,
dataLength: number,
threshold: number = 50
) {
return useMemo(() => {
const shouldVirtualize = canVirtualize && dataLength >= threshold;

return {
enabled: shouldVirtualize,
threshold,
itemHeight: 40, // Could be made configurable later
reason: !canVirtualize
? 'height_insufficient'
: dataLength < threshold
? 'data_too_small'
: 'enabled'
};
}, [canVirtualize, dataLength, threshold]);
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { TableSummary } from "./tableSummaryComp";
import { ThemeContext } from "@lowcoder-ee/comps/utils/themeContext";
import ResizeableTable from "./parts/ResizeableTable";
import { TableWrapper } from "./styles/TableWrapper";
import { useContainerHeight, useTableMode, useTableHeights, useVirtualization } from "./hooks/useTableConfiguration";

export const TableCompView = React.memo((props: {
comp: InstanceType<typeof TableImplComp>;
Expand All @@ -21,10 +22,6 @@ export const TableCompView = React.memo((props: {
const showDataLoadingIndicators = currentTheme?.showDataLoadingIndicators;

const compName = useContext(CompNameContext);
const [loading, setLoading] = useState(false);
const tableViewportRef = useRef<HTMLDivElement>(null);

const [containerHeight, setContainerHeight] = useState<number>(0);

const { comp, onDownload, onRefresh } = props;
const compChildren = comp.children;
Expand All @@ -48,34 +45,35 @@ export const TableCompView = React.memo((props: {
const size = useMemo(() => compChildren.size.getView(), [compChildren.size]);
const onEvent = useMemo(() => compChildren.onEvent.getView(), [compChildren.onEvent]);
const dynamicColumn = compChildren.dynamicColumn.getView();
const [loading, setLoading] = useState(false);
const autoHeight = compChildren.autoHeight.getView();
const rowAutoHeight = compChildren.rowAutoHeight.getView();
const showHeader = !compChildren.hideHeader.getView();

// NEW: Use hooks for clean logic
const { mode, isFixedMode } = useTableMode(autoHeight);
const { containerHeight, containerRef } = useContainerHeight(isFixedMode);
const heights = useTableHeights(mode as 'AUTO' | 'FIXED', containerHeight, {
showToolbar: !hideToolbar,
showHeader: showHeader,
toolbarHeight: 48,
headerHeight: 40
});
const virtualization = useVirtualization(
heights.canVirtualize,
data?.length ?? 0,
50
);


const dynamicColumnConfig = useMemo(
() => compChildren.dynamicColumnConfig.getView(),
[compChildren.dynamicColumnConfig]
);
const columnsAggrData = comp.columnAggrData;
const headerFilters = useMemo(() => compChildren.headerFilters.getView(), [compChildren.headerFilters]);

// Virtualization logic - simplified: enable for fixed height with 50+ rows
const isFixedHeight = !compChildren.autoHeight.getView(); // autoHeight: "fixed" when false
const rowAutoHeight = compChildren.rowAutoHeight.getView();

// Measure container height for virtualization
useEffect(() => {
if (!isFixedHeight || !tableViewportRef.current) return;

const measureHeight = () => {
const el = tableViewportRef.current;
if (el) {
// clientHeight = inner height available to the scrollable body
setContainerHeight(el.clientHeight);
}
};
measureHeight();
const resizeObserver = new ResizeObserver(measureHeight);
resizeObserver.observe(tableViewportRef.current);

return () => resizeObserver.disconnect();
}, [isFixedHeight]);

const antdColumns = useMemo(
() =>
Expand Down Expand Up @@ -186,7 +184,7 @@ export const TableCompView = React.memo((props: {
return (
<div style={{ height: '100%', display: 'flex', flexDirection: 'column' }}>
{toolbar.position === "above" && !hideToolbar && toolbarView}
<div ref={tableViewportRef} style={{ flex: 1, minHeight: 0 }}>
<div ref={containerRef} style={{ flex: 1, minHeight: 0 }}>
<TableWrapper
$style={style}
$headerStyle={headerStyle}
Expand All @@ -201,7 +199,7 @@ export const TableCompView = React.memo((props: {
onChange={(pagination: any, filters: any, sorter: any, extra: any) => {
onTableChange(pagination, filters, sorter, extra, comp.dispatch, onEvent);
}}
showHeader={!compChildren.hideHeader.getView()}
showHeader={showHeader}
columns={antdColumns}
dataSource={pageDataInfo.data}
size={compChildren.size.getView()}
Expand All @@ -221,7 +219,7 @@ export const TableCompView = React.memo((props: {
});
}}
containerHeight={containerHeight}
isFixedHeight={isFixedHeight}
isFixedHeight={isFixedMode}
/>
</TableWrapper>
</div>
Expand Down