diff --git a/.circleci/config.yml b/.circleci/config.yml index ba80c848ee..9aa8c392ca 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -3,7 +3,7 @@ version: 2 references: container_config: &container_config docker: - - image: circleci/node:8 + - image: circleci/node:lts working_directory: ~/ant-design attach_workspace: &attach_workspace diff --git a/CHANGELOG.en-US.md b/CHANGELOG.en-US.md index e56612e52f..fe34bf9fc5 100644 --- a/CHANGELOG.en-US.md +++ b/CHANGELOG.en-US.md @@ -15,6 +15,23 @@ timeline: true --- +## 3.23.2 + +`2019-09-06` + +- 🐞 Fix `round` Button font size too large. [#18701](https://github.com/ant-design/ant-design/pull/18701) +- 🐞 Fix Descriptions warning with same key when bordered is true. [#18637](https://github.com/ant-design/ant-design/pull/18637) +- 🐞 Fix Drawer animation when `placement` is right and `mask` is false. [#18636](https://github.com/ant-design/ant-design/pull/18636) +- 🐞 Fix Icon that `component` and `children` prop should have priority over `type` prop. [#18592](https://github.com/ant-design/ant-design/pull/18592) +- 🐞 Fix Layout.Sider boundary values for max-width. [#18553](https://github.com/ant-design/ant-design/pull/18553) [@Nikitenkova](https://github.com/Nikitenkova) +- 🐞 Fix PageHeader that back icon can't coexist with breadcrumb. [#18691](https://github.com/ant-design/ant-design/pull/18691) +- 🗑Deprecated Select `inputValue` prop and use `searchValue` instead. [#18629](https://github.com/ant-design/ant-design/pull/18629) +- TypeScript + - 🐞 Fix type definition of `status` for Result. [#18445](https://github.com/ant-design/ant-design/pull/18445) + - 🐞 Fix type definition of `target` for Anchor.Link. [#18646](https://github.com/ant-design/ant-design/pull/18646) + - 🐞 Fix type definition of `transformFile` params for Upload. [#18671](https://github.com/ant-design/ant-design/pull/18671) + - 🐞 Fix type definition of `title` and `footer` for Table. [#18697](https://github.com/ant-design/ant-design/pull/18697) [@yoyo837](https://github.com/yoyo837) + ## 3.23.1 `2019-09-03` diff --git a/CHANGELOG.zh-CN.md b/CHANGELOG.zh-CN.md index c6571a54d1..1b25d53f0d 100644 --- a/CHANGELOG.zh-CN.md +++ b/CHANGELOG.zh-CN.md @@ -15,6 +15,23 @@ timeline: true --- +## 3.23.2 + +`2019-09-06` + +- 🐞 修复圆形按钮的字体大一号的问题。[#18701](https://github.com/ant-design/ant-design/pull/18701) +- 🐞 修复 Descriptions 带边框时控制台告警的问题。[#18637](https://github.com/ant-design/ant-design/pull/18637) +- 🐞 修复 Drawer 无遮罩从右边展开时的动画问题。[#18636](https://github.com/ant-design/ant-design/pull/18636) +- 🐞 修复 Icon 中 `component` 和 `children` 属性优先级低于 `type` 的问题。[#18592](https://github.com/ant-design/ant-design/pull/18592) +- 🐞 修复 Layout.Sider 的最大宽度的响应式断点值。[#18553](https://github.com/ant-design/ant-design/pull/18553) [@Nikitenkova](https://github.com/Nikitenkova) +- 🐞 修复 PageHeader 中返回图标与面包屑无法共存的问题。[#18691](https://github.com/ant-design/ant-design/pull/18691) +- 🗑 废弃 Select 的 `inputValue` 属性,请使用 `searchValue` 代替。[#18629](https://github.com/ant-design/ant-design/pull/18629) +- TypeScript + - 🐞 修复 Result 中 `status` 的类型定义。[#18445](https://github.com/ant-design/ant-design/pull/18445) + - 🐞 修复 Anchor.Link 中 `target` 的类型定义。[#18646](https://github.com/ant-design/ant-design/pull/18646) + - 🐞 修复 Upload 中 `transformFile` 函数的参数定义。[#18671](https://github.com/ant-design/ant-design/pull/18671) + - 🐞 修复 Table 中 `title` 和 `footer` 的类型定义。[#18697](https://github.com/ant-design/ant-design/pull/18697) [@yoyo837](https://github.com/yoyo837) + ## 3.23.1 `2019-09-03` diff --git a/components/anchor/__tests__/Anchor.test.js b/components/anchor/__tests__/Anchor.test.js index 65be9cfa2e..3cf43c755c 100644 --- a/components/anchor/__tests__/Anchor.test.js +++ b/components/anchor/__tests__/Anchor.test.js @@ -279,10 +279,13 @@ describe('Anchor Render', () => { let dateNowMock; function dataNowMockFn() { - return jest - .spyOn(Date, 'now') - .mockImplementationOnce(() => 0) - .mockImplementationOnce(() => 1000); + let start = 0; + + const handler = () => { + return (start += 1000); + }; + + return jest.spyOn(Date, 'now').mockImplementation(handler); } dateNowMock = dataNowMockFn(); diff --git a/components/button/style/mixin.less b/components/button/style/mixin.less index d290be92c8..6e34f138f0 100644 --- a/components/button/style/mixin.less +++ b/components/button/style/mixin.less @@ -225,10 +225,10 @@ } // round button .btn-round(@btnClassName: btn) { - .button-size(@btn-circle-size; 0 @btn-circle-size / 2; @font-size-base + 2px; @btn-circle-size); + .button-size(@btn-circle-size; 0 @btn-circle-size / 2; @font-size-base; @btn-circle-size); &.@{btnClassName}-lg { .button-size( - @btn-circle-size-lg; 0 @btn-circle-size-lg / 2; @btn-font-size-lg + 2px; @btn-circle-size-lg + @btn-circle-size-lg; 0 @btn-circle-size-lg / 2; @btn-font-size-lg; @btn-circle-size-lg ); } &.@{btnClassName}-sm { diff --git a/components/descriptions/demo/size.md b/components/descriptions/demo/size.md index d37fd7dba3..3d7db86ddc 100644 --- a/components/descriptions/demo/size.md +++ b/components/descriptions/demo/size.md @@ -38,7 +38,7 @@ class Demo extends React.Component {

- + Cloud Database Prepaid 18:00:00 @@ -61,7 +61,7 @@ class Demo extends React.Component {

- + Cloud Database Prepaid 18:00:00 diff --git a/components/icon/__tests__/__snapshots__/index.test.js.snap b/components/icon/__tests__/__snapshots__/index.test.js.snap new file mode 100644 index 0000000000..8036fa6df7 --- /dev/null +++ b/components/icon/__tests__/__snapshots__/index.test.js.snap @@ -0,0 +1,426 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Icon \`component\` prop can access to svg defs if has children 1`] = ` + + + +`; + +exports[`Icon should give warning and render {null} 1`] = ` + +`; + +exports[`Icon should render to a ... 1`] = ` + + + +`; + +exports[`Icon should support basic usage 1`] = ` +
+ + + + + + + + + + + + + + + +
+`; + +exports[`Icon should support config global two-tone primary color 1`] = ` + + + +`; + +exports[`Icon should support older usage 1`] = ` +
+ + + + + + + + + + + + +
+`; + +exports[`Icon should support pass svg paths as children 1`] = ` + + + +`; + +exports[`Icon should support svg react component 1`] = ` + + + +`; + +exports[`Icon should support two-tone icon 1`] = ` + + + +`; + +exports[`Icon support render svg as component 1`] = ` + + + +`; + +exports[`Icon.createFromIconfontCN() should support iconfont.cn 1`] = ` +
+ + + + + + + + + +
+`; diff --git a/components/icon/__tests__/index.test.js b/components/icon/__tests__/index.test.js new file mode 100644 index 0000000000..cd56970a58 --- /dev/null +++ b/components/icon/__tests__/index.test.js @@ -0,0 +1,254 @@ +import React from 'react'; +import { render, mount } from 'enzyme'; +import ReactIcon from '@ant-design/icons-react'; +import Icon from '..'; +import Tooltip from '../../tooltip'; +import { getThemeFromTypeName, withThemeSuffix } from '../utils'; +import mountTest from '../../../tests/shared/mountTest'; + +describe('Icon', () => { + mountTest(Icon); + + it('should render to a ...', () => { + const wrapper = render(); + expect(wrapper).toMatchSnapshot(); + }); + + it('should support basic usage', () => { + const wrapper = render( +
+ + + + + +
, + ); + expect(wrapper).toMatchSnapshot(); + }); + + it('should support older usage', () => { + const wrapper = render( +
+ + + + +
, + ); + expect(wrapper).toMatchSnapshot(); + }); + + it('should support two-tone icon', () => { + const wrapper = render(); + expect(wrapper).toMatchSnapshot(); + }); + + it('should support config global two-tone primary color', () => { + const colors = ReactIcon.getTwoToneColors(); + Icon.setTwoToneColor('#1890ff'); + expect(Icon.getTwoToneColor()).toBe('#1890ff'); + const wrapper = render(); + expect(wrapper).toMatchSnapshot(); + ReactIcon.setTwoToneColors(colors); + }); + + it('should support pass svg paths as children', () => { + const wrapper = render( + + Cool Home + + , + ); + expect(wrapper).toMatchSnapshot(); + }); + + it('should give warning and render {null}', () => { + const wrapper = render(); + expect(wrapper).toMatchSnapshot(); + }); + + it('should support wrapped by Tooltip', () => { + const onVisibleChange = jest.fn(); + const wrapper = mount( + + + , + ); + expect(wrapper.find('i')).toHaveLength(1); + const icon = wrapper.find('i').at(0); + icon.simulate('mouseenter'); + expect(onVisibleChange).toHaveBeenCalledWith(true); + expect(wrapper.instance().tooltip.props.visible).toBe(true); + + icon.simulate('mouseleave'); + expect(onVisibleChange).toHaveBeenCalledWith(false); + expect(wrapper.instance().tooltip.props.visible).toBe(false); + }); + + it('should support custom usage of children', () => { + expect(() => { + render(&E648); + }).not.toThrow(); + }); + + it('support render svg as component', () => { + const renderSvg = () => ( + + ); + const SvgIcon = props => ; + + expect(mount().render()).toMatchSnapshot(); + }); + + describe('warning on conflicting theme', () => { + let errorSpy; + beforeEach(() => { + errorSpy = jest.spyOn(console, 'error').mockImplementation(() => {}); + }); + + afterEach(() => { + errorSpy.mockRestore(); + }); + + it('does not warn', () => { + mount(); + expect(errorSpy).not.toHaveBeenCalled(); + }); + + it('warns', () => { + mount(); + expect(errorSpy).toHaveBeenCalledWith( + "Warning: [antd: Icon] The icon name 'clock-circle-o' already specify a theme 'outlined', the 'theme' prop 'filled' will be ignored.", + ); + }); + }); + + describe('`component` prop', () => { + it('can access to svg defs if has children', () => { + const wrapper = render( + ( + + + + + + + + {React.Children.map(svgProps.children, child => + React.cloneElement( + child, + child.type === 'path' ? { fill: 'scriptUrl(#gradient)' } : {}, + ), + )} + + )} + > + Cool Home + + , + ); + expect(wrapper).toMatchSnapshot(); + }); + }); + + it('should support svg react component', () => { + const SvgComponent = props => ( + + Custom Svg + + + ); + + const wrapper = render( + + Cool Home + + , + ); + expect(wrapper).toMatchSnapshot(); + }); +}); + +describe('Icon.createFromIconfontCN()', () => { + const IconFont = Icon.createFromIconfontCN({ + scriptUrl: '//at.alicdn.com/t/font_8d5l8fzk5b87iudi.js', + }); + + it('should support iconfont.cn', () => { + const wrapper = render( +
+ + + +
, + ); + expect(wrapper).toMatchSnapshot(); + }); +}); + +describe('utils', () => { + it('getThemeFromTypeName() should work', () => { + const testCases = [ + 'check-circle', + 'check-circle-o', + 'check-circle-fill', + 'check-circle-twotone', + ]; + const result = testCases.map(type => getThemeFromTypeName(type)); + expect(result).toEqual([null, 'outlined', 'filled', 'twoTone']); + }); + + it('withThemeSuffix() should work', () => { + const testCases = [ + { type: 'home', theme: 'filled' }, + { type: 'home', theme: 'outlined' }, + { type: 'home', theme: 'twoTone' }, + { type: 'home', theme: 'This-is-the-secret' }, + { type: 'home-o', theme: 'filled' }, + { type: 'home-fill', theme: 'outlined' }, + { type: 'home-o', theme: 'twoTone' }, + { type: 'home-o', theme: 'This-is-the-secret' }, + ]; + const result = testCases.map(({ type, theme }) => withThemeSuffix(type, theme)); + expect(result).toEqual([ + 'home-fill', + 'home-o', + 'home-twotone', + 'home', + 'home-o-fill', + 'home-fill-o', + 'home-o-twotone', + 'home-o', + ]); + }); + + it('should report an error when there are deprecated typos in icon names', () => { + const errorSpy = jest.spyOn(console, 'error').mockImplementation(() => {}); + render(); + expect(errorSpy).toHaveBeenLastCalledWith( + "Warning: [antd: Icon] Icon 'interation' was a typo and is now deprecated, please use 'interaction' instead.", + ); + render(); + expect(errorSpy).toHaveBeenLastCalledWith( + "Warning: [antd: Icon] Icon 'cross' was a typo and is now deprecated, please use 'close' instead.", + ); + render(); + expect(errorSpy).toHaveBeenLastCalledWith( + "Warning: [antd: Icon] Icon 'canlendar' was a typo and is now deprecated, please use 'calendar' instead.", + ); + render(); + expect(errorSpy).toHaveBeenLastCalledWith( + "Warning: [antd: Icon] Icon 'colum-height' was a typo and is now deprecated, please use 'column-height' instead.", + ); + expect(errorSpy).toHaveBeenCalledTimes(4); + errorSpy.mockRestore(); + }); +}); diff --git a/components/icon/index.en-US.md b/components/icon/index.en-US.md index a5d7634a0d..d5c521aaa2 100644 --- a/components/icon/index.en-US.md +++ b/components/icon/index.en-US.md @@ -145,7 +145,7 @@ ReactDOM.render(, mountNode); The following properties are available for the component: -| Property | Description | Type | Default | Version | +| Property | Description | Type | Readonly | Version | | --- | --- | --- | --- | --- | | width | The width of the `svg` element | string \| number | '1em' | 3.10.0 | | height | The height of the `svg` element | string \| number | '1em' | 3.10.0 | diff --git a/components/page-header/__tests__/index.test.js b/components/page-header/__tests__/index.test.js index 8484c7ef21..4e7c576ee0 100644 --- a/components/page-header/__tests__/index.test.js +++ b/components/page-header/__tests__/index.test.js @@ -67,7 +67,7 @@ describe('PageHeader', () => { expect(wrapper).toMatchSnapshot(); }); - it('breadcrumbs and back icon can only have one', () => { + it('breadcrumbs and back icon can coexist', () => { const routes = [ { path: 'index', @@ -82,10 +82,10 @@ describe('PageHeader', () => { breadcrumbName: 'Third-level Menu', }, ]; - const wrapper = mount( true} breadcrumb={{ routes }} />); - expect(wrapper.find('.ant-breadcrumb')).toHaveLength(0); + const wrapper = mount(); + expect(wrapper.find('.ant-breadcrumb')).toHaveLength(1); - wrapper.setProps({ onBack: undefined }); + wrapper.setProps({ onBack: () => {} }); expect(wrapper.find('.ant-breadcrumb')).toHaveLength(1); }); }); diff --git a/components/page-header/index.tsx b/components/page-header/index.tsx index da3ace5c62..8f08ab02f0 100644 --- a/components/page-header/index.tsx +++ b/components/page-header/index.tsx @@ -8,7 +8,6 @@ import Breadcrumb, { BreadcrumbProps } from '../breadcrumb'; import Avatar, { AvatarProps } from '../avatar'; import TransButton from '../_util/transButton'; import LocaleReceiver from '../locale-provider/LocaleReceiver'; -import warning from '../_util/warning'; export interface PageHeaderProps { backIcon?: React.ReactNode; @@ -58,23 +57,6 @@ const renderBreadcrumb = (breadcrumb: BreadcrumbProps) => { return ; }; -const renderHeader = ( - breadcrumb: PageHeaderProps['breadcrumb'], - { backIcon, onBack }: PageHeaderProps, -) => { - // by design,Bread crumbs and back icon can only have one - if (backIcon && onBack) { - if (breadcrumb && breadcrumb.routes) { - warning(false, 'page-header', 'breadcrumbs and back icon can only have one'); - } - return null; - } - if (breadcrumb && breadcrumb.routes) { - return renderBreadcrumb(breadcrumb); - } - return null; -}; - const renderTitle = (prefixCls: string, props: PageHeaderProps) => { const { title, avatar, subTitle, tags, extra, backIcon, onBack } = props; const headingPrefixCls = `${prefixCls}-heading`; @@ -118,7 +100,7 @@ const PageHeader: React.SFC = props => ( } = props; const prefixCls = getPrefixCls('page-header', customizePrefixCls); - const breadcrumbDom = renderHeader(breadcrumb, props); + const breadcrumbDom = breadcrumb && breadcrumb.routes ? renderBreadcrumb(breadcrumb) : null; const className = classnames(prefixCls, customizeClassName, { 'has-breadcrumb': breadcrumbDom, 'has-footer': footer, diff --git a/components/result/index.tsx b/components/result/index.tsx index e5f6621065..de26295fbc 100644 --- a/components/result/index.tsx +++ b/components/result/index.tsx @@ -31,7 +31,7 @@ export type ResultStatusType = ExceptionStatusType | keyof typeof IconMap; export interface ResultProps { icon?: React.ReactNode; - status: ResultStatusType; + status?: ResultStatusType; title?: React.ReactNode; subTitle?: React.ReactNode; extra?: React.ReactNode; @@ -53,7 +53,7 @@ const ExceptionStatus = Object.keys(ExceptionMap); const renderIcon = (prefixCls: string, { status, icon }: ResultProps) => { const className = classnames(`${prefixCls}-icon`); - if (ExceptionStatus.includes(status)) { + if (ExceptionStatus.includes(status as ResultStatusType)) { const SVGComponent = ExceptionMap[status as ExceptionStatusType]; return (
diff --git a/components/steps/style/index.less b/components/steps/style/index.less index e5619f1d61..fdb028b4c1 100644 --- a/components/steps/style/index.less +++ b/components/steps/style/index.less @@ -148,7 +148,7 @@ } // ===================== Clickable ===================== -.@{steps-prefix-cls}:not(.@{steps-prefix-cls}-navigation) .@{steps-prefix-cls}-item { +.@{steps-prefix-cls} .@{steps-prefix-cls}-item { &:not(.@{steps-prefix-cls}-item-active) { & > .@{steps-prefix-cls}-item-container[role='button'] { cursor: pointer; diff --git a/components/table/interface.tsx b/components/table/interface.tsx index 5022f4ead2..cc2d00293a 100644 --- a/components/table/interface.tsx +++ b/components/table/interface.tsx @@ -183,8 +183,8 @@ export interface TableProps { useFixedHeader?: boolean; bordered?: boolean; showHeader?: boolean; - footer?: (currentPageData: Object[]) => React.ReactNode; - title?: (currentPageData: Object[]) => React.ReactNode; + footer?: (currentPageData: T[]) => React.ReactNode; + title?: (currentPageData: T[]) => React.ReactNode; scroll?: { x?: boolean | number | string; y?: boolean | number | string }; childrenColumnName?: string; bodyStyle?: React.CSSProperties; diff --git a/components/upload/interface.tsx b/components/upload/interface.tsx index 45ad40fc71..ac6ffe7491 100755 --- a/components/upload/interface.tsx +++ b/components/upload/interface.tsx @@ -54,7 +54,7 @@ export type UploadListType = 'text' | 'picture' | 'picture-card'; type PreviewFileHandler = (file: File | Blob) => PromiseLike; type TransformFileHandler = ( - file: UploadFile, + file: RcFile, ) => string | Blob | File | PromiseLike; export interface UploadProps { diff --git a/docs/spec/work-with-us.zh-CN.md b/docs/spec/work-with-us.zh-CN.md index b739184b2a..203dbd3a12 100644 --- a/docs/spec/work-with-us.zh-CN.md +++ b/docs/spec/work-with-us.zh-CN.md @@ -6,41 +6,28 @@ title: 加入我们 我们(蚂蚁金服体验技术部)是一支兼具设计视角和工程视角的团队,服务蚂蚁金服上百个中后台系统,主打产品 Ant Design 服务全球 100 万设计师和工程师,是西湖区学院路西侧最具影响力的设计语言。欢迎来这里和我们一起打造优雅高效的人机设计/研发体系。 -## ADI(Artificial Design Intelligence) 工程师 - -简历和作品集请投递:lindong.lld#alipay.com - -> 注明简历来自 ant.design 官网 - -- 岗位级别:P7/P8 -- 岗位地点:杭州 -- 岗位要求: - - 有良好的工程师背景,善于学习和使用各类工具、框架解决研发问题; - - 对人工智能应用在设计行业,有坚定的信心和意愿; - - 已经有相关实践工作,优先考虑。 -- 岗位职责: - - 负责 Ant Design 工具体系和智能设计的研发,并配合团队成员进行商业化实践,把设计做成业务; - - 组建和培养有梯度的研发团队。 - ## UI/UE 设计师 简历和作品集请投递:lindong.lld#alipay.com > 注明简历来自 ant.design 官网 -- 岗位级别:P6/P7 +- 岗位级别:P6/P7/P8 - 岗位地点:杭州 - 岗位要求: - - 至少 2-3 年的工作经验,扎实设计功底; + - 至少 3-5 年的工作经验,扎实设计功底; - 抽象能力强,善于透过表象找本质; - 沟通能力佳,善于自我管理; - 有企业级设计实战经验,加分; + - 有数据驱动的增长设计实践,加分; - 深度理解 SAP、Salesforce、Google 等设计体系,能提出自己独到见解并落实到实践中,加加加分。 - 岗位职责: - - 参与[蚂蚁金融科技](https://tech.antfin.com/)、区块链、人工智能等企业级产品的设计工作; - - 参与[语雀](https://www.yuque.com/)、[云凤蝶](https://www.yunfengdie.com/)、K12/中小学(支付宝搜索:小钱袋)等创新产品的设计工作; + - 参与[蚂蚁金融科技](https://tech.antfin.com/)、[区块链](https://tech.antfin.com/blockchain)、人工智能等企业级产品的设计工作; + - 参与[语雀](https://www.yuque.com/)、[云凤蝶](https://www.yunfengdie.com/)等创新产品的设计工作; - 参与 Ant Design 的打磨,将其建设成全球卓越的设计体系。 + - 参与 AntV 的打磨,将其建设成全球一流的数据可视化体系。 - One More Thing ❤️ : + - 你们总是为世界带去美好,但总是忘却你们也需要美好。我们正在努力打造 [🍳 Kitchen:一款为设计师提效的 Sketch 工具集](https://kitchen.alipay.com/)、[语雀画板](https://yuque.com/) 等专属设计师的产品,让设计真正变成财富。期待志同道合的你,一道给设计行业带来「微小而美好的改变」。 ## 前端工程师 @@ -60,3 +47,19 @@ title: 加入我们 - 岗位职责: - 负责 Ant Design 前端基础设施研发。 - 负责中后台设计/前端工具体系建设。 + +## ADI(Artificial Design Intelligence) 工程师 + +简历和作品集请投递:lindong.lld#alipay.com + +> 注明简历来自 ant.design 官网 + +- 岗位级别:P7/P8 +- 岗位地点:杭州 +- 岗位要求: + - 有良好的工程师背景,善于学习和使用各类工具、框架解决研发问题; + - 对人工智能应用在设计行业,有坚定的信心和意愿; + - 已经有相关实践工作,优先考虑。 +- 岗位职责: + - 负责 Ant Design 工具体系和智能设计的研发,并配合团队成员进行商业化实践,把设计做成业务; + - 组建和培养有梯度的研发团队。