Skip to content

Commit d6be9cb

Browse files
committed
feat(contentlayout): rewrite contentLayout to use Content and Footer
1 parent 950c864 commit d6be9cb

File tree

3 files changed

+76
-15
lines changed

3 files changed

+76
-15
lines changed

src/contentLayout/__tests__/contentLayout.test.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ describe('test contentLayout', () => {
7070
</ContentLayout>
7171
);
7272
expect(container.querySelector<HTMLDivElement>('.ant-table-body')?.style.maxHeight).toBe(
73-
'calc(calc(calc(100vh - 96px) - 0px) - 88px)'
73+
'calc(calc(calc(100vh - 96px) - 0px - 0px) - 88px)'
7474
);
7575
});
7676
test('should support contentLayout small table height', () => {
@@ -94,7 +94,7 @@ describe('test contentLayout', () => {
9494
</ContentLayout>
9595
);
9696
expect(container.querySelector<HTMLDivElement>('.ant-table-body')?.style.maxHeight).toBe(
97-
'calc(calc(calc(100vh - 96px) - 0px) - 72px)'
97+
'calc(calc(calc(100vh - 96px) - 0px - 0px) - 72px)'
9898
);
9999
});
100100
});

src/contentLayout/components.tsx

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,3 +47,30 @@ export const Header = React.forwardRef<HTMLDivElement, HeaderProps>(
4747
);
4848
}
4949
);
50+
51+
interface FooterProps extends ContentLayoutChildProps {}
52+
53+
export const Footer = ({ ref, children }: FooterProps) => {
54+
return (
55+
<div className={`${NAME}__footer`} ref={ref}>
56+
{children}
57+
</div>
58+
);
59+
};
60+
61+
interface ContentProps extends ContentLayoutChildProps {
62+
style?: React.CSSProperties;
63+
className?: string;
64+
height?: string | number;
65+
}
66+
67+
export const Content = ({ style = {}, className, height, children }: ContentProps) => {
68+
return (
69+
<div
70+
className={classNames(`${NAME}__content`, className)}
71+
style={height ? { ...style, height } : { ...style }}
72+
>
73+
{children}
74+
</div>
75+
);
76+
};

src/contentLayout/index.tsx

Lines changed: 47 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,15 @@
11
import React, { Children, cloneElement, useCallback, useMemo, useRef } from 'react';
22
import classNames from 'classnames';
33

4-
import { Header, TableLayout } from './components';
4+
import { Content, Footer, Header, TableLayout } from './components';
55
import './index.scss';
66

77
interface IProps {
8+
header?: React.ReactElement;
9+
content?: React.ReactElement;
10+
footer?: React.ReactElement;
811
height?: string;
9-
children?: React.ReactElement | React.ReactElement[];
12+
children?: React.ReactElement[];
1013
style?: React.CSSProperties;
1114
className?: string;
1215
}
@@ -16,34 +19,61 @@ export const NAME = 'dtc-content-layout';
1619
const ContentLayout = (props: IProps) => {
1720
const { height = 'calc(100vh - 96px)', style, className, children } = props;
1821
const headerRef: any = useRef(null);
22+
const footerRef: any = useRef(null);
1923

2024
const contentHeight = useMemo(() => {
21-
return `calc(${height} - ${headerRef?.current?.clientHeight || 0}px)`;
22-
}, [height, headerRef?.current]);
25+
return `calc(${height} - ${headerRef?.current?.clientHeight || 0}px - ${
26+
footerRef?.current?.clientHeight || 0
27+
}px)`;
28+
}, [height, headerRef?.current, footerRef?.current]);
2329

2430
const render = useCallback(() => {
25-
let header;
26-
const content: React.ReactElement<any, string | React.JSXElementConstructor<any>>[] = [];
31+
let header = null;
32+
let footer = null;
33+
const content: React.ReactElement[] = [];
2734

28-
Children.forEach(children, (child) => {
35+
if (props?.content) {
36+
content.push(
37+
cloneElement(props.content, {
38+
key: 'content-prop',
39+
})
40+
);
41+
}
42+
43+
Children.forEach(children, (child, index) => {
2944
if (child?.type === Header) {
3045
header = cloneElement(child, {
3146
key: 'header',
3247
ref: headerRef,
3348
});
34-
}
35-
if (child?.type === TableLayout) {
49+
} else if (child?.type === TableLayout) {
50+
footer = cloneElement(child, {
51+
key: 'footer-table',
52+
ref: footerRef,
53+
height: contentHeight,
54+
});
55+
} else if (child?.type === Footer) {
56+
footer = cloneElement(child, {
57+
key: 'footer',
58+
ref: footerRef,
59+
});
60+
} else {
61+
const childKey = (child as React.ReactElement)?.key || `content-${index}`;
3662
content.push(
37-
cloneElement(child, {
38-
key: 'table',
63+
cloneElement(child as React.ReactElement, {
64+
key: childKey,
3965
height: contentHeight,
4066
})
4167
);
4268
}
4369
});
4470

45-
return [header, ...content];
46-
}, [children, contentHeight]);
71+
const result: (React.ReactElement | null)[] = [];
72+
if (header) result.push(header);
73+
result.push(...content);
74+
if (footer) result.push(footer);
75+
return result;
76+
}, [children, contentHeight, props?.content]);
4777

4878
return (
4979
<div
@@ -59,10 +89,14 @@ type OriginalInterface = typeof ContentLayout;
5989
interface LayoutInterface extends OriginalInterface {
6090
Header: typeof Header;
6191
Table: typeof TableLayout;
92+
Footer: typeof Footer;
93+
Content: typeof Content;
6294
}
6395

6496
const LayoutWrapper = ContentLayout;
6597
(LayoutWrapper as LayoutInterface).Header = Header;
6698
(LayoutWrapper as LayoutInterface).Table = TableLayout;
99+
(LayoutWrapper as LayoutInterface).Content = Content;
100+
(LayoutWrapper as LayoutInterface).Footer = Footer;
67101

68102
export default LayoutWrapper as LayoutInterface;

0 commit comments

Comments
 (0)