mirror of
https://github.com/ant-design/ant-design.git
synced 2025-01-18 22:36:31 +08:00
Merge pull request #25589 from ant-design/master
chore: merge master into feature
This commit is contained in:
commit
4b2bc6c6fb
@ -15,6 +15,25 @@ timeline: true
|
||||
|
||||
---
|
||||
|
||||
## 4.4.2
|
||||
|
||||
`2020-07-11`
|
||||
|
||||
- 🛠 Adjust Alert animation to remove directly dom operation. [#dd8e9f8](https://github.com/ant-design/ant-design/commit/dd8e9f8) [@Yunfly](https://github.com/Yunfly)
|
||||
- Select
|
||||
- 🐞 Fix Select shifts vertically when searching. [#25536](https://github.com/ant-design/ant-design/pull/25536) [@07akioni](https://github.com/07akioni)
|
||||
- 💄 Add `@select-item-select-color` to control the color when Select item is selected. [#25476](https://github.com/ant-design/ant-design/pull/25476)
|
||||
- 🐞 Fix Form.Item warning for `preserve` as invalidate dom prop. [#25518](https://github.com/ant-design/ant-design/pull/25518)
|
||||
- 🐞 Fix Card cover margin bug when bordered is false. [#25515](https://github.com/ant-design/ant-design/pull/25515) [@yutingzhao1991](https://github.com/yutingzhao1991)
|
||||
- 💄 Adjust Typography style to set `overflow-wrap: break-word` as default. [#25516](https://github.com/ant-design/ant-design/pull/25516)
|
||||
- 🐞 Fix Table `expandedRowRender` nested Table cell background color. [#25498](https://github.com/ant-design/ant-design/pull/25498)
|
||||
- 🐞 Fix Popover wrong positioning on Radio.Button. [#25449](https://github.com/ant-design/ant-design/pull/25449) [@zgoby](https://github.com/zgoby)
|
||||
- 🐞 Fix RangePicker clear icon position issue when `size=small`. [#25458](https://github.com/ant-design/ant-design/pull/25458)
|
||||
- 🆕 Upload supports to show thumbnail for non-image files as `thumbUrl` configured in `onChange` event. [#25432](https://github.com/ant-design/ant-design/pull/25432) [@AlbertAZ1992](https://github.com/AlbertAZ1992)
|
||||
- 🐞 Fix Table `onChange` triggered multiple times when change page size. [#25520](https://github.com/ant-design/ant-design/pull/25520) [@zhangchen915](https://github.com/zhangchen915)
|
||||
- 🛠 Remove `babel-runtime` and add `@babel/runtime` in dependencies, reduce gzipped bundle size `18.6KB`. [#25530](https://github.com/ant-design/ant-design/pull/25530)
|
||||
- 🇪🇸 Improve es_ES localization. [#25460](https://github.com/ant-design/ant-design/pull/25460) [@gersongams](https://github.com/gersongams)
|
||||
|
||||
## 4.4.1
|
||||
|
||||
`2020-07-06`
|
||||
|
@ -15,6 +15,25 @@ timeline: true
|
||||
|
||||
---
|
||||
|
||||
## 4.4.2
|
||||
|
||||
`2020-07-11`
|
||||
|
||||
- 🛠 调整 Alert 组件关闭动画实现移除直接的 dom 操作。[#dd8e9f8](https://github.com/ant-design/ant-design/commit/dd8e9f8) [@Yunfly](https://github.com/Yunfly)
|
||||
- Select
|
||||
- 🐞 修正了 Select 在搜索时纵向位移的问题。[#25536](https://github.com/ant-design/ant-design/pull/25536) [@07akioni](https://github.com/07akioni)
|
||||
- 💄 增加 `@select-item-selected-color` 以控制 Select 选项选中时的颜色。[#25476](https://github.com/ant-design/ant-design/pull/25476)
|
||||
- 🐞 修复 Form.Item 警告 `preserve` 是无效 dom 属性的问题。[#25518](https://github.com/ant-design/ant-design/pull/25518)
|
||||
- 🐞 修复当 Card 组件无边框时封面图边距的问题。[#25515](https://github.com/ant-design/ant-design/pull/25515) [@yutingzhao1991](https://github.com/yutingzhao1991)
|
||||
- 💄 调整 Typography 样式添加 `overflow-wrap: break-word` 默认样式。[#25516](https://github.com/ant-design/ant-design/pull/25516)
|
||||
- 🐞 修复 Table `expandedRowRender` 内嵌 Table 时单元格背景丢失的问题。[#25498](https://github.com/ant-design/ant-design/pull/25498)
|
||||
- 🐞 修复 Radio.Button 上使用 Popover 时的位置异常问题。[#25449](https://github.com/ant-design/ant-design/pull/25449) [@zgoby](https://github.com/zgoby)
|
||||
- 🐞 修复 RangePicker 在 `size=small` 时清除按钮的位置问题。[#25458](https://github.com/ant-design/ant-design/pull/25458)
|
||||
- 🆕 Upload 支持上传非图片文件时在 `onChange` 事件中设置 `thumbUrl` 来展示缩略图。[#25432](https://github.com/ant-design/ant-design/pull/25432) [@AlbertAZ1992](https://github.com/AlbertAZ1992)
|
||||
- 🐞 修复 Table 切换页条目数时 `onChange` 触发多次的问题。[#25520](https://github.com/ant-design/ant-design/pull/25520) [@zhangchen915](https://github.com/zhangchen915)
|
||||
- 🛠 移除 `babel-runtime` 并添加 `@babel/runtime` 依赖,减少 gzipped 包体积 `18.6KB`。[#25530](https://github.com/ant-design/ant-design/pull/25530)
|
||||
- 🇪🇸 改进 es_ES 国际化。[#25460](https://github.com/ant-design/ant-design/pull/25460) [@gersongams](https://github.com/gersongams)
|
||||
|
||||
## 4.4.1
|
||||
|
||||
`2020-07-06`
|
||||
|
@ -88,13 +88,6 @@ const Alert: AlertInterface = ({
|
||||
const prefixCls = getPrefixCls('alert', customizePrefixCls);
|
||||
|
||||
const handleClose = (e: React.MouseEvent<HTMLButtonElement>) => {
|
||||
e.preventDefault();
|
||||
const dom = ref.current as HTMLElement;
|
||||
dom.style.height = `${dom.offsetHeight}px`;
|
||||
// Magic code
|
||||
// 重复一次后才能正确设置 height
|
||||
dom.style.height = `${dom.offsetHeight}px`;
|
||||
|
||||
setClosing(true);
|
||||
props.onClose?.(e);
|
||||
};
|
||||
|
@ -7,6 +7,7 @@
|
||||
.reset-component;
|
||||
|
||||
position: relative;
|
||||
max-height: 1000vh;
|
||||
padding: 8px 15px 8px 37px;
|
||||
word-wrap: break-word;
|
||||
border-radius: @border-radius-base;
|
||||
@ -146,7 +147,7 @@
|
||||
}
|
||||
|
||||
&&-closing {
|
||||
height: 0 !important;
|
||||
max-height: 0;
|
||||
margin: 0;
|
||||
padding-top: 0;
|
||||
padding-bottom: 0;
|
||||
|
@ -4199,7 +4199,7 @@ exports[`renders ./components/calendar/demo/notice-calendar.md correctly 1`] = `
|
||||
`;
|
||||
|
||||
exports[`renders ./components/calendar/demo/select.md correctly 1`] = `
|
||||
<div>
|
||||
Array [
|
||||
<div
|
||||
class="ant-alert ant-alert-info ant-alert-no-icon"
|
||||
data-show="true"
|
||||
@ -4212,7 +4212,7 @@ exports[`renders ./components/calendar/demo/select.md correctly 1`] = `
|
||||
<span
|
||||
class="ant-alert-description"
|
||||
/>
|
||||
</div>
|
||||
</div>,
|
||||
<div
|
||||
class="ant-picker-calendar ant-picker-calendar-full"
|
||||
>
|
||||
@ -5151,6 +5151,6 @@ exports[`renders ./components/calendar/demo/select.md correctly 1`] = `
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>,
|
||||
]
|
||||
`;
|
||||
|
@ -37,12 +37,12 @@ class App extends React.Component {
|
||||
render() {
|
||||
const { value, selectedValue } = this.state;
|
||||
return (
|
||||
<div>
|
||||
<>
|
||||
<Alert
|
||||
message={`You selected date: ${selectedValue && selectedValue.format('YYYY-MM-DD')}`}
|
||||
/>
|
||||
<Calendar value={value} onSelect={this.onSelect} onPanelChange={this.onPanelChange} />
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -559,7 +559,7 @@ exports[`renders ./components/carousel/demo/fade.md correctly 1`] = `
|
||||
`;
|
||||
|
||||
exports[`renders ./components/carousel/demo/position.md correctly 1`] = `
|
||||
<div>
|
||||
Array [
|
||||
<div
|
||||
class="ant-radio-group ant-radio-group-outline"
|
||||
style="margin-bottom:8px"
|
||||
@ -641,7 +641,7 @@ exports[`renders ./components/carousel/demo/position.md correctly 1`] = `
|
||||
Right
|
||||
</span>
|
||||
</label>
|
||||
</div>
|
||||
</div>,
|
||||
<div
|
||||
class="ant-carousel"
|
||||
>
|
||||
@ -854,6 +854,6 @@ exports[`renders ./components/carousel/demo/position.md correctly 1`] = `
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>,
|
||||
]
|
||||
`;
|
||||
|
@ -26,7 +26,7 @@ class PositionCarouselDemo extends React.Component {
|
||||
render() {
|
||||
const { dotPosition } = this.state;
|
||||
return (
|
||||
<div>
|
||||
<>
|
||||
<Radio.Group
|
||||
onChange={this.handlePositionChange}
|
||||
value={dotPosition}
|
||||
@ -51,7 +51,7 @@ class PositionCarouselDemo extends React.Component {
|
||||
<h3>4</h3>
|
||||
</div>
|
||||
</Carousel>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -460,7 +460,7 @@ exports[`renders ./components/collapse/demo/custom.md correctly 1`] = `
|
||||
`;
|
||||
|
||||
exports[`renders ./components/collapse/demo/extra.md correctly 1`] = `
|
||||
<div>
|
||||
Array [
|
||||
<div
|
||||
class="ant-collapse ant-collapse-icon-position-left"
|
||||
>
|
||||
@ -651,11 +651,11 @@ exports[`renders ./components/collapse/demo/extra.md correctly 1`] = `
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<br />
|
||||
</div>,
|
||||
<br />,
|
||||
<span>
|
||||
Expand Icon Position:
|
||||
</span>
|
||||
</span>,
|
||||
<div
|
||||
class="ant-select ant-select-single ant-select-show-arrow"
|
||||
style="margin:0 8px"
|
||||
@ -715,8 +715,8 @@ exports[`renders ./components/collapse/demo/extra.md correctly 1`] = `
|
||||
</svg>
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>,
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`renders ./components/collapse/demo/ghost.md correctly 1`] = `
|
||||
|
@ -51,7 +51,7 @@ class Demo extends React.Component {
|
||||
render() {
|
||||
const { expandIconPosition } = this.state;
|
||||
return (
|
||||
<div>
|
||||
<>
|
||||
<Collapse
|
||||
defaultActiveKey={['1']}
|
||||
onChange={callback}
|
||||
@ -77,7 +77,7 @@ class Demo extends React.Component {
|
||||
<Option value="left">left</Option>
|
||||
<Option value="right">right</Option>
|
||||
</Select>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -41,3 +41,10 @@ exports[`Grid should render Row 1`] = `
|
||||
class="ant-row"
|
||||
/>
|
||||
`;
|
||||
|
||||
exports[`Grid when typeof gutter is object array in large screen 1`] = `
|
||||
<div
|
||||
class="ant-row"
|
||||
style="margin-left:-20px;margin-right:-20px;margin-top:-200px;margin-bottom:200px"
|
||||
/>
|
||||
`;
|
||||
|
@ -4,6 +4,7 @@ import { Col, Row } from '..';
|
||||
import mountTest from '../../../tests/shared/mountTest';
|
||||
import rtlTest from '../../../tests/shared/rtlTest';
|
||||
import useBreakpoint from '../hooks/useBreakpoint';
|
||||
import ResponsiveObserve from '../../_util/responsiveObserve';
|
||||
|
||||
describe('Grid', () => {
|
||||
mountTest(Row);
|
||||
@ -24,7 +25,12 @@ describe('Grid', () => {
|
||||
|
||||
it('when typeof gutter is object', () => {
|
||||
const wrapper = mount(<Row gutter={{ xs: 8, sm: 16, md: 24 }} />);
|
||||
expect(wrapper.instance().getGutter()).toEqual([8, 0]);
|
||||
expect(wrapper.find('div').first().props().style).toEqual(
|
||||
expect.objectContaining({
|
||||
marginLeft: -4,
|
||||
marginRight: -4,
|
||||
}),
|
||||
);
|
||||
});
|
||||
|
||||
it('when typeof gutter is object array', () => {
|
||||
@ -36,11 +42,16 @@ describe('Grid', () => {
|
||||
]}
|
||||
/>,
|
||||
);
|
||||
expect(wrapper.instance().getGutter()).toEqual([8, 8]);
|
||||
expect(wrapper.find('div').first().props().style).toEqual(
|
||||
expect.objectContaining({
|
||||
marginLeft: -4,
|
||||
marginRight: -4,
|
||||
}),
|
||||
);
|
||||
});
|
||||
|
||||
it('when typeof gutter is object array in large screen', () => {
|
||||
const wrapper = mount(
|
||||
const wrapper = render(
|
||||
<Row
|
||||
gutter={[
|
||||
{ xs: 8, sm: 16, md: 24, lg: 32, xl: 40 },
|
||||
@ -48,10 +59,7 @@ describe('Grid', () => {
|
||||
]}
|
||||
/>,
|
||||
);
|
||||
wrapper.setState({
|
||||
screens: { md: true, lg: true, xl: true },
|
||||
});
|
||||
expect(wrapper.instance().getGutter()).toEqual([40, 400]);
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('renders wrapped Col correctly', () => {
|
||||
@ -68,10 +76,10 @@ describe('Grid', () => {
|
||||
});
|
||||
|
||||
it('when component has been unmounted, componentWillUnmount should be called', () => {
|
||||
const wrapper = mount(<Row />);
|
||||
const willUnmount = jest.spyOn(wrapper.instance(), 'componentWillUnmount');
|
||||
const Unmount = jest.spyOn(ResponsiveObserve, 'unsubscribe');
|
||||
const wrapper = mount(<Row gutter={{ xs: 20 }} />);
|
||||
wrapper.unmount();
|
||||
expect(willUnmount).toHaveBeenCalled();
|
||||
expect(Unmount).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should work correct when gutter is object', () => {
|
||||
|
@ -44,9 +44,8 @@ function parseFlex(flex: FlexType): string {
|
||||
return flex;
|
||||
}
|
||||
|
||||
export default class Col extends React.Component<ColProps, {}> {
|
||||
renderCol = ({ getPrefixCls, direction }: ConfigConsumerProps) => {
|
||||
const { props } = this;
|
||||
const Col = React.forwardRef<HTMLDivElement, ColProps>((props, ref) => {
|
||||
const renderCol = ({ getPrefixCls, direction }: ConfigConsumerProps) => {
|
||||
const {
|
||||
prefixCls: customizePrefixCls,
|
||||
span,
|
||||
@ -123,7 +122,7 @@ export default class Col extends React.Component<ColProps, {}> {
|
||||
}
|
||||
|
||||
return (
|
||||
<div {...others} style={mergedStyle} className={classes}>
|
||||
<div {...others} style={mergedStyle} className={classes} ref={ref}>
|
||||
{children}
|
||||
</div>
|
||||
);
|
||||
@ -132,7 +131,9 @@ export default class Col extends React.Component<ColProps, {}> {
|
||||
);
|
||||
};
|
||||
|
||||
render() {
|
||||
return <ConfigConsumer>{this.renderCol}</ConfigConsumer>;
|
||||
}
|
||||
}
|
||||
return <ConfigConsumer>{renderCol}</ConfigConsumer>;
|
||||
});
|
||||
|
||||
Col.displayName = 'Col';
|
||||
|
||||
export default Col;
|
||||
|
@ -20,48 +20,37 @@ export interface RowProps extends React.HTMLAttributes<HTMLDivElement> {
|
||||
prefixCls?: string;
|
||||
}
|
||||
|
||||
export interface RowState {
|
||||
screens: ScreenMap;
|
||||
}
|
||||
const Row = React.forwardRef<HTMLDivElement, RowProps>((props, ref) => {
|
||||
const [screens, setScreens] = React.useState<ScreenMap>({
|
||||
xs: true,
|
||||
sm: true,
|
||||
md: true,
|
||||
lg: true,
|
||||
xl: true,
|
||||
xxl: true,
|
||||
});
|
||||
const gutterRef = React.useRef<Gutter | [Gutter, Gutter]>();
|
||||
gutterRef.current = props.gutter;
|
||||
|
||||
export default class Row extends React.Component<RowProps, RowState> {
|
||||
static defaultProps = {
|
||||
gutter: 0,
|
||||
};
|
||||
|
||||
state: RowState = {
|
||||
screens: {
|
||||
xs: true,
|
||||
sm: true,
|
||||
md: true,
|
||||
lg: true,
|
||||
xl: true,
|
||||
xxl: true,
|
||||
},
|
||||
};
|
||||
|
||||
token: number;
|
||||
|
||||
componentDidMount() {
|
||||
this.token = ResponsiveObserve.subscribe(screens => {
|
||||
const { gutter } = this.props;
|
||||
React.useEffect(() => {
|
||||
const token = ResponsiveObserve.subscribe(screen => {
|
||||
const currentGutter = gutterRef.current || 0;
|
||||
if (
|
||||
(!Array.isArray(gutter) && typeof gutter === 'object') ||
|
||||
(Array.isArray(gutter) && (typeof gutter[0] === 'object' || typeof gutter[1] === 'object'))
|
||||
(!Array.isArray(currentGutter) && typeof currentGutter === 'object') ||
|
||||
(Array.isArray(currentGutter) &&
|
||||
(typeof currentGutter[0] === 'object' || typeof currentGutter[1] === 'object'))
|
||||
) {
|
||||
this.setState({ screens });
|
||||
setScreens(screen);
|
||||
}
|
||||
});
|
||||
}
|
||||
return () => {
|
||||
ResponsiveObserve.unsubscribe(token);
|
||||
};
|
||||
}, []);
|
||||
|
||||
componentWillUnmount() {
|
||||
ResponsiveObserve.unsubscribe(this.token);
|
||||
}
|
||||
|
||||
getGutter(): [number, number] {
|
||||
const getGutter = (): [number, number] => {
|
||||
const results: [number, number] = [0, 0];
|
||||
const { gutter } = this.props;
|
||||
const { screens } = this.state;
|
||||
const { gutter = 0 } = props;
|
||||
const normalizedGutter = Array.isArray(gutter) ? gutter : [gutter, 0];
|
||||
normalizedGutter.forEach((g, index) => {
|
||||
if (typeof g === 'object') {
|
||||
@ -77,9 +66,9 @@ export default class Row extends React.Component<RowProps, RowState> {
|
||||
}
|
||||
});
|
||||
return results;
|
||||
}
|
||||
};
|
||||
|
||||
renderRow = ({ getPrefixCls, direction }: ConfigConsumerProps) => {
|
||||
const renderRow = ({ getPrefixCls, direction }: ConfigConsumerProps) => {
|
||||
const {
|
||||
prefixCls: customizePrefixCls,
|
||||
justify,
|
||||
@ -88,9 +77,9 @@ export default class Row extends React.Component<RowProps, RowState> {
|
||||
style,
|
||||
children,
|
||||
...others
|
||||
} = this.props;
|
||||
} = props;
|
||||
const prefixCls = getPrefixCls('row', customizePrefixCls);
|
||||
const gutter = this.getGutter();
|
||||
const gutter = getGutter();
|
||||
const classes = classNames(
|
||||
prefixCls,
|
||||
{
|
||||
@ -120,14 +109,16 @@ export default class Row extends React.Component<RowProps, RowState> {
|
||||
|
||||
return (
|
||||
<RowContext.Provider value={{ gutter }}>
|
||||
<div {...otherProps} className={classes} style={rowStyle}>
|
||||
<div {...otherProps} className={classes} style={rowStyle} ref={ref}>
|
||||
{children}
|
||||
</div>
|
||||
</RowContext.Provider>
|
||||
);
|
||||
};
|
||||
|
||||
render() {
|
||||
return <ConfigConsumer>{this.renderRow}</ConfigConsumer>;
|
||||
}
|
||||
}
|
||||
return <ConfigConsumer>{renderRow}</ConfigConsumer>;
|
||||
});
|
||||
|
||||
Row.displayName = 'Row';
|
||||
|
||||
export default Row;
|
||||
|
@ -20465,7 +20465,7 @@ exports[`Locale Provider should display the text as ca 1`] = `
|
||||
type="button"
|
||||
>
|
||||
<span>
|
||||
OK
|
||||
D’acord
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
@ -20522,7 +20522,7 @@ exports[`Locale Provider should display the text as ca 1`] = `
|
||||
<span
|
||||
class="ant-transfer-list-header-selected"
|
||||
>
|
||||
0 item
|
||||
0 ítem
|
||||
</span>
|
||||
<span
|
||||
class="ant-transfer-list-header-title"
|
||||
@ -20537,7 +20537,7 @@ exports[`Locale Provider should display the text as ca 1`] = `
|
||||
<div>
|
||||
<input
|
||||
class="ant-input ant-transfer-list-search"
|
||||
placeholder="Cercar aquí"
|
||||
placeholder="Cercar"
|
||||
type="text"
|
||||
value=""
|
||||
/>
|
||||
@ -20720,7 +20720,7 @@ exports[`Locale Provider should display the text as ca 1`] = `
|
||||
<span
|
||||
class="ant-transfer-list-header-selected"
|
||||
>
|
||||
0 item
|
||||
0 ítem
|
||||
</span>
|
||||
<span
|
||||
class="ant-transfer-list-header-title"
|
||||
@ -20735,7 +20735,7 @@ exports[`Locale Provider should display the text as ca 1`] = `
|
||||
<div>
|
||||
<input
|
||||
class="ant-input ant-transfer-list-search"
|
||||
placeholder="Cercar aquí"
|
||||
placeholder="Cercar"
|
||||
type="text"
|
||||
value=""
|
||||
/>
|
||||
@ -21989,7 +21989,7 @@ exports[`Locale Provider should display the text as ca 1`] = `
|
||||
type="button"
|
||||
>
|
||||
<span>
|
||||
OK
|
||||
D’acord
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
|
@ -1,21 +1,34 @@
|
||||
/* eslint-disable no-template-curly-in-string */
|
||||
import Pagination from 'rc-pagination/lib/locale/ar_EG';
|
||||
import DatePicker from '../date-picker/locale/ar_EG';
|
||||
import TimePicker from '../time-picker/locale/ar_EG';
|
||||
import Calendar from '../calendar/locale/ar_EG';
|
||||
import { Locale } from '../locale-provider';
|
||||
|
||||
const typeTemplate = 'صالحًا ${type} من نوع ${label} ليس';
|
||||
|
||||
const localeValues: Locale = {
|
||||
locale: 'ar',
|
||||
Pagination,
|
||||
DatePicker,
|
||||
TimePicker,
|
||||
Calendar,
|
||||
global: {
|
||||
placeholder: 'يرجى التحديد',
|
||||
},
|
||||
Table: {
|
||||
filterTitle: 'الفلاتر',
|
||||
filterConfirm: 'تأكيد',
|
||||
filterReset: 'إعادة ضبط',
|
||||
selectAll: 'اختيار الكل',
|
||||
selectInvert: 'إلغاء الاختيار',
|
||||
selectionAll: 'حدد جميع البيانات',
|
||||
sortTitle: 'رتب',
|
||||
expand: 'توسيع الصف',
|
||||
collapse: 'طي الصف',
|
||||
triggerDesc: 'ترتيب تنازلي',
|
||||
triggerAsc: 'ترتيب تصاعدي',
|
||||
cancelSort: 'إلغاء الترتيب',
|
||||
},
|
||||
Modal: {
|
||||
okText: 'تأكيد',
|
||||
@ -41,6 +54,67 @@ const localeValues: Locale = {
|
||||
Empty: {
|
||||
description: 'لا توجد بيانات',
|
||||
},
|
||||
Icon: {
|
||||
icon: 'أيقونة',
|
||||
},
|
||||
Text: {
|
||||
edit: 'تعديل',
|
||||
copy: 'نسخ',
|
||||
copied: 'نقل',
|
||||
expand: 'وسع',
|
||||
},
|
||||
PageHeader: {
|
||||
back: 'عودة',
|
||||
},
|
||||
Form: {
|
||||
defaultValidateMessages: {
|
||||
default: '${label} خطأ في حقل الإدخال',
|
||||
required: '${label} يرجى إدخال',
|
||||
enum: '[${enum}] يجب أن يكون واحدا من ${label}',
|
||||
whitespace: 'لا يمكن أن يكون حرفًا فارغًا ${label}',
|
||||
date: {
|
||||
format: 'تنسيق التاريخ غير صحيح ${label}',
|
||||
parse: 'لا يمكن تحويلها إلى تاريخ ${label}',
|
||||
invalid: 'غير صحيح ${label} تاريخ',
|
||||
},
|
||||
types: {
|
||||
string: typeTemplate,
|
||||
method: typeTemplate,
|
||||
array: typeTemplate,
|
||||
object: typeTemplate,
|
||||
number: typeTemplate,
|
||||
date: typeTemplate,
|
||||
boolean: typeTemplate,
|
||||
integer: typeTemplate,
|
||||
float: typeTemplate,
|
||||
regexp: typeTemplate,
|
||||
email: typeTemplate,
|
||||
url: typeTemplate,
|
||||
hex: typeTemplate,
|
||||
},
|
||||
string: {
|
||||
len: 'أحرف ${len} ان يكون ${label} يجب',
|
||||
min: 'أحرف ${min} على الأقل ${label}',
|
||||
max: 'أحرف ${max} يصل إلى ${label}',
|
||||
range: 'أحرف ${max}-${min} ان يكون مابين ${label} يجب',
|
||||
},
|
||||
number: {
|
||||
len: '${len} ان يساوي ${label} يجب',
|
||||
min: '${min} الأدنى هو ${label} حد',
|
||||
max: '${max} الأقصى هو ${label} حد',
|
||||
range: '${max}-${min} ان يكون مابين ${label} يجب',
|
||||
},
|
||||
array: {
|
||||
len: '${len} طوله ${label} يجب أن يكون',
|
||||
min: '${min} طوله الأدنى ${label} يجب أن يكون',
|
||||
max: '${max} طوله الأقصى ${label} يجب أن يكون',
|
||||
range: '${max}-${min} طوله مابين ${label} يجب أن يكون',
|
||||
},
|
||||
pattern: {
|
||||
mismatch: '${pattern} مع ${label} لا يتطابق',
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
export default localeValues;
|
||||
|
@ -1,44 +1,128 @@
|
||||
/* eslint-disable no-template-curly-in-string */
|
||||
import Pagination from 'rc-pagination/lib/locale/ca_ES';
|
||||
import DatePicker from '../date-picker/locale/ca_ES';
|
||||
import TimePicker from '../time-picker/locale/ca_ES';
|
||||
import Calendar from '../calendar/locale/ca_ES';
|
||||
import { Locale } from '../locale-provider';
|
||||
|
||||
const typeTemplate = '${label} no és un ${type} vàlid';
|
||||
|
||||
const localeValues: Locale = {
|
||||
locale: 'ca',
|
||||
Pagination,
|
||||
DatePicker,
|
||||
TimePicker,
|
||||
Calendar,
|
||||
global: {
|
||||
placeholder: 'Seleccionar',
|
||||
},
|
||||
Table: {
|
||||
filterTitle: 'Filtrar Menu',
|
||||
filterConfirm: 'OK',
|
||||
filterReset: 'Restablir',
|
||||
filterTitle: 'Filtrar el menú',
|
||||
filterConfirm: 'D’acord',
|
||||
filterReset: 'Reiniciar',
|
||||
filterEmptyText: 'Sense filtres',
|
||||
selectAll: 'Seleccionar la pàgina actual',
|
||||
selectInvert: 'Invertir la selecció',
|
||||
selectionAll: 'Seleccionar-ho tot',
|
||||
sortTitle: 'Ordenar',
|
||||
expand: 'Ampliar la fila',
|
||||
collapse: 'Plegar la fila',
|
||||
triggerDesc: 'Ordre descendent',
|
||||
triggerAsc: 'Ordre ascendent',
|
||||
cancelSort: 'Desactivar l’ordre',
|
||||
},
|
||||
Modal: {
|
||||
okText: 'OK',
|
||||
okText: 'D’acord',
|
||||
cancelText: 'Cancel·lar',
|
||||
justOkText: 'OK',
|
||||
justOkText: 'D’acord',
|
||||
},
|
||||
Popconfirm: {
|
||||
okText: 'OK',
|
||||
okText: 'D’acord',
|
||||
cancelText: 'Cancel·lar',
|
||||
},
|
||||
Transfer: {
|
||||
searchPlaceholder: 'Cercar aquí',
|
||||
itemUnit: 'item',
|
||||
itemsUnit: 'items',
|
||||
titles: ['', ''],
|
||||
searchPlaceholder: 'Cercar',
|
||||
itemUnit: 'ítem',
|
||||
itemsUnit: 'ítems',
|
||||
remove: 'Eliminar',
|
||||
selectCurrent: 'Seleccionar la pàgina actual',
|
||||
removeCurrent: 'Eliminar la selecció',
|
||||
selectAll: 'Seleccionar-ho tot',
|
||||
removeAll: 'Eliminar-ho tot',
|
||||
selectInvert: 'Invertir la selecció',
|
||||
},
|
||||
Upload: {
|
||||
uploading: 'Carregant...',
|
||||
removeFile: 'Elimina el fitxer',
|
||||
uploading: 'Carregant…',
|
||||
removeFile: 'Eliminar el fitxer',
|
||||
uploadError: 'Error de càrrega',
|
||||
previewFile: 'Vista prèvia del fitxer',
|
||||
downloadFile: "Descarrega l'arxiu",
|
||||
downloadFile: 'Baixar el fitxer',
|
||||
},
|
||||
Empty: {
|
||||
description: 'Sense dades',
|
||||
},
|
||||
Icon: {
|
||||
icon: 'icona',
|
||||
},
|
||||
Text: {
|
||||
edit: 'Editar',
|
||||
copy: 'Copiar',
|
||||
copied: 'Copiat',
|
||||
expand: 'Ampliar',
|
||||
},
|
||||
PageHeader: {
|
||||
back: 'Enrere',
|
||||
},
|
||||
Form: {
|
||||
defaultValidateMessages: {
|
||||
default: 'Error de validació del camp ${label}',
|
||||
required: 'Introdueix ${label}',
|
||||
enum: '${label} ha de ser un de [${enum}]',
|
||||
whitespace: '${label} no pot ser un caràcter en blanc',
|
||||
date: {
|
||||
format: 'El format de la data de ${label} és invàlid',
|
||||
parse: '${label} no es pot convertir a cap data',
|
||||
invalid: '${label} és una data invàlida',
|
||||
},
|
||||
types: {
|
||||
string: typeTemplate,
|
||||
method: typeTemplate,
|
||||
array: typeTemplate,
|
||||
object: typeTemplate,
|
||||
number: typeTemplate,
|
||||
date: typeTemplate,
|
||||
boolean: typeTemplate,
|
||||
integer: typeTemplate,
|
||||
float: typeTemplate,
|
||||
regexp: typeTemplate,
|
||||
email: typeTemplate,
|
||||
url: typeTemplate,
|
||||
hex: typeTemplate,
|
||||
},
|
||||
string: {
|
||||
len: '${label} ha de ser de ${len} caràcters',
|
||||
min: '${label} ha de tenir com a mínim ${min} caràcters',
|
||||
max: '${label} ha de tenir com a màxim ${max} caràcters',
|
||||
range: '${label} ha d’estar entre ${min} i ${max} caràcters',
|
||||
},
|
||||
number: {
|
||||
len: '${label} ha de ser igual a ${len}',
|
||||
min: '${label} ha de tenir un valor mínim de ${min}',
|
||||
max: '${label} ha de tenir un valor màxim de ${max}',
|
||||
range: '${label} ha de tenir un valor entre ${min} i ${max}',
|
||||
},
|
||||
array: {
|
||||
len: 'La llargada de ${label} ha de ser de ${len}',
|
||||
min: 'La llargada de ${label} ha de ser com a mínim de ${min}',
|
||||
max: 'La llargada de ${label} ha de ser com a màxim de ${max}',
|
||||
range: 'La llargada de ${label} ha d’estar entre ${min} i ${max}',
|
||||
},
|
||||
pattern: {
|
||||
mismatch: '${label} no coincideix amb el patró ${pattern}',
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
export default localeValues;
|
||||
|
@ -31,7 +31,7 @@ A long list can be divided into several pages using `Pagination`, and only one p
|
||||
| pageSizeOptions | Specify the sizeChanger options | string\[] | \[`10`, `20`, `50`, `100`] | |
|
||||
| showLessItems | Show less page items | boolean | false | |
|
||||
| showQuickJumper | Determine whether you can jump to pages directly | boolean \| { goButton: ReactNode } | false | |
|
||||
| showSizeChanger | Determine whether to show `pageSize` select, it will be `true` when `total>=50` | boolean | - | |
|
||||
| showSizeChanger | Determine whether to show `pageSize` select, it will be true when `total > 50` | boolean | - | |
|
||||
| showTitle | Show page item's title | boolean | true | |
|
||||
| showTotal | To display the total number and range | function(total, range) | - | |
|
||||
| simple | Whether to use simple mode | boolean | - | |
|
||||
|
@ -32,7 +32,7 @@ cover: https://gw.alipayobjects.com/zos/alicdn/1vqv2bj68/Pagination.svg
|
||||
| pageSizeOptions | 指定每页可以显示多少条 | string\[] | \[`10`, `20`, `50`, `100`] | |
|
||||
| showLessItems | 是否显示较少页面内容 | boolean | false | |
|
||||
| showQuickJumper | 是否可以快速跳转至某页 | boolean \| { goButton: ReactNode } | false | |
|
||||
| showSizeChanger | 是否展示 `pageSize` 切换器,当 `total` 大于 `50` 时默认为 `true` | boolean | - | |
|
||||
| showSizeChanger | 是否展示 `pageSize` 切换器,当 `total` 大于 50 时默认为 true | boolean | - | |
|
||||
| showTitle | 是否显示原生 tooltip 页码提示 | boolean | true | |
|
||||
| showTotal | 用于显示数据总量和当前数据顺序 | function(total, range) | - | |
|
||||
| simple | 当添加该属性时,显示为简单分页 | boolean | - | |
|
||||
|
@ -86,6 +86,10 @@
|
||||
.@{select-prefix-cls}-selection-search-input {
|
||||
height: @select-height-without-border;
|
||||
}
|
||||
|
||||
&::after {
|
||||
line-height: @select-height-without-border;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -123,6 +127,7 @@
|
||||
.@{select-prefix-cls}-selector {
|
||||
height: @input-height;
|
||||
|
||||
&::after,
|
||||
.@{select-prefix-cls}-selection-item,
|
||||
.@{select-prefix-cls}-selection-placeholder {
|
||||
line-height: @input-height - 2 * @border-width-base;
|
||||
|
@ -100,7 +100,7 @@ describe('Table.pagination', () => {
|
||||
|
||||
wrapper.find('.ant-select-selector').simulate('mousedown');
|
||||
wrapper.find('.ant-select-item').last().simulate('click');
|
||||
expect(scrollTo).toHaveBeenCalledTimes(3);
|
||||
expect(scrollTo).toHaveBeenCalledTimes(2);
|
||||
});
|
||||
|
||||
it('fires change event', () => {
|
||||
@ -334,6 +334,24 @@ describe('Table.pagination', () => {
|
||||
expect(wrapper.render()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should call onChange when change pagination size', () => {
|
||||
const onChange = jest.fn();
|
||||
const wrapper = mount(
|
||||
createTable({
|
||||
pagination: {
|
||||
total: 200,
|
||||
showSizeChanger: true,
|
||||
},
|
||||
onChange,
|
||||
}),
|
||||
);
|
||||
wrapper.find('.ant-select-selector').simulate('mousedown');
|
||||
const dropdownWrapper = mount(wrapper.find('Trigger').instance().getComponent());
|
||||
dropdownWrapper.find('.ant-select-item-option').at(2).simulate('click');
|
||||
|
||||
expect(onChange).toBeCalledTimes(1)
|
||||
});
|
||||
|
||||
it('dynamic warning', () => {
|
||||
resetWarned();
|
||||
const errorSpy = jest.spyOn(console, 'error').mockImplementation(() => {});
|
||||
|
@ -72,9 +72,6 @@ const data = [
|
||||
|
||||
const SortableItem = sortableElement(props => <tr {...props} />);
|
||||
const SortableContainer = sortableContainer(props => <tbody {...props} />);
|
||||
const DragableBodyRow = ({ index, className, style, ...restProps }) => (
|
||||
<SortableItem index={restProps['data-row-key']} {...restProps} />
|
||||
);
|
||||
|
||||
class SortableTable extends React.Component {
|
||||
state = {
|
||||
@ -90,6 +87,13 @@ class SortableTable extends React.Component {
|
||||
}
|
||||
};
|
||||
|
||||
DraggableBodyRow = ({ className, style, ...restProps }) => {
|
||||
const { dataSource } = this.state;
|
||||
// function findIndex base on Table rowKey props and should always be a right array index
|
||||
const index = dataSource.findIndex(x => x.index === restProps['data-row-key']);
|
||||
return <SortableItem index={index} {...restProps} />;
|
||||
};
|
||||
|
||||
render() {
|
||||
const { dataSource } = this.state;
|
||||
const DraggableContainer = props => (
|
||||
@ -109,7 +113,7 @@ class SortableTable extends React.Component {
|
||||
components={{
|
||||
body: {
|
||||
wrapper: DraggableContainer,
|
||||
row: DragableBodyRow,
|
||||
row: this.DraggableBodyRow,
|
||||
},
|
||||
}}
|
||||
/>
|
||||
|
@ -7,11 +7,11 @@ title:
|
||||
|
||||
## zh-CN
|
||||
|
||||
集成 [react-resizable](https://github.com/STRML/react-resizable) 来实现可伸缩列。
|
||||
集成 [react-resizable](https://github.com/STRML/react-resizable) 来实现可伸缩列。如果有排序需要,可以通过[额外标记](https://codesandbox.io/s/zrj8xvyzxx)阻止触发排序。
|
||||
|
||||
## en-US
|
||||
|
||||
Implement resizable column by integrate with [react-resizable](https://github.com/STRML/react-resizable).
|
||||
Implement resizable column by integrate with [react-resizable](https://github.com/STRML/react-resizable). When sort needed, you can use [additional mark](https://codesandbox.io/s/zrj8xvyzxx) to prevent resize trigger sort.
|
||||
|
||||
```jsx
|
||||
import { Table } from 'antd';
|
||||
|
@ -75,37 +75,24 @@ export default function usePagination(
|
||||
}
|
||||
}
|
||||
|
||||
const refreshPagination = (current: number = 1) => {
|
||||
const refreshPagination = (current: number = 1, pageSize?: number) => {
|
||||
setInnerPagination({
|
||||
...mergedPagination,
|
||||
current,
|
||||
pageSize: pageSize || mergedPagination.pageSize,
|
||||
});
|
||||
};
|
||||
|
||||
const onInternalChange: PaginationProps['onChange'] = (...args) => {
|
||||
const [current] = args;
|
||||
refreshPagination(current);
|
||||
|
||||
onChange(current, args[1] || mergedPagination.pageSize!);
|
||||
|
||||
if (pagination && pagination.onChange) {
|
||||
pagination.onChange(...args);
|
||||
const onInternalChange: PaginationProps['onChange'] = (current, pageSize) => {
|
||||
const paginationPageSize = mergedPagination?.pageSize;
|
||||
if (pageSize && pageSize !== paginationPageSize) {
|
||||
current = 1;
|
||||
if (pagination && pagination.onShowSizeChange) pagination.onShowSizeChange(current, pageSize);
|
||||
}
|
||||
};
|
||||
if (pagination && pagination.onChange) pagination.onChange(current, pageSize);
|
||||
|
||||
const onInternalShowSizeChange: PaginationProps['onShowSizeChange'] = (...args) => {
|
||||
const [, pageSize] = args;
|
||||
setInnerPagination({
|
||||
...mergedPagination,
|
||||
current: 1,
|
||||
pageSize,
|
||||
});
|
||||
|
||||
onChange(1, pageSize);
|
||||
|
||||
if (pagination && pagination.onShowSizeChange) {
|
||||
pagination.onShowSizeChange(...args);
|
||||
}
|
||||
refreshPagination(current, pageSize);
|
||||
onChange(current, pageSize || paginationPageSize!);
|
||||
};
|
||||
|
||||
if (pagination === false) {
|
||||
@ -116,7 +103,6 @@ export default function usePagination(
|
||||
{
|
||||
...mergedPagination,
|
||||
onChange: onInternalChange,
|
||||
onShowSizeChange: onInternalShowSizeChange,
|
||||
},
|
||||
refreshPagination,
|
||||
];
|
||||
|
@ -17,8 +17,6 @@ Controlled mode lets parent nodes reflect the status of child nodes more intelli
|
||||
import React, { useState } from 'react';
|
||||
import { Tree } from 'antd';
|
||||
|
||||
const { TreeNode } = Tree;
|
||||
|
||||
const treeData = [
|
||||
{
|
||||
title: '0-0',
|
||||
|
@ -16,8 +16,6 @@ The most basic usage, tell you how to use checkable, selectable, disabled, defau
|
||||
```tsx
|
||||
import { Tree } from 'antd';
|
||||
|
||||
const { TreeNode } = Tree;
|
||||
|
||||
const treeData = [
|
||||
{
|
||||
title: 'parent 1',
|
||||
|
@ -17,8 +17,6 @@ To load data asynchronously when click to expand a treeNode.
|
||||
import React, { useState } from 'react';
|
||||
import { Tree } from 'antd';
|
||||
|
||||
const { TreeNode } = Tree;
|
||||
|
||||
interface DataNode {
|
||||
title: string;
|
||||
key: string;
|
||||
|
@ -53,6 +53,10 @@ antd use shallow compare of props to optimize performance. You should always pas
|
||||
|
||||
Try `defaultValue` or `onChange` to change `value`, and please read [React's documentation](https://facebook.github.io/react/docs/forms.html#controlled-components).
|
||||
|
||||
### Components are not vertically aligned when placed in single row.
|
||||
|
||||
Try [Space](https://ant.design/components/space/) component to make them aligned.
|
||||
|
||||
### antd overrides my global styles
|
||||
|
||||
Yes, antd is designed to develop a complete background application, we override some global styles for styling convenience, and it can't be removed now. More info at https://github.com/ant-design/ant-design/issues/4331 .
|
||||
|
@ -53,6 +53,10 @@ antd 内部会对 props 进行浅比较实现性能优化。当状态变更,
|
||||
|
||||
尝试使用 `defaultValue` 或 `onChange` 来改变 `value`,请参考 [React 的文档](https://reactjs.org/docs/forms.html#controlled-components)。
|
||||
|
||||
### 多个组件放一排时没有垂直对齐怎么办?
|
||||
|
||||
尝试使用 [Space](https://ant.design/components/space-cn/) 组件来使他们对齐。
|
||||
|
||||
### antd 覆盖了我的全局样式!
|
||||
|
||||
是的,antd 在设计的时候就是用来开发一个完整的应用的,为了方便,我们覆盖了一些全局样式,现在还不能移除,想要了解更多请追踪这个 issue:https://github.com/ant-design/ant-design/issues/4331 ,或者参考这个教程 [How to avoid modifying global styles?](docs/react/customize-theme#How-to-avoid-modifying-global-styles-?)
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "antd",
|
||||
"version": "4.4.1",
|
||||
"version": "4.4.2",
|
||||
"description": "An enterprise-class UI design language and React components implementation",
|
||||
"keywords": [
|
||||
"ant",
|
||||
|
@ -16,49 +16,49 @@ interface Recommend {
|
||||
|
||||
const LIST_CN: Recommend[] = [
|
||||
{
|
||||
title: '蚂蚁金服体验技术部招聘啦!',
|
||||
title: 'Ant Design 1.0 背后的故事:把艺术变成技术',
|
||||
description:
|
||||
'欢迎志同道合的你加入我们,一同在「引领全球体验科技,创造一流用户体验」的愿景指引下前行。',
|
||||
img: 'https://gw.alipayobjects.com/mdn/rms_08e378/afts/img/A*BPVATKTgfXwAAAAAAAAAAABkARQnAQ',
|
||||
href: 'https://www.yuque.com/uf44r1/wqrwsg/alwufg',
|
||||
'Ant Design 是一个设计体系,而 Ant Designers 是一群人。本文将讲讲 Ant Design 1.0 背后的故事,还原那些人、那些事。',
|
||||
img: 'https://gw.alipayobjects.com/mdn/rms_08e378/afts/img/A*h21tT45dgD8AAAAAAAAAAABkARQnAQ',
|
||||
href: 'https://zhuanlan.zhihu.com/p/104027273',
|
||||
popularize: true,
|
||||
},
|
||||
{
|
||||
title: '图表库 G2Plot 1.0 发布了!',
|
||||
title: 'Ant Design Pro V5 已经支持预览',
|
||||
description:
|
||||
'开箱即用图表库 G2Plot 1.0 发布,支持 40+ 图表类型,高级统计分析组件和复杂交互内置。',
|
||||
img: 'https://gw.alipayobjects.com/mdn/rms_08e378/afts/img/A*UsnLRpUZChQAAAAAAAAAAABkARQnAQ',
|
||||
href: 'https://zhuanlan.zhihu.com/p/113888415',
|
||||
'经过长时间的准备,Pro V5 已经基本完成。在新版本中我们进行了很多预设,对于数据流和布局更是进行了大刀阔斧的改进。',
|
||||
img: 'https://gw.alipayobjects.com/mdn/rms_08e378/afts/img/A*oY1sTrR5FswAAAAAAAAAAABkARQnAQ',
|
||||
href: 'https://zhuanlan.zhihu.com/p/141740103',
|
||||
},
|
||||
{
|
||||
title: 'Ant Design 暗黑模式设计解析',
|
||||
description: '让我们一起来看下,Ant Design 这一针对企业级的设计体系是如何设计暗黑模式的?',
|
||||
img: 'https://gw.alipayobjects.com/mdn/rms_08e378/afts/img/A*pxK_TboMzL8AAAAAAAAAAABkARQnAQ',
|
||||
href: 'https://zhuanlan.zhihu.com/p/112470365',
|
||||
title: 'JCD 驱动 - 复杂系统设计应对之道',
|
||||
description: '基于蚂蚁集团 CTO 线的业务土壤,我们探索出以 JCD 为核心的企业级产品设计思维,助力设计师在深耕业务上有章可循,有方法可用。',
|
||||
img: 'https://gw.alipayobjects.com/mdn/rms_08e378/afts/img/A*dGDxQZQ7ymoAAAAAAAAAAABkARQnAQ',
|
||||
href: 'https://zhuanlan.zhihu.com/p/103237648',
|
||||
},
|
||||
];
|
||||
|
||||
const LIST_EN: Recommend[] = [
|
||||
{
|
||||
title: 'Ant Experience Technology Department Wants You!',
|
||||
title: 'The Story behind Ant Design 1.0: Turn Art into Technology',
|
||||
description:
|
||||
'⚡️ Our vision is ’To Lead Global Experience Technology, to Create First-Class User Experience.‘. Welcome to join us.',
|
||||
img: 'https://gw.alipayobjects.com/mdn/rms_08e378/afts/img/A*Jd4sQJ9mmaQAAAAAAAAAAABkARQnAQ',
|
||||
href: 'https://www.yuque.com/uf44r1/wqrwsg/alwufg',
|
||||
'🌺 While Ant Design is a design system, Ant Designers are a group of people. This article will tell you the story behind Ant Design 1.0.',
|
||||
img: 'https://gw.alipayobjects.com/mdn/rms_08e378/afts/img/A*h21tT45dgD8AAAAAAAAAAABkARQnAQ',
|
||||
href: 'https://zhuanlan.zhihu.com/p/104027273',
|
||||
popularize: true,
|
||||
},
|
||||
{
|
||||
title: 'Chart Library G2Plot 1.0 has Come!',
|
||||
title: 'Ant Design Pro V5 has Supported Preview!',
|
||||
description:
|
||||
'📈 G2Plot 1.0 supports 40+ types of charts, including built-in statistic & analysis components and complicated interactions. Now it is ready for use out of the box.',
|
||||
img: 'https://gw.alipayobjects.com/mdn/rms_08e378/afts/img/A*UsnLRpUZChQAAAAAAAAAAABkARQnAQ',
|
||||
href: 'https://zhuanlan.zhihu.com/p/113888415',
|
||||
'📈 After a long time of preparation, Pro V5 has been basically completed. In this new version, we have done a lot of presets, and have made radical improvements to the data flow and layouts.',
|
||||
img: 'https://gw.alipayobjects.com/mdn/rms_08e378/afts/img/A*oY1sTrR5FswAAAAAAAAAAABkARQnAQ',
|
||||
href: 'https://zhuanlan.zhihu.com/p/141740103',
|
||||
},
|
||||
{
|
||||
title: 'Dark Theme of Ant Design',
|
||||
description: '🌃 Let us take a look at how to design the dark theme of Ant Design.',
|
||||
img: 'https://gw.alipayobjects.com/mdn/rms_08e378/afts/img/A*pxK_TboMzL8AAAAAAAAAAABkARQnAQ',
|
||||
href: 'https://zhuanlan.zhihu.com/p/112470365',
|
||||
title: 'Driven by JCD: How to Design Complicated Systems',
|
||||
description: '🏦 Based on the business practice of Ant Group CTO line, we have summed up a design thinking system of enterprise product, which is called JCD.',
|
||||
img: 'https://gw.alipayobjects.com/mdn/rms_08e378/afts/img/A*dGDxQZQ7ymoAAAAAAAAAAABkARQnAQ',
|
||||
href: 'https://zhuanlan.zhihu.com/p/103237648',
|
||||
},
|
||||
];
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user