mirror of
https://github.com/ant-design/ant-design.git
synced 2024-11-24 11:10:01 +08:00
feat(grid): row's 'align' and 'justify' support reponsive value (#37860)
* feat: row's 'align' and 'justify' support reponsive value * refactor: refactor code * refactor: refactor code * refactor: refactor code * refactor: refactor code * refactor: refactor code * refactor: refactor code * refactor: refactor code * docs: 更新文档 * docs: 更新文档 * docs: 更新文档 * docs: 更新文档 * feat: remove other * Update components/grid/index.zh-CN.md Co-authored-by: afc163 <afc163@gmail.com> * docs: update support version Co-authored-by: tangwenhui <tangwenhui@rd.netease.com> Co-authored-by: afc163 <afc163@gmail.com>
This commit is contained in:
parent
8a454a136e
commit
2559b2fb1b
@ -143,4 +143,44 @@ describe('Grid', () => {
|
||||
xxl: false,
|
||||
});
|
||||
});
|
||||
|
||||
it('should align by responsive align prop', () => {
|
||||
const matchMediaSpy = jest.spyOn(window, 'matchMedia');
|
||||
matchMediaSpy.mockImplementation(
|
||||
query =>
|
||||
({
|
||||
addListener: (cb: (e: { matches: boolean }) => void) => {
|
||||
cb({ matches: query === '(max-width: 575px)' });
|
||||
},
|
||||
removeListener: jest.fn(),
|
||||
matches: query === '(max-width: 575px)',
|
||||
} as any),
|
||||
);
|
||||
const { container } = render(<Row align="middle" />);
|
||||
expect(container.innerHTML).toContain('ant-row-middle');
|
||||
const { container: container2 } = render(<Row align={{ xs: 'middle' }} />);
|
||||
expect(container2.innerHTML).toContain('ant-row-middle');
|
||||
const { container: container3 } = render(<Row align={{ lg: 'middle' }} />);
|
||||
expect(container3.innerHTML).not.toContain('ant-row-middle');
|
||||
});
|
||||
|
||||
it('should justify by responsive justify prop', () => {
|
||||
const matchMediaSpy = jest.spyOn(window, 'matchMedia');
|
||||
matchMediaSpy.mockImplementation(
|
||||
query =>
|
||||
({
|
||||
addListener: (cb: (e: { matches: boolean }) => void) => {
|
||||
cb({ matches: query === '(max-width: 575px)' });
|
||||
},
|
||||
removeListener: jest.fn(),
|
||||
matches: query === '(max-width: 575px)',
|
||||
} as any),
|
||||
);
|
||||
const { container } = render(<Row justify="center" />);
|
||||
expect(container.innerHTML).toContain('ant-row-center');
|
||||
const { container: container2 } = render(<Row justify={{ xs: 'center' }} />);
|
||||
expect(container2.innerHTML).toContain('ant-row-center');
|
||||
const { container: container3 } = render(<Row justify={{ lg: 'center' }} />);
|
||||
expect(container3.innerHTML).not.toContain('ant-row-center');
|
||||
});
|
||||
});
|
||||
|
@ -44,9 +44,9 @@ If the Ant Design grid layout component does not meet your needs, you can use th
|
||||
|
||||
| Property | Description | Type | Default | Version |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| align | Vertical alignment | `top` \| `middle` \| `bottom` | `top` | |
|
||||
| align | Vertical alignment | `top` \| `middle` \| `bottom` \| `stretch` \| `{[key in 'xs' \| 'sm' \| 'md' \| 'lg' \| 'xl' \| 'xxl']: 'top' \| 'middle' \| 'bottom' \| 'stretch'}` | `top` | object: 4.24.0 |
|
||||
| gutter | Spacing between grids, could be a number or a object like { xs: 8, sm: 16, md: 24}. Or you can use array to make horizontal and vertical spacing work at the same time `[horizontal, vertical]` | number \| object \| array | 0 | |
|
||||
| justify | Horizontal arrangement | `start` \| `end` \| `center` \| `space-around` \| `space-between` \| `space-evenly` | `start` | |
|
||||
| justify | Horizontal arrangement | `start` \| `end` \| `center` \| `space-around` \| `space-between` \| `space-evenly` \| `{[key in 'xs' \| 'sm' \| 'md' \| 'lg' \| 'xl' \| 'xxl']: 'start' \| 'end' \| 'center' \| 'space-around' \| 'space-between' \| 'space-evenly'}` | `start` | object: 4.24.0 |
|
||||
| wrap | Auto wrap line | boolean | true | 4.8.0 |
|
||||
|
||||
### Col
|
||||
|
@ -43,9 +43,9 @@ Ant Design 的布局组件若不能满足你的需求,你也可以直接使用
|
||||
|
||||
| 成员 | 说明 | 类型 | 默认值 | 版本 |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| align | 垂直对齐方式 | `top` \| `middle` \| `bottom` | `top` | |
|
||||
| align | 垂直对齐方式 | `top` \| `middle` \| `bottom` \| `stretch` \| `{[key in 'xs' \| 'sm' \| 'md' \| 'lg' \| 'xl' \| 'xxl']: 'top' \| 'middle' \| 'bottom' \| 'stretch'}` | `top` | object: 4.24.0 |
|
||||
| gutter | 栅格间隔,可以写成像素值或支持响应式的对象写法来设置水平间隔 { xs: 8, sm: 16, md: 24}。或者使用数组形式同时设置 `[水平间距, 垂直间距]` | number \| object \| array | 0 | |
|
||||
| justify | 水平排列方式 | `start` \| `end` \| `center` \| `space-around` \| `space-between` \| `space-evenly` | `start` | |
|
||||
| justify | 水平排列方式 | `start` \| `end` \| `center` \| `space-around` \| `space-between` \| `space-evenly` \| `{[key in 'xs' \| 'sm' \| 'md' \| 'lg' \| 'xl' \| 'xxl']: 'start' \| 'end' \| 'center' \| 'space-around' \| 'space-between' \| 'space-evenly'}` | `start` | object: 4.24.0 |
|
||||
| wrap | 是否自动换行 | boolean | true | 4.8.0 |
|
||||
|
||||
### Col
|
||||
|
@ -10,16 +10,50 @@ import RowContext from './RowContext';
|
||||
const RowAligns = tuple('top', 'middle', 'bottom', 'stretch');
|
||||
const RowJustify = tuple('start', 'end', 'center', 'space-around', 'space-between', 'space-evenly');
|
||||
|
||||
type Responsive = 'xxl' | 'xl' | 'lg' | 'md' | 'sm' | 'xs';
|
||||
type ResponsiveLike<T> = {
|
||||
[key in Responsive]?: T;
|
||||
};
|
||||
|
||||
type Gap = number | undefined;
|
||||
export type Gutter = number | undefined | Partial<Record<Breakpoint, number>>;
|
||||
|
||||
type ResponsiveAligns = ResponsiveLike<typeof RowAligns[number]>;
|
||||
type ResponsiveJustify = ResponsiveLike<typeof RowJustify[number]>;
|
||||
export interface RowProps extends React.HTMLAttributes<HTMLDivElement> {
|
||||
gutter?: Gutter | [Gutter, Gutter];
|
||||
align?: typeof RowAligns[number];
|
||||
justify?: typeof RowJustify[number];
|
||||
align?: typeof RowAligns[number] | ResponsiveAligns;
|
||||
justify?: typeof RowJustify[number] | ResponsiveJustify;
|
||||
prefixCls?: string;
|
||||
wrap?: boolean;
|
||||
}
|
||||
|
||||
function useMergePropByScreen(oriProp: RowProps['align'] | RowProps['justify'], screen: ScreenMap) {
|
||||
const [prop, setProp] = React.useState(typeof oriProp === 'string' ? oriProp : '');
|
||||
|
||||
const clacMergeAlignOrJustify = () => {
|
||||
if (typeof oriProp !== 'object') {
|
||||
return;
|
||||
}
|
||||
for (let i = 0; i < responsiveArray.length; i++) {
|
||||
const breakpoint: Breakpoint = responsiveArray[i];
|
||||
// if do not match, do nothing
|
||||
if (!screen[breakpoint]) continue;
|
||||
const curVal = oriProp[breakpoint];
|
||||
if (curVal !== undefined) {
|
||||
setProp(curVal);
|
||||
return;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
React.useEffect(() => {
|
||||
clacMergeAlignOrJustify();
|
||||
}, [JSON.stringify(oriProp), screen]);
|
||||
|
||||
return prop;
|
||||
}
|
||||
|
||||
const Row = React.forwardRef<HTMLDivElement, RowProps>((props, ref) => {
|
||||
const {
|
||||
prefixCls: customizePrefixCls,
|
||||
@ -43,6 +77,20 @@ const Row = React.forwardRef<HTMLDivElement, RowProps>((props, ref) => {
|
||||
xl: true,
|
||||
xxl: true,
|
||||
});
|
||||
// to save screens info when responsiveObserve callback had been call
|
||||
const [curScreens, setCurScreens] = React.useState<ScreenMap>({
|
||||
xs: false,
|
||||
sm: false,
|
||||
md: false,
|
||||
lg: false,
|
||||
xl: false,
|
||||
xxl: false,
|
||||
});
|
||||
|
||||
// ================================== calc reponsive data ==================================
|
||||
const mergeAlign = useMergePropByScreen(align, curScreens);
|
||||
|
||||
const mergeJustify = useMergePropByScreen(justify, curScreens);
|
||||
|
||||
const supportFlexGap = useFlexGapSupport();
|
||||
|
||||
@ -51,6 +99,7 @@ const Row = React.forwardRef<HTMLDivElement, RowProps>((props, ref) => {
|
||||
// ================================== Effect ==================================
|
||||
React.useEffect(() => {
|
||||
const token = ResponsiveObserve.subscribe(screen => {
|
||||
setCurScreens(screen);
|
||||
const currentGutter = gutterRef.current || 0;
|
||||
if (
|
||||
(!Array.isArray(currentGutter) && typeof currentGutter === 'object') ||
|
||||
@ -89,8 +138,8 @@ const Row = React.forwardRef<HTMLDivElement, RowProps>((props, ref) => {
|
||||
prefixCls,
|
||||
{
|
||||
[`${prefixCls}-no-wrap`]: wrap === false,
|
||||
[`${prefixCls}-${justify}`]: justify,
|
||||
[`${prefixCls}-${align}`]: align,
|
||||
[`${prefixCls}-${mergeJustify}`]: mergeJustify,
|
||||
[`${prefixCls}-${mergeAlign}`]: mergeAlign,
|
||||
[`${prefixCls}-rtl`]: direction === 'rtl',
|
||||
},
|
||||
className,
|
||||
|
Loading…
Reference in New Issue
Block a user