Skip to content

Commit

Permalink
feat(grid): add Row and Col components (#734)
Browse files Browse the repository at this point in the history
Co-authored-by: Dan <liudan548326@yeah.net>
  • Loading branch information
Lee Hon and Dan authored Jan 25, 2021
1 parent 2cf9932 commit 57d63a1
Show file tree
Hide file tree
Showing 13 changed files with 17,793 additions and 42 deletions.
87 changes: 66 additions & 21 deletions src/components/grid/Grid.stories.tsx
Original file line number Diff line number Diff line change
@@ -1,28 +1,73 @@
import React from 'react'
import { Meta, Story } from '@storybook/react/types-6-0'

import Grid from './index'
import { GridProps } from './interface'
import './style/index.less'
import './style/demo.less'
import React from 'react';
import { Meta, Story } from '@storybook/react/types-6-0';
import { Row, Col } from './index';
import { RowProps, ColProps } from './interface';
import './style/index.less';
import './style/row.less';
import './style/demo.less';

export default {
title: 'Components/Basic/Grid',
component: Grid,
title: 'Basic Components/Grid',
component: Row,
} as Meta;

const Template : Story<GridProps> = (args) => (
<Grid className="demo">
<Grid {...args} span={12}>Text</Grid>
<Grid {...args}>Text</Grid>
<Grid {...args}>Text</Grid>
<Grid {...args}>Text</Grid>
<Grid {...args}>Text</Grid>
</Grid>
);
const Template: Story<RowProps & ColProps> = (args) => {
const { gutter, direction, justify, alignItems, alignContent, wrap, order, span, offset } = args;
const rowProps = { gutter, direction, justify, alignItems, alignContent, wrap };
const rolProps = { order, span, offset };
return (
<div className="grid-demo">
<Row {...args}>
<Col span={12} className="box">
<div>100%</div>
</Col>
</Row>
<Row {...rowProps}>
<Col span={4} className="box" {...rolProps}>
<div>对参数的修改可在此处看到效果</div>
</Col>
<Col span={4} className="box">
<div>33.33%</div>
</Col>
<Col span={4} className="box">
<div>33.33%</div>
</Col>
</Row>
<Row {...args}>
<Col span={3} className="box">
<div>25%</div>
</Col>
<Col span={3} className="box">
<div>25%</div>
</Col>
<Col span={3} className="box">
<div>25%</div>
</Col>
<Col span={3} className="box">
<div>25%</div>
</Col>
</Row>
<Row {...args}>
<Col span={8} className="box">
<div>66.66%</div>
</Col>
<Col span={4} className="box">
<div>33.33%</div>
</Col>
</Row>
</div>
);
};

export const Default = Template.bind({});
Default.args = {
span: 3,
className: "box",
}
gutter: [0, 10],
direction: 'row',
justify: 'flex-start',
alignItems: 'stretch',
alignContent: 'stretch',
wrap: 'wrap',
order: 0,
span: 4,
offset: 0,
};
48 changes: 48 additions & 0 deletions src/components/grid/__test__/__snapshots__/grid.test.tsx.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`Testing Grid should be stable 1`] = `
<DocumentFragment>
<div
class="gio-row"
style="margin: -5px -5px 5px -5px;"
>
<div
class="gio-col gio-col-span-3"
style="padding: 5px 5px 5px 5px;"
>
0
</div>
<div
class="gio-col gio-col-span-1 gio-col-order-1"
style="padding: 5px 5px 5px 5px;"
>
3
</div>
<div
class="gio-col gio-col-span-1"
style="padding: 5px 5px 5px 5px;"
>
1
</div>
<div
class="gio-col gio-col-span-7"
style="padding: 5px 5px 5px 5px;"
>
<div
class="gio-row"
>
<div
class="gio-col gio-col-span-6 gio-col-offset-3"
>
4
</div>
<div
class="gio-col gio-col-span-3"
>
5
</div>
</div>
</div>
</div>
</DocumentFragment>
`;
24 changes: 24 additions & 0 deletions src/components/grid/__test__/grid.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import React from 'react';
import { render } from '@testing-library/react';
import { Row, Col } from '..';

describe('Testing Grid', () => {
it('should be stable', () => {
const { asFragment } = render(
<Row gutter={[10, 10]}>
<Col span={3}>0</Col>
<Col order={1}>3</Col>
<Col>1</Col>
<Col span={7}>
<Row>
<Col span={6} offset={3}>
4
</Col>
<Col span={3}>5</Col>
</Row>
</Col>
</Row>
);
expect(asFragment()).toMatchSnapshot();
});
});
50 changes: 50 additions & 0 deletions src/components/grid/col.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import React, { useContext } from 'react';
import classNames from 'classnames';
import { isNumber } from 'lodash';
import { ColProps } from './interface';
import usePrefixCls from '../../utils/hooks/use-prefix-cls';
import { RowContext } from './row';

const Col = ({
component: Component = 'div',
prefixCls: customizePrefixCls,
children,
className,
style,
order,
offset,
span = 1,
}: React.PropsWithChildren<ColProps>) => {
const prefixCls = usePrefixCls('col', customizePrefixCls);
const { gutters } = useContext(RowContext);

const mergedStyle: React.CSSProperties = {
...(gutters[0] > 0
? {
paddingLeft: gutters[0] / 2,
paddingRight: gutters[0] / 2,
}
: {}),
...(gutters[1] > 0
? {
paddingTop: gutters[1] / 2,
paddingBottom: gutters[1] / 2,
}
: {}),
...style,
};

return (
<Component
className={classNames(prefixCls, className, `${prefixCls}-span-${span}`, {
[`${prefixCls}-order-${order}`]: isNumber(order),
[`${prefixCls}-offset-${offset}`]: isNumber(offset),
})}
style={mergedStyle}
>
{children}
</Component>
);
};

export default Col;
File renamed without changes.
8 changes: 8 additions & 0 deletions src/components/grid/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import Row from './row';
import Col from './col';
import Grid from './grid';

export { GridProps, RowProps, ColProps } from './interface';

export { Row, Col };
export default Grid;
63 changes: 57 additions & 6 deletions src/components/grid/interface.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,23 @@
import React, { ElementType } from 'react';

interface ComponentProps {
/**
`className`前缀
*/
prefixCls?: string;
className?: string;
style?: React.CSSProperties;
/**
根元素的组件
*/
component?: ElementType;
}

export interface GridProps<C extends ElementType = ElementType> extends ComponentProps {
export interface GridProps extends ComponentProps {
/**
`className`前缀
*/
prefixCls?: string;
/**
根元素的组件
*/
component?: C;

// flexbox types
/**
Expand Down Expand Up @@ -42,7 +46,7 @@ export interface GridProps<C extends ElementType = ElementType> extends Componen
gap?: number | string;

/**
宽度,1 个单位=8px
所占的栅格数
*/
span?: number;
/**
Expand All @@ -54,3 +58,50 @@ export interface GridProps<C extends ElementType = ElementType> extends Componen
*/
collapse?: boolean;
}

export interface RowContextState {
gutters: [number, number];
}

export interface RowProps extends ComponentProps {
// flexbox types
/**
`flex-direction`映射
*/
direction?: 'row' | 'row-reverse' | 'column' | 'column-reverse';
/**
`justify-content`映射
*/
justify?: 'flex-start' | 'center' | 'flex-end' | 'space-between' | 'space-around' | 'space-evenly';
/**
`align-items`映射
*/
alignItems?: 'flex-start' | 'center' | 'flex-end' | 'stretch' | 'baseline';
/**
`align-content`映射
*/
alignContent?: 'stretch' | 'center' | 'flex-start' | 'flex-end' | 'space-between' | 'space-around';
/**
`flex-wrap`映射
*/
wrap?: 'nowrap' | 'wrap' | 'wrap-reverse';
/**
子元素的间距,可能为 `css-grid gap` 的映射
*/
gutter?: number | [number, number];
}

export interface ColProps extends ComponentProps {
/**
`flex order` 映射
*/
order?: number;
/**
所占的栅格数
*/
span?: number;
/*
栅格左侧的间隔格数,间隔内不可以有栅格
*/
offset?: number;
}
65 changes: 65 additions & 0 deletions src/components/grid/row.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import React, { createContext, Context, useMemo } from 'react';
import classNames from 'classnames';
import { isArray, isUndefined } from 'lodash';
import { RowProps, RowContextState } from './interface';
import usePrefixCls from '../../utils/hooks/use-prefix-cls';
import { dataMap } from './help';

export const RowContext: Context<RowContextState> = createContext({ gutters: [0, 0] });

const Row = ({
component: Component = 'div',
prefixCls: customizePrefixCls,
className,
style,
children,
direction,
justify,
alignItems,
alignContent,
wrap,
gutter = 0,
}: React.PropsWithChildren<RowProps>) => {
const prefixCls = usePrefixCls('row', customizePrefixCls);

const gutters: [number, number] = useMemo(() => {
if (isUndefined(gutter)) return [0, 0];
return isArray(gutter) ? gutter : [gutter, gutter];
}, [gutter]);

const cssVars = dataMap(
{
direction,
justify,
alignItems,
alignContent,
wrap,
},
'--gio-grid'
) as React.CSSProperties;

const rowHackStyle = {
...(gutters[0] > 0
? {
marginLeft: gutters[0] / -2,
marginRight: gutters[0] / -2,
}
: {}),
...(gutters[1] > 0
? {
marginTop: gutters[1] / -2,
marginBottom: gutters[1] / 2,
}
: {}),
};

return (
<RowContext.Provider value={{ gutters }}>
<Component className={classNames(prefixCls, className)} style={{ ...cssVars, ...rowHackStyle, ...style }}>
{children}
</Component>
</RowContext.Provider>
);
};

export default Row;
Loading

1 comment on commit 57d63a1

@vercel
Copy link

@vercel vercel bot commented on 57d63a1 Jan 25, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.