From f94f50f326f99b76fc32e30881db4f7acfa27741 Mon Sep 17 00:00:00 2001 From: tanjinzhou <415800467@qq.com> Date: Wed, 11 Sep 2019 18:11:48 +0800 Subject: [PATCH] cr exxx to nxxx --- .../__tests__/__snapshots__/demo.test.js.snap | 7 +- components/form/FormItem.jsx | 31 +++++--- components/form/__tests__/label.test.js | 20 +++++ components/input/Group.jsx | 5 +- components/input/Input.jsx | 33 ++++++-- components/input/Password.js | 5 +- components/input/Search.jsx | 22 ++---- .../__tests__/__snapshots__/demo.test.js.snap | 2 +- components/input/demo/tooltip.md | 2 +- components/input/index.en-US.md | 15 +--- components/input/index.zh-CN.md | 15 +--- components/input/inputProps.js | 5 +- components/list/index.en-US.md | 2 +- components/list/index.jsx | 2 +- components/modal/ConfirmDialog.jsx | 3 +- components/modal/demo/confirm-router.md | 4 +- components/modal/index.en-US.md | 3 +- components/modal/index.zh-CN.md | 4 +- types/form/form.d.ts | 78 ++++++++++--------- types/input/input.d.ts | 4 + types/input/passward.d.ts | 9 +++ types/modal.d.ts | 4 + 22 files changed, 153 insertions(+), 122 deletions(-) create mode 100644 types/input/passward.d.ts diff --git a/components/empty/__tests__/__snapshots__/demo.test.js.snap b/components/empty/__tests__/__snapshots__/demo.test.js.snap index 0c922239a..e61d91ef3 100644 --- a/components/empty/__tests__/__snapshots__/demo.test.js.snap +++ b/components/empty/__tests__/__snapshots__/demo.test.js.snap @@ -92,12 +92,7 @@ exports[`renders ./components/empty/demo/config-provider.md correctly 1`] = `
-
-
-
No Data
-

No Data

-
-
+
diff --git a/components/form/FormItem.jsx b/components/form/FormItem.jsx index b0567deda..806fa076b 100644 --- a/components/form/FormItem.jsx +++ b/components/form/FormItem.jsx @@ -1,4 +1,3 @@ -import intersperse from 'intersperse'; import PropTypes from '../_util/vue-types'; import classNames from 'classnames'; import find from 'lodash/find'; @@ -21,6 +20,10 @@ import Icon from '../icon'; import { ConfigConsumerProps } from '../config-provider'; function noop() {} + +function intersperseSpace(list) { + return list.reduce((current, item) => [...current, ' ', item], []).slice(1); +} export const FormItemProps = { id: PropTypes.string, prefixCls: PropTypes.string, @@ -59,7 +62,6 @@ export default { mixins: [BaseMixin], props: initDefaultProps(FormItemProps, { hasFeedback: false, - prefixCls: 'ant-form', colon: true, }), inject: { @@ -83,8 +85,10 @@ export default { this.collectFormItemContext(this.$vnode.context, 'delete'); }, mounted() { + const { help, validateStatus } = this.$props; warning( - this.getControls(this.slotDefault, true).length <= 1, + this.getControls(this.slotDefault, true).length <= 1 || + (help !== undefined || validateStatus !== undefined), '`Form.Item` cannot generate `validateStatus` and `help` automatically, ' + 'while there are more than one `getFieldDecorator` in it.', ); @@ -118,13 +122,16 @@ export default { if (help === undefined && onlyControl) { const errors = this.getField().errors; if (errors) { - return intersperse( + return intersperseSpace( errors.map((e, index) => { - return isValidElement(e.message) - ? cloneElement(e.message, { key: index }) - : e.message; + let node = null; + if (isValidElement(e)) { + node = e; + } else if (isValidElement(e.message)) { + node = e.message; + } + return node ? cloneElement(node, { key: index }) : e.message; }), - ' ', ); } else { return ''; @@ -339,15 +346,15 @@ export default { if (!id) { return; } - const controls = document.querySelectorAll(`[id="${id}"]`); - if (controls.length !== 1) { + const formItemNode = this.$el; + const control = formItemNode.querySelector(`[id="${id}"]`); + if (control) { // Only prevent in default situation // Avoid preventing event in `label={link}`` if (typeof label === 'string') { e.preventDefault(); } - const control = this.$el.querySelector(`[id="${id}"]`); - if (control && control.focus) { + if (control.focus) { control.focus(); } } diff --git a/components/form/__tests__/label.test.js b/components/form/__tests__/label.test.js index afbdffd26..840dc13f9 100644 --- a/components/form/__tests__/label.test.js +++ b/components/form/__tests__/label.test.js @@ -3,6 +3,26 @@ import Form from '..'; import { asyncExpect } from '@/tests/utils'; describe('Form', () => { + // Mock of `querySelector` + const originQuerySelector = HTMLElement.prototype.querySelector; + HTMLElement.prototype.querySelector = function querySelector(str) { + const match = str.match(/^\[id=('|")(.*)('|")]$/); + const id = match && match[2]; + + // Use origin logic + if (id) { + const [input] = this.getElementsByTagName('input'); + if (input && input.id === id) { + return input; + } + } + + return originQuerySelector.call(this, str); + }; + + afterAll(() => { + HTMLElement.prototype.querySelector = originQuerySelector; + }); it('should remove duplicated user input colon', () => { const wrapper = mount({ render() { diff --git a/components/input/Group.jsx b/components/input/Group.jsx index c21290d75..362155a5f 100644 --- a/components/input/Group.jsx +++ b/components/input/Group.jsx @@ -1,12 +1,11 @@ +import PropTypes from '../_util/vue-types'; import { filterEmpty } from '../_util/props-util'; import { ConfigConsumerProps } from '../config-provider'; export default { name: 'AInputGroup', props: { - prefixCls: { - type: String, - }, + prefixCls: PropTypes.string, size: { validator(value) { return ['small', 'large', 'default'].includes(value); diff --git a/components/input/Input.jsx b/components/input/Input.jsx index 7f7bc6e42..c2f03294c 100644 --- a/components/input/Input.jsx +++ b/components/input/Input.jsx @@ -38,12 +38,12 @@ export default { data() { const { value, defaultValue } = this.$props; return { - stateValue: fixControlledValue(!hasProp(this, 'value') ? defaultValue : value), + stateValue: !hasProp(this, 'value') ? defaultValue : value, }; }, watch: { value(val) { - this.stateValue = fixControlledValue(val); + this.stateValue = val; }, }, mounted() { @@ -95,6 +95,21 @@ export default { if (!e.target.composing) { this.$emit('change.value', value); } + let event = e; + if (e.type === 'click' && this.$refs.input) { + // click clear icon + event = { ...e }; + event.target = this.$refs.input; + event.currentTarget = this.$refs.input; + const originalInputValue = this.$refs.input.value; + // change input value cause e.target.value should be '' when clear input + this.$refs.input.value = ''; + this.$emit('change', event); + this.$emit('input', event); + // reset input value + this.$refs.input.value = originalInputValue; + return; + } this.$emit('change', e); this.$emit('input', e); }, @@ -129,7 +144,7 @@ export default { let suffix = getComponentFromProp(this, 'suffix'); if (suffix || allowClear) { return ( - + {this.renderClearIcon(prefixCls)} {suffix} @@ -179,14 +194,18 @@ export default { return children; } let prefix = getComponentFromProp(this, 'prefix'); - prefix = prefix ? {prefix} : null; + prefix = prefix ? ( + + {prefix} + + ) : null; const affixWrapperCls = classNames(`${prefixCls}-affix-wrapper`, { [`${prefixCls}-affix-wrapper-sm`]: size === 'small', [`${prefixCls}-affix-wrapper-lg`]: size === 'large', }); return ( - + {prefix} {children} {suffix} @@ -201,13 +220,14 @@ export default { 'addonAfter', 'prefix', 'suffix', + 'allowClear', 'value', 'defaultValue', ]); const { stateValue, getInputClassName, handleKeyDown, handleChange, $listeners } = this; const inputProps = { domProps: { - value: stateValue, + value: fixControlledValue(stateValue), }, attrs: { ...otherProps, ...this.$attrs }, on: { @@ -218,6 +238,7 @@ export default { }, class: getInputClassName(prefixCls), ref: 'input', + key: 'ant-input', }; if ($listeners['change.value']) { inputProps.directives = [{ name: 'ant-input' }]; diff --git a/components/input/Password.js b/components/input/Password.js index 1da00f1d3..c7de5edec 100644 --- a/components/input/Password.js +++ b/components/input/Password.js @@ -2,9 +2,6 @@ import classNames from 'classnames'; import Input from './Input'; import Icon from '../icon'; import inputProps from './inputProps'; -import Button from '../button'; -import { cloneElement } from '../_util/vnode'; -import { getOptionProps, getComponentFromProp, isValidElement } from '../_util/props-util'; import PropTypes from '../_util/vue-types'; import BaseMixin from '../_util/BaseMixin'; @@ -47,7 +44,7 @@ export default { }, on: { [iconTrigger]: this.onChange, - onMouseDown: e => { + mousedown: e => { // Prevent focused state lost // https://github.com/ant-design/ant-design/issues/15173 e.preventDefault(); diff --git a/components/input/Search.jsx b/components/input/Search.jsx index 2b92a2f00..fe690d5a4 100644 --- a/components/input/Search.jsx +++ b/components/input/Search.jsx @@ -17,14 +17,6 @@ export default { }, props: { ...inputProps, - prefixCls: { - default: 'ant-input-search', - type: String, - }, - inputPrefixCls: { - default: 'ant-input', - type: String, - }, enterButton: PropTypes.oneOfType([PropTypes.bool, PropTypes.string, PropTypes.object]), }, inject: { @@ -52,13 +44,13 @@ export default { ); if (suffix) { - let cloneSuffix = suffix; - if (isValidElement(cloneSuffix) && !cloneSuffix.key) { - cloneSuffix = cloneElement(cloneSuffix, { - key: 'originSuffix', - }); - } - return [cloneSuffix, node]; + // let cloneSuffix = suffix; + // if (isValidElement(cloneSuffix) && !cloneSuffix.key) { + // cloneSuffix = cloneElement(cloneSuffix, { + // key: 'originSuffix', + // }); + // } + return [suffix, node]; } return node; diff --git a/components/input/__tests__/__snapshots__/demo.test.js.snap b/components/input/__tests__/__snapshots__/demo.test.js.snap index 5cf72c47b..771535ce0 100644 --- a/components/input/__tests__/__snapshots__/demo.test.js.snap +++ b/components/input/__tests__/__snapshots__/demo.test.js.snap @@ -10,7 +10,7 @@ exports[`renders ./components/input/demo/addon.md correctly 1`] = ` `; -exports[`renders ./components/input/demo/allowClear.md correctly 1`] = ``; +exports[`renders ./components/input/demo/allowClear.md correctly 1`] = ``; exports[`renders ./components/input/demo/autosize-textarea.md correctly 1`] = `
diff --git a/components/input/demo/tooltip.md b/components/input/demo/tooltip.md index 63a9f56e5..b2eb073f2 100644 --- a/components/input/demo/tooltip.md +++ b/components/input/demo/tooltip.md @@ -27,7 +27,7 @@ You can use the Input in conjunction with [Tooltip](/components/tooltip/) compon @change="onChange" @blur="onBlur" placeholder="Input a number" - maxLength="25" + :maxLength="25" style="width: 120px" /> diff --git a/components/input/index.en-US.md b/components/input/index.en-US.md index 9792dceb0..17204a602 100644 --- a/components/input/index.en-US.md +++ b/components/input/index.en-US.md @@ -68,21 +68,8 @@ Supports all props of `Input`. ```` -#### Input.Password +#### Input.Password (Added in 1.14.0) | Property | Description | Type | Default | | --- | --- | --- | --- | | visibilityToggle | Whether show toggle button | boolean | true | - -## FAQ - -### Why Input lose focus when change `prefix/suffix` - -When Input dynamic add or remove `prefix/suffix` will make Vue recreate the dom structure and new input will be not focused. -You can set an empty `` element to keep the dom structure: - -```jsx -const suffix = condition ? : ; - - -``` diff --git a/components/input/index.zh-CN.md b/components/input/index.zh-CN.md index 4f07b01b2..67193c773 100644 --- a/components/input/index.zh-CN.md +++ b/components/input/index.zh-CN.md @@ -69,20 +69,7 @@ ```` -#### Input.Password +#### Input.Password (1.14.0 中新增) | 参数 | 说明 | 类型 | 默认值 | | --- | --- | --- | --- | | visibilityToggle | 是否显示切换按钮 | boolean | true | - -## FAQ - -### 为什么我动态改变 `prefix/suffix` 时,Input 会失去焦点? - -当 Input 动态添加或者删除 `prefix/suffix` 时,Vue 会重新创建 DOM 结构而新的 input 是没有焦点的。 -你可以预设一个空的 `` 来保持 DOM 结构不变: - -```jsx -const suffix = condition ? : ; - - -``` diff --git a/components/input/inputProps.js b/components/input/inputProps.js index cf03b6afe..d63c358d9 100644 --- a/components/input/inputProps.js +++ b/components/input/inputProps.js @@ -1,8 +1,7 @@ import PropTypes from '../_util/vue-types'; export default { - prefixCls: { - type: String, - }, + prefixCls: PropTypes.string, + inputPrefixCls: PropTypes.string, defaultValue: [String, Number], value: [String, Number], placeholder: [String, Number], diff --git a/components/list/index.en-US.md b/components/list/index.en-US.md index 2e996f90e..1c735461c 100644 --- a/components/list/index.en-US.md +++ b/components/list/index.en-US.md @@ -10,13 +10,13 @@ | grid | The grid type of list. You can set grid to something like {gutter: 16, column: 4} | object | - | | header | List header renderer | string\|slot | - | | itemLayout | The layout of list, default is `horizontal`, If a vertical list is desired, set the itemLayout property to `vertical` | string | - | +| rowKey | Item's unique key, could be a string or function that returns a string | string\|Function(record):string | `key` | | loading | Shows a loading indicator while the contents of the list are being fetched | boolean\|[object](https://vue.ant.design/components/spin/#API) | false | | loadMore | Shows a load more content | string\|slot | - | | locale | i18n text including empty text | object | emptyText: 'No Data'
| | pagination | Pagination [config](https://vue.ant.design/components/pagination/#API), hide it by setting it to false | boolean \| object | false | | split | Toggles rendering of the split under the list item | boolean | true | | renderItem | Custom item renderer, slot="renderItem" and slot-scope="item, index" | (item, index) => vNode | | - | -| rowKey | Specify the key that will be used for uniquely identify each element | item => string\|number | | ### pagination diff --git a/components/list/index.jsx b/components/list/index.jsx index 54d8700d3..c68ba8022 100644 --- a/components/list/index.jsx +++ b/components/list/index.jsx @@ -224,7 +224,7 @@ const List = { childrenContent = grid ? {childrenList} : childrenList; } else if (!children.length && !isLoading) { const renderEmpty = - (this.configProvider.renderEmpty && this.configProvider.renderEmpty()) || + (this.configProvider.renderEmpty && this.configProvider.renderEmpty) || ConfigConsumerProps.renderEmpty; childrenContent = this.renderEmpty(prefixCls, renderEmpty); } diff --git a/components/modal/ConfirmDialog.jsx b/components/modal/ConfirmDialog.jsx index 0261a9b38..154a0b3b1 100644 --- a/components/modal/ConfirmDialog.jsx +++ b/components/modal/ConfirmDialog.jsx @@ -3,7 +3,6 @@ import Icon from '../icon'; import Dialog from './Modal'; import ActionButton from './ActionButton'; import { getConfirmLocale } from './locale'; -import { hasProp } from '../_util/props-util'; import warning from '../_util/warning'; export default { @@ -92,7 +91,7 @@ export default { >
- + {iconNode} {typeof props.title === 'function' ? props.title(h) : props.title} diff --git a/components/modal/demo/confirm-router.md b/components/modal/demo/confirm-router.md index 3d97b12ce..fcd0abd4f 100644 --- a/components/modal/demo/confirm-router.md +++ b/components/modal/demo/confirm-router.md @@ -20,7 +20,7 @@ import Button from '../../button' export default { methods: { showConfirm() { - const _self = this + const self = this for (let i = 0; i < 3; i += 1) { setTimeout(() => { this.$confirm({ @@ -32,7 +32,7 @@ export default { }, cancelText: 'Click to destroy all', onCancel() { - _self.destroyAll() + self.destroyAll() }, }); }, i * 500); diff --git a/components/modal/index.en-US.md b/components/modal/index.en-US.md index 93c76dadd..3b054f724 100644 --- a/components/modal/index.en-US.md +++ b/components/modal/index.en-US.md @@ -57,7 +57,8 @@ The properties of the object are follows: | closable | Whether a close (x) button is visible on top right of the modal dialog or not | boolean | `false` | | class | class of container | string | - | | content | Content | string\|vNode \|function(h) | - | -| iconType | Icon `type` of the Icon component | string | `question-circle` | +| icon | custom icon (`Added in 1.14.0`) | string\|()=>VNode | `` | +| iconType | Icon `type` of the Icon component (deperated after `1.14.0`) | string | `question-circle` | | keyboard | Whether support press esc to close | Boolean | true | | mask | Whether show mask or not. | Boolean | true | | maskClosable | Whether to close the modal dialog when the mask (area outside the modal) is clicked | Boolean | `false` | diff --git a/components/modal/index.zh-CN.md b/components/modal/index.zh-CN.md index 166aa6e11..b24cf7142 100644 --- a/components/modal/index.zh-CN.md +++ b/components/modal/index.zh-CN.md @@ -56,7 +56,9 @@ | closable | 是否显示右上角的关闭按钮 | boolean | `false` | | class | 容器类名 | string | - | | content | 内容 | string \|vNode \|function(h) | 无 | -| iconType | 图标 Icon 类型 | string | question-circle | +| icon | 自定义图标(1.14.0 新增) | string\|()=>VNode | `` | +| iconType | 图标类型(1.14.0 后废弃,请使用 `icon`) | string | `question-circle` | +| mask | 是否展示遮罩 | Boolean | true | | maskClosable | 点击蒙层是否允许关闭 | Boolean | `false` | | keyboard | 是否支持键盘esc关闭 | boolean | true | | okText | 确认按钮文字 | string | 确定 | diff --git a/types/form/form.d.ts b/types/form/form.d.ts index 62f7ab9cb..fd90c7b7d 100644 --- a/types/form/form.d.ts +++ b/types/form/form.d.ts @@ -16,34 +16,36 @@ export interface Field { export interface FieldValue { [fieldName: string]: any; } +/** dom-scroll-into-view 组件配置参数 */ +export type DomScrollIntoViewConfig = { + /** 是否和左边界对齐 */ + alignWithLeft?: boolean; + /** 是否和上边界对齐 */ + alignWithTop?: boolean; + /** 顶部偏移量 */ + offsetTop?: number; + /** 左侧偏移量 */ + offsetLeft?: number; + /** 底部偏移量 */ + offsetBottom?: number; + /** 右侧偏移量 */ + offsetRight?: number; + /** 是否允许容器水平滚动 */ + allowHorizontalScroll?: boolean; + /** 当内容可见时是否允许滚动容器 */ + onlyScrollIfNeeded?: boolean; +}; -export interface ValidateFieldOptions { - /** - * If true, every field will stop validation at first failed rule - * @default false - * @type boolean - */ +export type ValidateFieldsOptions = { + /** 所有表单域是否在第一个校验规则失败后停止继续校验 */ first?: boolean; - - /** - * Those fields will stop validation at first failed rule - * @type string[] - */ + /** 指定哪些表单域在第一个校验规则失败后停止继续校验 */ firstFields?: string[]; - - /** - * Should validate validated field again when validateTrigger is been triggered again - * @default false - * @type boolean - */ + /** 已经校验过的表单域,在 validateTrigger 再次被触发时是否再次校验 */ force?: boolean; - - /** - * Config scroll behavior of validateFieldsAndScroll - * @type object - */ - scroll?: object; -} + /** 定义 validateFieldsAndScroll 的滚动行为 */ + scroll?: DomScrollIntoViewConfig; +}; declare interface ValidationRule { /** @@ -211,7 +213,7 @@ export interface WrappedFormUtils { * Get the specified fields' values. If you don't specify a parameter, you will get all fields' values. * @type Funtion (Function([fieldNames: string[])) */ - getFieldsValue(fieldNames?: string[]): object; + getFieldsValue(fieldNames?: string[]): { [field: string]: any }; /** * Get the value of a field. @@ -262,13 +264,16 @@ export interface WrappedFormUtils { * @type Function */ validateFields( - fieldNames: string[], - options: ValidateFieldOptions, + fieldNames: Array, + options: ValidateFieldsOptions, callback: ValidateCallback, ): void; - validateFields(fieldNames: string[], callback: ValidateCallback): void; - validateFields(options: ValidateFieldOptions, callback: ValidateCallback): void; + validateFields(options: ValidateFieldsOptions, callback: ValidateCallback): void; + validateFields(fieldNames: Array, callback: ValidateCallback): void; + validateFields(fieldNames: Array, options: ValidateFieldsOptions): void; + validateFields(fieldNames: Array): void; validateFields(callback: ValidateCallback): void; + validateFields(options: ValidateFieldsOptions): void; validateFields(): void; /** @@ -277,13 +282,16 @@ export interface WrappedFormUtils { * @type Function */ validateFieldsAndScroll( - fieldNames?: string[], - options?: Object, - callback?: ValidateCallback, + fieldNames: Array, + options: ValidateFieldsOptions, + callback: ValidateCallback, ): void; - validateFieldsAndScroll(fieldNames?: string[], callback?: ValidateCallback): void; - validateFieldsAndScroll(options?: Object, callback?: ValidateCallback): void; - validateFieldsAndScroll(callback?: ValidateCallback): void; + validateFieldsAndScroll(options: ValidateFieldsOptions, callback: ValidateCallback): void; + validateFieldsAndScroll(fieldNames: Array, callback: ValidateCallback): void; + validateFieldsAndScroll(fieldNames: Array, options: ValidateFieldsOptions): void; + validateFieldsAndScroll(fieldNames: Array): void; + validateFieldsAndScroll(callback: ValidateCallback): void; + validateFieldsAndScroll(options: ValidateFieldsOptions): void; validateFieldsAndScroll(): void; } diff --git a/types/input/input.d.ts b/types/input/input.d.ts index cdeb12461..14e649abd 100644 --- a/types/input/input.d.ts +++ b/types/input/input.d.ts @@ -6,11 +6,13 @@ import { AntdComponent } from '../component'; import { InputGroup } from './input-group'; import { InputSearch } from './input-search'; import { TextArea } from './textarea'; +import { Passward } from './passward'; export declare class Input extends AntdComponent { static Group: typeof InputGroup; static Search: typeof InputSearch; static TextArea: typeof TextArea; + static Passward: typeof Passward; /** * The label text displayed after (on the right side of) the input field. @@ -74,4 +76,6 @@ export declare class Input extends AntdComponent { * @type string | number */ value: string | number; + + allowClear?: boolean; } diff --git a/types/input/passward.d.ts b/types/input/passward.d.ts new file mode 100644 index 000000000..78ccc3c70 --- /dev/null +++ b/types/input/passward.d.ts @@ -0,0 +1,9 @@ +// Project: https://github.com/vueComponent/ant-design-vue +// Definitions by: akki-jat +// Definitions: https://github.com/vueComponent/ant-design-vue/types + +import { AntdComponent } from '../component'; + +export declare class Passward extends AntdComponent { + visibilityToggle?: boolean; +} diff --git a/types/modal.d.ts b/types/modal.d.ts index 260e7efd4..6a416adae 100644 --- a/types/modal.d.ts +++ b/types/modal.d.ts @@ -48,6 +48,10 @@ export interface ModalOptions { */ iconType?: string; + icon?: string | Function; + + mask?: boolean; + /** * Whether support press esc to close * @default true