From 40c778c2f63b28cb9bf5c625bab8da40dd50b3ab Mon Sep 17 00:00:00 2001 From: LuckyFBB <976060700@qq.com> Date: Fri, 14 Nov 2025 17:26:55 +0800 Subject: [PATCH] feat(contentlayout): rewrite contentLayout to use Content and Footer --- .../__tests__/contentLayout.test.tsx | 4 +- src/contentLayout/components.tsx | 49 ------- src/contentLayout/index.tsx | 128 ++++++++++++++---- 3 files changed, 103 insertions(+), 78 deletions(-) delete mode 100644 src/contentLayout/components.tsx diff --git a/src/contentLayout/__tests__/contentLayout.test.tsx b/src/contentLayout/__tests__/contentLayout.test.tsx index 486056082..a551bbb7a 100644 --- a/src/contentLayout/__tests__/contentLayout.test.tsx +++ b/src/contentLayout/__tests__/contentLayout.test.tsx @@ -70,7 +70,7 @@ describe('test contentLayout', () => { ); expect(container.querySelector('.ant-table-body')?.style.maxHeight).toBe( - 'calc(calc(calc(100vh - 96px) - 0px) - 88px)' + 'calc(calc(calc(100vh - 96px) - 0px - 0px) - 88px)' ); }); test('should support contentLayout small table height', () => { @@ -94,7 +94,7 @@ describe('test contentLayout', () => { ); expect(container.querySelector('.ant-table-body')?.style.maxHeight).toBe( - 'calc(calc(calc(100vh - 96px) - 0px) - 72px)' + 'calc(calc(calc(100vh - 96px) - 0px - 0px) - 88px)' ); }); }); diff --git a/src/contentLayout/components.tsx b/src/contentLayout/components.tsx deleted file mode 100644 index 17eab5ca7..000000000 --- a/src/contentLayout/components.tsx +++ /dev/null @@ -1,49 +0,0 @@ -import React from 'react'; -import { Table, TableProps } from 'antd'; -import classNames from 'classnames'; - -import { NAME } from '.'; - -interface ContentLayoutChildProps { - ref?: React.Ref; - children?: React.ReactNode; -} - -type ITableProps = { - height?: string; - style?: React.CSSProperties; - className?: string; -} & TableProps & - Omit; - -export const TableLayout = ({ height, size, className, ...otherProps }: ITableProps) => { - let lineHeight = size === 'small' ? 36 : 44; - - if (otherProps.footer) { - let footerHeight = 44; - if (className?.includes('dt-pagination-small')) footerHeight = 36; - lineHeight = lineHeight + footerHeight; - } - - const scroll: TableProps['scroll'] = { - y: `calc(${height} - ${lineHeight}px)`, - ...otherProps.scroll, - }; - - return ; -}; - -interface HeaderProps extends ContentLayoutChildProps { - style?: React.CSSProperties; - className?: string; -} - -export const Header = React.forwardRef( - ({ className, style, children }, ref) => { - return ( -
- {children} -
- ); - } -); diff --git a/src/contentLayout/index.tsx b/src/contentLayout/index.tsx index 6053ce5b9..f1a84452e 100644 --- a/src/contentLayout/index.tsx +++ b/src/contentLayout/index.tsx @@ -1,68 +1,142 @@ import React, { Children, cloneElement, useCallback, useMemo, useRef } from 'react'; +import { Table, TableProps } from 'antd'; import classNames from 'classnames'; -import { Header, TableLayout } from './components'; import './index.scss'; interface IProps { + header?: React.ReactElement; + content?: React.ReactElement; + footer?: React.ReactElement; height?: string; - children?: React.ReactElement | React.ReactElement[]; + children?: React.ReactElement[]; style?: React.CSSProperties; className?: string; + padding?: number | string; } -export const NAME = 'dtc-content-layout'; +const NAME = 'dtc-content-layout'; const ContentLayout = (props: IProps) => { - const { height = 'calc(100vh - 96px)', style, className, children } = props; + const { height = 'calc(100vh - 96px)', className, style, padding, children } = props; const headerRef: any = useRef(null); + const footerRef: any = useRef(null); const contentHeight = useMemo(() => { - return `calc(${height} - ${headerRef?.current?.clientHeight || 0}px)`; - }, [height, headerRef?.current]); + return `calc(${height} - ${headerRef?.current?.clientHeight || 0}px - ${ + footerRef?.current?.clientHeight || 0 + }px)`; + }, [height, headerRef?.current, footerRef?.current]); const render = useCallback(() => { - let header; - const content: React.ReactElement>[] = []; - + let herder = props?.header && ( + {props?.header} + ); + const content = [props?.content]; + let footer = props?.footer && ( + {props?.footer} + ); Children.forEach(children, (child) => { - if (child?.type === Header) { - header = cloneElement(child, { - key: 'header', - ref: headerRef, + if (child?.type === ContentLayout.Header) { + herder = cloneElement(child, { + thisRef: headerRef, }); - } - if (child?.type === TableLayout) { + } else if (child?.type === ContentLayout.Footer) { + footer = cloneElement(child, { + thisRef: footerRef, + }); + } else if (child) { content.push( - cloneElement(child, { - key: 'table', + cloneElement(child as React.ReactElement, { height: contentHeight, }) ); } }); - return [header, ...content]; + return [herder, ...content, footer]; }, [children, contentHeight]); return (
{render()}
); }; -type OriginalInterface = typeof ContentLayout; -interface LayoutInterface extends OriginalInterface { - Header: typeof Header; - Table: typeof TableLayout; +interface ContentLayoutChildProps { + thisRef?: React.Ref; + children?: React.ReactElement | React.ReactElement[] | React.ReactNode; + style?: React.CSSProperties; +} +interface HeaderProps extends ContentLayoutChildProps {} + +ContentLayout.Header = ({ thisRef, children, style }: HeaderProps) => { + return ( +
+ {children} +
+ ); +}; + +type ITableProps = { + height?: string; + children?: any; +} & TableProps & + ContentLayoutChildProps; + +ContentLayout.Table = ({ height, children, ...otherProps }: ITableProps) => { + let lineHeight = 44; + + if (otherProps.footer) { + lineHeight = lineHeight * 2; + } + const scroll: TableProps['scroll'] = { + y: `calc(${height} - ${lineHeight}px)`, + ...otherProps?.scroll, + }; + + return children ? ( + cloneElement(children, { + scroll, + }) + ) : ( +
+ ); +}; + +interface FooterProps extends ContentLayoutChildProps {} + +ContentLayout.Footer = ({ thisRef, children }: FooterProps) => { + return ( +
+ {children} +
+ ); +}; + +interface ContentProps extends ContentLayoutChildProps { + style?: React.CSSProperties; + className?: string; + height?: string | number; } -const LayoutWrapper = ContentLayout; -(LayoutWrapper as LayoutInterface).Header = Header; -(LayoutWrapper as LayoutInterface).Table = TableLayout; +ContentLayout.Content = ({ style = {}, className, height, children }: ContentProps) => { + return ( +
+ {children} +
+ ); +}; -export default LayoutWrapper as LayoutInterface; +export default ContentLayout;