Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[feat]: add gio-grid component #338

Merged
merged 38 commits into from
Oct 26, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
4ba98b9
feat: add grid
iahu Oct 21, 2020
efff50b
feat: add test cases
iahu Oct 22, 2020
4c57128
fix: make ts happy again
iahu Oct 22, 2020
846acda
chore: revert yarn.lock file
iahu Oct 22, 2020
3a49ce2
chore: remove package-lock.json
iahu Oct 22, 2020
119d484
fix: typo
iahu Oct 24, 2020
d4f9f65
Merge branch 'master' into grid
iahu Oct 25, 2020
fe15842
feat: time-picker (#292)
gh2049 Oct 12, 2020
d6e6628
feat(searchbar): add placeholder prop (#290)
Oct 12, 2020
75286b2
refactor(table): define when dataSource update, pagination behaviour …
Oct 12, 2020
960ed51
feat(date-picker): add rengePicker feature (#296)
berber1016 Oct 12, 2020
116bf06
docs: @gio-design/components 20.10.0 change log (#306)
Oct 13, 2020
661d5c2
docs: @gio-design/components 20.10.1 change log (#309)
Oct 13, 2020
aff4c0b
docs: @gio-design/components 20.10.2 change log
Oct 13, 2020
983e628
docs: update version number
Oct 13, 2020
228c993
fix: time-picker style (#307)
gh2049 Oct 15, 2020
eb82533
feat(date-picker): add dateRangePicker disabledDate methods (#314)
berber1016 Oct 15, 2020
0d9a860
fix: allow use value control selections; (#317)
Oct 15, 2020
6ea3163
style(form): 根据stylelint的提示,修改了form组件中index.less中部分属性的顺序 (#318)
WORLDI Oct 16, 2020
c8c5108
fix select text overflow and add icons (#319)
Oct 16, 2020
a9619d2
docs: @gio-design/components 20.10.3 change log (#320)
Oct 16, 2020
f4b295c
docs: @gio-designs/components release-20.10.4 change log (#322)
Oct 16, 2020
de49f90
feat: add grid
iahu Oct 21, 2020
ef52dbb
feat: add test cases
iahu Oct 22, 2020
61db1ce
fix: make ts happy again
iahu Oct 22, 2020
318ce9e
chore: revert yarn.lock file
iahu Oct 22, 2020
9554339
chore: remove package-lock.json
iahu Oct 22, 2020
5d68782
fix: typo
iahu Oct 24, 2020
84dd64b
fix(upload): upload组件增加一个可选参数isBorder,控制图片上传成功后边框是否显示 (#331)
WORLDI Oct 20, 2020
a0a84cc
chore: create release pull request template
jack0pan Oct 20, 2020
6cb9be5
chore: delete old pull request template
jack0pan Oct 20, 2020
5354b3a
chore: create feature or fix pull request template
jack0pan Oct 20, 2020
4dc7070
fix(dropdown): 修复Dropdown组件中placement方向的问题,由12个方向改为只有上下6个方向可选,默认方向为下 …
WORLDI Oct 22, 2020
d630222
style(select): 定义了select组件中input选择框内的文字尺寸 (#337)
WORLDI Oct 22, 2020
679071a
test(alert): unit test of alert component is added (#339)
WORLDI Oct 22, 2020
8373b90
fix(components): change folder name from camel case to kebab case (#329)
phyzess Oct 23, 2020
a70891e
Merge branch 'grid' of github.com:iahu/gio-design into grid
iahu Oct 25, 2020
227b893
fix: index time-picker
iahu Oct 25, 2020
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
82 changes: 82 additions & 0 deletions packages/components/src/components/grid/__test__/grid.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
import React from 'react';
import { render, unmountComponentAtNode } from 'react-dom';
import { act } from 'react-dom/test-utils';
import Grid from '..';

let container: HTMLDivElement;
beforeEach(() => {
// 创建一个 DOM 元素作为渲染目标
container = document.createElement('div');
document.body.appendChild(container);
});

afterEach(() => {
// 退出时进行清理
unmountComponentAtNode(container);
container.remove();
container = (undefined as unknown) as HTMLDivElement;
});

describe('<Grid />', () => {
it('should render correctly', () => {
act(() => {
render(<Grid />, container);
});
expect(container.querySelector('.gio-grid')).not.toBeNull();
});

it('should render custom classNames', () => {
act(() => {
render(<Grid className="test1 test2" />, container);
});
expect(container.querySelector('.gio-grid.test1.test2')).not.toBeNull();
});

it('should replace the root node with the passed `component` options', () => {
act(() => {
render(<Grid component="span" />, container);
});
expect(container.querySelector('.gio-grid')).not.toBeNull();
});

it('should render nested', () => {
act(() => {
render(
<Grid>
<Grid />
<Grid>
<Grid />
</Grid>
</Grid>,
container
);
});
expect(container.querySelectorAll('.gio-grid').length).toEqual(4);
expect(container.querySelector('.gio-grid > .gio-grid > .gio-grid')).not.toBeNull();
});

it('should make css custom properties', () => {
act(() => {
render(
<Grid
span={12}
gap={1}
direction="row"
wrap="wrap"
justify="center"
alignItems="center"
alignContent="center"
/>,
container
);
});

const grid = container.querySelector('.gio-grid') as HTMLDivElement;
expect(grid.style.getPropertyValue('--gio-grid-span')).toBe('12');
expect(grid.style.getPropertyValue('--gio-grid-gap')).toBe('1');
expect(grid.style.getPropertyValue('--gio-grid-wrap')).toBe('wrap');
expect(grid.style.getPropertyValue('--gio-grid-justify')).toBe('center');
expect(grid.style.getPropertyValue('--gio-grid-align-items')).toBe('center');
expect(grid.style.getPropertyValue('--gio-grid-align-content')).toBe('center');
});
});
39 changes: 39 additions & 0 deletions packages/components/src/components/grid/help.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import isNil from 'lodash/isNil';
import isNaN from 'lodash/isNaN';
import keys from 'lodash/keys';
import kebabCase from 'lodash/kebabCase';

export default {};

export const getAttrName = (cls: string, prefix?: string): string => {
// if (!prefix) {
// return cls;
// }
return `${prefix}-${kebabCase(cls)}`;
};

interface ObjType {
[key: string]: undefined | number | string | boolean;
}

type Ret<T> = {
[P in keyof T]: string | boolean;
};

const falsely = <T>(o: T) => isNil(o) || isNaN(o);

export const dataMap = <T extends ObjType = ObjType>(obj: T, prefixCls: string): Ret<T> => {
const cls = {} as Ret<T>;
keys(obj).forEach((key) => {
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
cls[getAttrName(key, prefixCls) as keyof Ret<T>] = falsely(obj[key]) ? false : obj[key]!.toString();
});

return cls;
};

export const clip = (min: number, max: number, value: number): number => {
return Math.max(min, Math.min(max, value));
};

export const isNumber = <T = unknown>(n: T): boolean => typeof n === 'number';
Copy link
Collaborator

Choose a reason for hiding this comment

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

有个isFinite可以判断非Nan和infinity的数字

53 changes: 53 additions & 0 deletions packages/components/src/components/grid/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import React, { useContext } from 'react';
import classNames from 'classnames';

import { ConfigContext } from '../config-provider/context';
import { GridProps } from './interface';
import { clip, dataMap, isNumber } from './help';

const Grid: React.FC<GridProps> = (props: React.PropsWithChildren<GridProps>) => {
const {
component: Component = 'div',
prefixCls: customizePrefixCls,
className,
children,
direction,
justify,
alignItems,
alignContent,
wrap,
span,
gap,
container = false,
collapse = false,
style,
} = props;
const { getPrefixCls } = useContext(ConfigContext);
const prefixCls = getPrefixCls('grid', customizePrefixCls);
const cssProps = dataMap(
{
direction,
justify,
alignItems,
alignContent,
span: isNumber(span) ? clip(0, 12, span as number) : span,
gap,
wrap,
},
'--gio-grid'
);

return (
<Component
className={classNames(prefixCls, className)}
data-collapse={collapse}
data-gap={!!gap}
data-container={!!container}
style={{ ...cssProps, ...style }}
>
{children}
</Component>
);
};

export default Grid;
25 changes: 25 additions & 0 deletions packages/components/src/components/grid/interface.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import React, { ElementType } from 'react';

interface ComponentProps {
className?: string;
style?: React.CSSProperties;
}

export interface GridProps<C extends ElementType = ElementType> extends ComponentProps {
prefixCls?: string;
component?: C;

// flexbox types
direction?: 'row' | 'row-reverse' | 'column' | 'column-reverse';
justify?: 'flex-start' | 'center' | 'flex-end' | 'space-between' | 'space-around' | 'space-evenly';
alignItems?: 'flex-start' | 'center' | 'flex-end' | 'stretch' | 'baseline';
alignContent?: 'stretch' | 'center' | 'flex-start' | 'flex-end' | 'space-between' | 'space-around';
wrap?: 'nowrap' | 'wrap' | 'wrap-reverse';
gap?: number | string;

// grid property
span?: number;
container?: boolean;

collapse?: boolean;
}
59 changes: 59 additions & 0 deletions packages/components/src/components/grid/style/index.less
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
@import '../../../stylesheet/index.less';

@component-cls: ~'@{component-prefix}-grid';

.@{component-cls} {
display: flex;
flex-wrap: var(--gio-grid-wrap, wrap);
box-sizing: border-box;
flex-direction: var(--gio-grid-direction, row);
justify-content: var(--gio-grid-justify, flex-start);
align-items: var(--gio-grid-align-items, stretch);
align-content: var(--gio-grid-align-content, stretch);

--gio-grid-gap-size: calc(var(--gio-grid-gap, 0) * 8px);

&[data-container='true'] {
position: relative;
width: 100%;
}

.normal-gap {
width: calc(100% * var(--gio-grid-span) / 12 - var(--gio-grid-gap-size));

&[data-gap='true'] {
> * {
--gio-grid-item-marign: calc(var(--gio-grid-gap-size) / 2);
margin: var(--gio-grid-item-marign);
}
}
}

.css-grid-gap {
gap: var(--gio-grid-gap-size);
width: calc((100% + var(--gio-grid-gap-size)) / 12 * var(--gio-grid-span) - var(--gio-grid-gap-size));

&[data-gap='true'] {
--gio-grid-item-marign: unset;
// > * {
// margin: unset !important;
// }
}
}

&[data-collapse='false'] {
.normal-gap();

> [data-gap] {
.normal-gap();
}
}

&[data-collapse='true'] {
.css-grid-gap();

> [data-gap] {
.css-grid-gap();
}
}
}
1 change: 1 addition & 0 deletions packages/components/src/components/grid/style/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
import './index.less';
1 change: 1 addition & 0 deletions packages/components/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,3 +40,4 @@ export { default as List } from './components/list';
export { default as Select } from './components/select';
export { default as Form, FormLayout } from './components/form';
export { default as TimePicker } from './components/time-picker';
export { default as Grid } from './components/grid';
29 changes: 29 additions & 0 deletions packages/website/src/components/basic/grid/demo/base.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import React from 'react';
import { Grid } from '@gio-design/components';

import '@gio-design/components/es/components/grid/style/index.css';
import './style.less';

const Base = (): JSX.Element => {
return (
<Grid className="demo">
<Grid className="box" span={12}>
span=12
</Grid>
<Grid className="box" span={3}>
span=3
</Grid>
<Grid className="box" span={3}>
span=3
</Grid>
<Grid className="box" span={3}>
span=3
</Grid>
<Grid className="box" span={3}>
span=3
</Grid>
</Grid>
);
};

export default Base;
23 changes: 23 additions & 0 deletions packages/website/src/components/basic/grid/demo/collapse.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import React from 'react';
import { Grid } from '@gio-design/components';

import '@gio-design/components/es/components/grid/style/index.css';
import './style.less';

const Base = (): JSX.Element => {
return (
<Grid collapse container gap={1} className="demo">
<Grid span={12}>span=12</Grid>
<Grid span={3} gap={1} collapse container>
<Grid span={12}>span=12</Grid>
<Grid span={6}>span=6</Grid>
<Grid span={6}>span=6</Grid>
</Grid>
<Grid span={3}>span=3</Grid>
<Grid span={3}>span=3</Grid>
<Grid span={3}>span=3</Grid>
</Grid>
);
};

export default Base;
65 changes: 65 additions & 0 deletions packages/website/src/components/basic/grid/demo/flex.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import '@gio-design/components/es/components/grid/style/index.css';

import React, { useState } from 'react';

import { Grid, Form, Radio, RadioGroup } from '@gio-design/components';

const { Item } = Form;

const options = {
direction: ['row', 'row-reverse', 'column', 'column-reverse'],
justify: ['flex-start', 'center', 'flex-end', 'space-between', 'space-around', 'space-evenly'],
alignItems: ['flex-start', 'center', 'flex-end', 'stretch', 'baseline'],
alignContent: ['stretch', 'center', 'flex-start', 'flex-end', 'space-between', 'space-around'],
wrap: ['wrap', 'nowrap', 'wrap-reverse'],
} as const;

type Options = typeof options;
type OptionKey = keyof Options;
const optionKeys = Object.keys(options) as Array<OptionKey>;

type InitState = {
[P in OptionKey]: Options[P][number];
};
const initState = {} as InitState;

optionKeys.forEach((key) => {
const [value] = options[key];
(initState[key] as InitState[OptionKey]) = value;
});

const Base = (): JSX.Element => {
const [formData, setFormData] = useState(initState);
const onValuesChange = (value: Partial<InitState>) => setFormData({ ...formData, ...value });

return (
<div className="flex-props">
<Grid container gap={1} {...(formData as unknown)} className="box demo">
<Grid span={12}>span=12</Grid>
<Grid span={3}>span=3</Grid>
<Grid span={3}>span=6</Grid>
<Grid span={3} style={{ height: 140 }}>
span=3
</Grid>
</Grid>

<div className="box">
<Form initialValues={formData} onValuesChange={onValuesChange}>
{optionKeys.map((key) => (
<Item key={key} name={key} label={`${key}:`}>
<RadioGroup>
{(options[key] as readonly string[]).map((d) => (
<Radio key={d} value={d}>
{d}
</Radio>
))}
</RadioGroup>
</Item>
))}
</Form>
</div>
</div>
);
};

export default Base;
Loading