diff --git a/docs/examples/virtual.tsx b/docs/examples/virtual.tsx index 0780a55a7..5aadf61ad 100644 --- a/docs/examples/virtual.tsx +++ b/docs/examples/virtual.tsx @@ -12,6 +12,8 @@ interface RecordType { } const columns: ColumnsType = [ + // { title: 'title1', dataIndex: 'a', key: 'a', width: 100,}, + // { title: 'title1', dataIndex: 'a', key: 'a', width: 100, }, { title: 'title1', dataIndex: 'a', key: 'a', width: 100, fixed: 'left' }, { title: 'title2', dataIndex: 'b', key: 'b', width: 100, fixed: 'left', ellipsis: true }, { @@ -198,7 +200,7 @@ const Demo = () => { b || c} - scroll={{ x: 1200, y: scrollY ? 200 : null }} + scroll={{ x: 1300, y: scrollY ? 200 : null }} data={data} // data={[]} rowKey="indexKey" @@ -209,6 +211,15 @@ const Demo = () => { }} // onRow={() => ({ className: 'rowed' })} rowClassName="nice-try" + getContainerWidth={(ele, width) => { + // Minus border + const borderWidth = getComputedStyle( + ele.querySelector('.rc-virtual-list'), + ).borderInlineStartWidth; + const mergedWidth = width - parseInt(borderWidth, 10); + + return mergedWidth; + }} /> ); diff --git a/src/Table.tsx b/src/Table.tsx index ab0b3a451..3562516ab 100644 --- a/src/Table.tsx +++ b/src/Table.tsx @@ -118,6 +118,8 @@ export interface TableProps direction?: Direction; + sticky?: boolean | TableSticky; + // =================================== Internal =================================== /** * @private Internal usage, may remove by refactor. Should always use `columns` instead. @@ -143,6 +145,14 @@ export interface TableProps // Force column to be average width if not set tailor?: boolean; + /** + * @private Internal usage, may remove by refactor. + * + * !!! DO NOT USE IN PRODUCTION ENVIRONMENT !!! + */ + // Pass the way to get real width. e.g. exclude the border width + getContainerWidth?: (ele: HTMLElement, width: number) => number; + /** * @private Internal usage, may remove by refactor. * @@ -151,8 +161,6 @@ export interface TableProps internalRefs?: { body: React.MutableRefObject; }; - - sticky?: boolean | TableSticky; } function defaultEmpty() { @@ -197,6 +205,7 @@ function Table(tableProps: TableProps(tableProps: TableProps(tableProps: TableProps { - if (width !== componentWidth) { + let mergedWidth = fullTableRef.current ? fullTableRef.current.offsetWidth : width; + if (useInternalHooks && getContainerWidth) { + mergedWidth = getContainerWidth(fullTableRef.current, mergedWidth) || mergedWidth; + } + + if (mergedWidth !== componentWidth) { triggerOnScroll(); - setComponentWidth(fullTableRef.current ? fullTableRef.current.offsetWidth : width); + setComponentWidth(mergedWidth); } }; diff --git a/src/VirtualTable/index.tsx b/src/VirtualTable/index.tsx index fcb2102a8..c92aaf74b 100644 --- a/src/VirtualTable/index.tsx +++ b/src/VirtualTable/index.tsx @@ -17,14 +17,12 @@ const renderBody: CustomizeScrollBody = (rawData, props) => { export interface VirtualTableProps extends Omit, 'scroll'> { scroll: { - x: number; + x?: number; y: number; }; listItemHeight?: number; } -const PRESET_COLUMN_WIDTH = 100; - function VirtualTable(props: VirtualTableProps) { const { columns, scroll, prefixCls = DEFAULT_PREFIX, className, listItemHeight } = props; @@ -32,11 +30,7 @@ function VirtualTable(props: VirtualTableProps) { // Fill scrollX if (typeof scrollX !== 'number') { - scrollX = ((columns || []).length + 1) * PRESET_COLUMN_WIDTH; - - if (process.env.NODE_ENV !== 'production') { - warning(false, '`scroll.x` in virtual table must be number.'); - } + scrollX = 1; } // Fill scrollY diff --git a/src/hooks/useColumns/index.tsx b/src/hooks/useColumns/index.tsx index baa026f32..52cc445fd 100644 --- a/src/hooks/useColumns/index.tsx +++ b/src/hooks/useColumns/index.tsx @@ -132,6 +132,7 @@ function useColumns( columnWidth, fixed, scrollWidth, + clientWidth, }: { prefixCls?: string; columns?: ColumnsType; @@ -147,6 +148,7 @@ function useColumns( direction?: Direction; expandRowByClick?: boolean; columnWidth?: number | string; + clientWidth: number; fixed?: FixedType; scrollWidth?: number; }, @@ -278,7 +280,11 @@ function useColumns( } // ========================= FillWidth ======================== - const [filledColumns, realScrollWidth] = useWidthColumns(flattenColumns, scrollWidth); + const [filledColumns, realScrollWidth] = useWidthColumns( + flattenColumns, + scrollWidth, + clientWidth, + ); return [mergedColumns, filledColumns, realScrollWidth]; } diff --git a/src/hooks/useColumns/useWidthColumns.tsx b/src/hooks/useColumns/useWidthColumns.tsx index 34bcb6afe..cacb04751 100644 --- a/src/hooks/useColumns/useWidthColumns.tsx +++ b/src/hooks/useColumns/useWidthColumns.tsx @@ -15,7 +15,11 @@ function parseColWidth(totalWidth: number, width: string | number = '') { /** * Fill all column with width */ -export default function useWidthColumns(flattenColumns: ColumnsType, scrollWidth: number) { +export default function useWidthColumns( + flattenColumns: ColumnsType, + scrollWidth: number, + clientWidth: number, +) { return React.useMemo<[columns: ColumnsType, realScrollWidth: number]>(() => { // Fill width if needed if (scrollWidth && scrollWidth > 0) { @@ -34,7 +38,7 @@ export default function useWidthColumns(flattenColumns: ColumnsType, scroll }); // Fill width - let restWidth = scrollWidth - totalWidth; + let restWidth = Math.max(scrollWidth - totalWidth, missWidthCount); let restCount = missWidthCount; const avgWidth = restWidth / missWidthCount; @@ -63,9 +67,25 @@ export default function useWidthColumns(flattenColumns: ColumnsType, scroll return clone; }); - return [filledColumns, realTotal]; + // If realTotal is less than clientWidth, + // We need extend column width + if (realTotal < clientWidth) { + const scale = clientWidth / realTotal; + + restWidth = clientWidth; + + filledColumns.forEach((col: any, index) => { + const colWidth = Math.floor(col.width * scale); + + col.width = index === filledColumns.length - 1 ? restWidth : colWidth; + + restWidth -= colWidth; + }); + } + + return [filledColumns, Math.max(realTotal, clientWidth)]; } return [flattenColumns, scrollWidth]; - }, [flattenColumns, scrollWidth]); + }, [flattenColumns, scrollWidth, clientWidth]); } diff --git a/tests/Virtual.spec.tsx b/tests/Virtual.spec.tsx index 084a89a2a..fc4400800 100644 --- a/tests/Virtual.spec.tsx +++ b/tests/Virtual.spec.tsx @@ -106,7 +106,6 @@ describe('Table.Virtual', () => { scroll: {} as any, }); - expect(errSpy).toHaveBeenCalledWith('Warning: `scroll.x` in virtual table must be number.'); expect(errSpy).toHaveBeenCalledWith('Warning: `scroll.y` in virtual table must be number.'); }); @@ -226,4 +225,23 @@ describe('Table.Virtual', () => { expect(container.querySelector('.bamboo').textContent).toEqual('0'); }); + + it('columns less than width', async () => { + const { container } = getTable({ + columns: [{}, {}], + scroll: { + y: 10, + }, + getContainerWidth: () => 200, + data: [{}], + }); + + resize(container.querySelector('.rc-table')); + + await waitFakeTimer(); + + expect(container.querySelectorAll('col')).toHaveLength(2); + expect(container.querySelectorAll('col')[0]).toHaveStyle({ width: '100px' }); + expect(container.querySelectorAll('col')[1]).toHaveStyle({ width: '100px' }); + }); });