Merge remote-tracking branch 'origin/feat-vue3' into next

pull/3067/head
tangjinzhou 2020-10-27 23:47:20 +08:00
commit 1e1a1bd8a8
14 changed files with 162 additions and 69 deletions

View File

@ -24,6 +24,7 @@
<h2 align="center">Backers</h2>
<p align="center">
<a href="https://github.com/chuzhixin/vue-admin-beautiful" target="_blank"><img width="64" style="border-radius: 50%;" src="https://gitee.com/chu1204505056/image/raw/master/vue-admin-beautiful.png" title="vue-admin-beautiful"></a>
<a href="https://github.com/limichange" target="_blank"><img width="64" style="border-radius: 50%;" src="https://avatars0.githubusercontent.com/u/1947344?s=400&v=4" title="limichange donation total 24$ by qq from 2018.9"></a>
<a href="https://opencollective.com/ant-design-vue/backer/0/website" target="_blank"><img src="https://opencollective.com/ant-design-vue/backer/0/avatar.svg"></a>
<a href="https://opencollective.com/ant-design-vue/backer/1/website" target="_blank"><img src="https://opencollective.com/ant-design-vue/backer/1/avatar.svg"></a>

View File

@ -105,7 +105,7 @@ Become a sponsor and get your logo on our README on Github with a link to your s
Support us with a monthly donation and help us continue our activities. [[Become a backer](https://opencollective.com/ant-design-vue#backer)]
<a href="https://opencollective.com/ant-design-vue/backer/0/website" target="_blank"><img src="https://opencollective.com/ant-design-vue/backer/0/avatar.svg"></a> <a href="https://opencollective.com/ant-design-vue/backer/1/website" target="_blank"><img src="https://opencollective.com/ant-design-vue/backer/1/avatar.svg"></a> <a href="https://opencollective.com/ant-design-vue/backer/2/website" target="_blank"><img src="https://opencollective.com/ant-design-vue/backer/2/avatar.svg"></a> <a href="https://opencollective.com/ant-design-vue/backer/3/website" target="_blank"><img src="https://opencollective.com/ant-design-vue/backer/3/avatar.svg"></a> <a href="https://opencollective.com/ant-design-vue/backer/4/website" target="_blank"><img src="https://opencollective.com/ant-design-vue/backer/4/avatar.svg"></a> <a href="https://opencollective.com/ant-design-vue/backer/5/website" target="_blank"><img src="https://opencollective.com/ant-design-vue/backer/5/avatar.svg"></a> <a href="https://opencollective.com/ant-design-vue/backer/6/website" target="_blank"><img src="https://opencollective.com/ant-design-vue/backer/6/avatar.svg"></a> <a href="https://opencollective.com/ant-design-vue/backer/7/website" target="_blank"><img src="https://opencollective.com/ant-design-vue/backer/7/avatar.svg"></a> <a href="https://opencollective.com/ant-design-vue/backer/8/website" target="_blank"><img src="https://opencollective.com/ant-design-vue/backer/8/avatar.svg"></a> <a href="https://opencollective.com/ant-design-vue/backer/9/website" target="_blank"><img src="https://opencollective.com/ant-design-vue/backer/9/avatar.svg"></a> <a href="https://opencollective.com/ant-design-vue/backer/10/website" target="_blank"><img src="https://opencollective.com/ant-design-vue/backer/10/avatar.svg"></a>
<a href="https://github.com/chuzhixin/vue-admin-beautiful" target="_blank"><img width="64" style="border-radius: 50%;" src="https://gitee.com/chu1204505056/image/raw/master/vue-admin-beautiful.png" title="vue-admin-beautiful"></a> <a href="https://opencollective.com/ant-design-vue/backer/0/website" target="_blank"><img src="https://opencollective.com/ant-design-vue/backer/0/avatar.svg"></a> <a href="https://opencollective.com/ant-design-vue/backer/1/website" target="_blank"><img src="https://opencollective.com/ant-design-vue/backer/1/avatar.svg"></a> <a href="https://opencollective.com/ant-design-vue/backer/2/website" target="_blank"><img src="https://opencollective.com/ant-design-vue/backer/2/avatar.svg"></a> <a href="https://opencollective.com/ant-design-vue/backer/3/website" target="_blank"><img src="https://opencollective.com/ant-design-vue/backer/3/avatar.svg"></a> <a href="https://opencollective.com/ant-design-vue/backer/4/website" target="_blank"><img src="https://opencollective.com/ant-design-vue/backer/4/avatar.svg"></a> <a href="https://opencollective.com/ant-design-vue/backer/5/website" target="_blank"><img src="https://opencollective.com/ant-design-vue/backer/5/avatar.svg"></a> <a href="https://opencollective.com/ant-design-vue/backer/6/website" target="_blank"><img src="https://opencollective.com/ant-design-vue/backer/6/avatar.svg"></a> <a href="https://opencollective.com/ant-design-vue/backer/7/website" target="_blank"><img src="https://opencollective.com/ant-design-vue/backer/7/avatar.svg"></a> <a href="https://opencollective.com/ant-design-vue/backer/8/website" target="_blank"><img src="https://opencollective.com/ant-design-vue/backer/8/avatar.svg"></a> <a href="https://opencollective.com/ant-design-vue/backer/9/website" target="_blank"><img src="https://opencollective.com/ant-design-vue/backer/9/avatar.svg"></a> <a href="https://opencollective.com/ant-design-vue/backer/10/website" target="_blank"><img src="https://opencollective.com/ant-design-vue/backer/10/avatar.svg"></a>
## Patreon

View File

@ -99,7 +99,7 @@ Become a sponsor and get your logo on our README on Github with a link to your s
Support us with a monthly donation and help us continue our activities. [[Become a backer](https://opencollective.com/ant-design-vue#backer)]
<a href="https://opencollective.com/ant-design-vue/backer/0/website" target="_blank"><img src="https://opencollective.com/ant-design-vue/backer/0/avatar.svg"></a> <a href="https://opencollective.com/ant-design-vue/backer/1/website" target="_blank"><img src="https://opencollective.com/ant-design-vue/backer/1/avatar.svg"></a> <a href="https://opencollective.com/ant-design-vue/backer/2/website" target="_blank"><img src="https://opencollective.com/ant-design-vue/backer/2/avatar.svg"></a> <a href="https://opencollective.com/ant-design-vue/backer/3/website" target="_blank"><img src="https://opencollective.com/ant-design-vue/backer/3/avatar.svg"></a> <a href="https://opencollective.com/ant-design-vue/backer/4/website" target="_blank"><img src="https://opencollective.com/ant-design-vue/backer/4/avatar.svg"></a> <a href="https://opencollective.com/ant-design-vue/backer/5/website" target="_blank"><img src="https://opencollective.com/ant-design-vue/backer/5/avatar.svg"></a> <a href="https://opencollective.com/ant-design-vue/backer/6/website" target="_blank"><img src="https://opencollective.com/ant-design-vue/backer/6/avatar.svg"></a> <a href="https://opencollective.com/ant-design-vue/backer/7/website" target="_blank"><img src="https://opencollective.com/ant-design-vue/backer/7/avatar.svg"></a> <a href="https://opencollective.com/ant-design-vue/backer/8/website" target="_blank"><img src="https://opencollective.com/ant-design-vue/backer/8/avatar.svg"></a> <a href="https://opencollective.com/ant-design-vue/backer/9/website" target="_blank"><img src="https://opencollective.com/ant-design-vue/backer/9/avatar.svg"></a> <a href="https://opencollective.com/ant-design-vue/backer/10/website" target="_blank"><img src="https://opencollective.com/ant-design-vue/backer/10/avatar.svg"></a><a href="https://opencollective.com/ant-design-vue/backer/9/website" target="_blank"><img src="https://opencollective.com/ant-design-vue/backer/9/avatar.svg"></a>
<a href="https://github.com/chuzhixin/vue-admin-beautiful" target="_blank"><img width="64" style="border-radius: 50%;" src="https://gitee.com/chu1204505056/image/raw/master/vue-admin-beautiful.png" title="vue-admin-beautiful"></a> <a href="https://opencollective.com/ant-design-vue/backer/0/website" target="_blank"><img src="https://opencollective.com/ant-design-vue/backer/0/avatar.svg"></a> <a href="https://opencollective.com/ant-design-vue/backer/1/website" target="_blank"><img src="https://opencollective.com/ant-design-vue/backer/1/avatar.svg"></a> <a href="https://opencollective.com/ant-design-vue/backer/2/website" target="_blank"><img src="https://opencollective.com/ant-design-vue/backer/2/avatar.svg"></a> <a href="https://opencollective.com/ant-design-vue/backer/3/website" target="_blank"><img src="https://opencollective.com/ant-design-vue/backer/3/avatar.svg"></a> <a href="https://opencollective.com/ant-design-vue/backer/4/website" target="_blank"><img src="https://opencollective.com/ant-design-vue/backer/4/avatar.svg"></a> <a href="https://opencollective.com/ant-design-vue/backer/5/website" target="_blank"><img src="https://opencollective.com/ant-design-vue/backer/5/avatar.svg"></a> <a href="https://opencollective.com/ant-design-vue/backer/6/website" target="_blank"><img src="https://opencollective.com/ant-design-vue/backer/6/avatar.svg"></a> <a href="https://opencollective.com/ant-design-vue/backer/7/website" target="_blank"><img src="https://opencollective.com/ant-design-vue/backer/7/avatar.svg"></a> <a href="https://opencollective.com/ant-design-vue/backer/8/website" target="_blank"><img src="https://opencollective.com/ant-design-vue/backer/8/avatar.svg"></a> <a href="https://opencollective.com/ant-design-vue/backer/9/website" target="_blank"><img src="https://opencollective.com/ant-design-vue/backer/9/avatar.svg"></a> <a href="https://opencollective.com/ant-design-vue/backer/10/website" target="_blank"><img src="https://opencollective.com/ant-design-vue/backer/10/avatar.svg"></a><a href="https://opencollective.com/ant-design-vue/backer/9/website" target="_blank"><img src="https://opencollective.com/ant-design-vue/backer/9/avatar.svg"></a>
## Patreon

View File

@ -136,23 +136,11 @@
form {
.has-feedback {
.@{ant-prefix}-input {
padding-right: @input-padding-horizontal-base + @input-affix-width;
}
// https://github.com/ant-design/ant-design/issues/19884
.@{ant-prefix}-input-affix-wrapper {
.@{ant-prefix}-input-suffix {
padding-right: 18px;
}
.@{ant-prefix}-input {
padding-right: @input-padding-horizontal-base + @input-affix-width * 2;
}
&.@{ant-prefix}-input-affix-wrapper-input-with-clear-btn {
.@{ant-prefix}-input {
padding-right: @input-padding-horizontal-base + @input-affix-width * 3;
}
}
}
// Fix overlapping between feedback icon and <Select>'s arrow.

View File

@ -35,25 +35,29 @@ const ClearableLabeledInput = defineComponent({
addonBefore: PropTypes.VNodeChild,
addonAfter: PropTypes.VNodeChild,
readonly: PropTypes.looseBool,
isFocused: PropTypes.looseBool,
},
methods: {
renderClearIcon(prefixCls: string) {
const { allowClear, value, disabled, readonly, inputType, handleReset } = this.$props;
if (
!allowClear ||
disabled ||
readonly ||
value === undefined ||
value === null ||
value === ''
) {
if (!allowClear) {
return null;
}
const showClearIcon =
!disabled && !readonly && value !== undefined && value !== null && value !== '';
const className =
inputType === ClearableInputType[0]
? `${prefixCls}-textarea-clear-icon`
: `${prefixCls}-clear-icon`;
return <CloseCircleFilled onClick={handleReset} class={className} role="button" />;
return (
<CloseCircleFilled
onClick={handleReset}
class={classNames(className, {
[`${className}-hidden`]: !showClearIcon,
})}
role="button"
/>
);
},
renderSuffix(prefixCls: string) {
@ -71,6 +75,7 @@ const ClearableLabeledInput = defineComponent({
renderLabeledIcon(prefixCls: string, element: VNode): VNode {
const props = this.$props;
const { style } = this.$attrs;
const suffix = this.renderSuffix(prefixCls);
if (!hasPrefixSuffix(this)) {
return cloneElement(element, {
@ -83,14 +88,15 @@ const ClearableLabeledInput = defineComponent({
) : null;
const affixWrapperCls = classNames(this.$attrs?.class, `${prefixCls}-affix-wrapper`, {
[`${prefixCls}-affix-wrapper-focused`]: props.isFocused,
[`${prefixCls}-affix-wrapper-disabled`]: props.disabled,
[`${prefixCls}-affix-wrapper-sm`]: props.size === 'small',
[`${prefixCls}-affix-wrapper-lg`]: props.size === 'large',
[`${prefixCls}-affix-wrapper-input-with-clear-btn`]:
props.suffix && props.allowClear && this.$props.value,
});
return (
<span class={affixWrapperCls} style={this.$attrs?.style}>
<span class={affixWrapperCls} style={style}>
{prefix}
{cloneElement(element, {
style: null,

View File

@ -67,6 +67,7 @@ export default defineComponent({
const value = typeof props.value === 'undefined' ? props.defaultValue : props.value;
return {
stateValue: typeof value === 'undefined' ? '' : value,
isFocused: false,
};
},
watch: {
@ -90,6 +91,16 @@ export default defineComponent({
}
},
methods: {
handleInputFocus(e) {
this.isFocused = true;
this.onFocus && this.onFocus(e);
},
handleInputBlur(e) {
this.isFocused = false;
this.onBlur && this.onBlur(e);
},
focus() {
this.input.focus();
},
@ -148,7 +159,15 @@ export default defineComponent({
'inputPrefixCls',
'loading',
]);
const { handleKeyDown, handleChange, size, disabled, $attrs } = this;
const {
handleKeyDown,
handleChange,
handleInputFocus,
handleInputBlur,
size,
disabled,
$attrs,
} = this;
const inputProps: any = {
...otherProps,
@ -161,6 +180,8 @@ export default defineComponent({
key: 'ant-input',
onInput: handleChange,
onChange: handleChange,
onFocus: handleInputFocus,
onBlur: handleInputBlur,
};
if (!inputProps.autofocus) {
delete inputProps.autofocus;
@ -197,7 +218,7 @@ export default defineComponent({
},
render() {
const { prefixCls: customizePrefixCls } = this.$props;
const { stateValue } = this.$data;
const { stateValue, isFocused } = this.$data;
const getPrefixCls = this.configProvider.getPrefixCls;
const prefixCls = getPrefixCls('input', customizePrefixCls);
const addonAfter = getComponent(this, 'addonAfter');
@ -216,6 +237,7 @@ export default defineComponent({
addonBefore,
suffix,
prefix,
isFocused,
};
return <ClearableLabeledInput {...props} ref={this.saveClearableInput} />;
},

View File

@ -5,12 +5,14 @@ import inputProps from './inputProps';
import { hasProp, getOptionProps } from '../_util/props-util';
import { defaultConfigProvider } from '../config-provider';
import { fixControlledValue, resolveOnChange } from './Input';
import classNames from '../_util/classNames';
import PropTypes, { withUndefined } from '../_util/vue-types';
const TextAreaProps = {
...inputProps,
autosize: withUndefined(PropTypes.oneOfType([Object, Boolean])),
autoSize: withUndefined(PropTypes.oneOfType([Object, Boolean])),
showCount: PropTypes.looseBool,
};
export default defineComponent({
@ -102,9 +104,13 @@ export default defineComponent({
renderTextArea(prefixCls: string) {
const props = getOptionProps(this);
const { style, class: customClass } = this.$attrs;
const resizeProps = {
...props,
...this.$attrs,
style: style && !props.showCount,
class: customClass && !props.showCount,
showCount: null,
prefixCls,
onInput: this.handleChange,
onChange: this.handleChange,
@ -114,19 +120,44 @@ export default defineComponent({
},
},
render() {
const { stateValue, prefixCls: customizePrefixCls } = this;
const { stateValue, prefixCls: customizePrefixCls, maxlength, showCount } = this;
const { style, class: customClass } = this.$attrs;
const getPrefixCls = this.configProvider.getPrefixCls;
const prefixCls = getPrefixCls('input', customizePrefixCls);
let value = fixControlledValue(stateValue);
// Max length value
const hasMaxlength = Number(maxlength) > 0;
value = hasMaxlength ? value.slice(0, maxlength) : value;
const props: any = {
...getOptionProps(this),
...this.$attrs,
prefixCls,
inputType: 'text',
value: fixControlledValue(stateValue),
element: this.renderTextArea(prefixCls),
handleReset: this.handleReset,
};
return <ClearableLabeledInput {...props} ref={this.saveClearableInput} />;
let textareaNode = (
<ClearableLabeledInput {...props} value={value} ref={this.saveClearableInput} />
);
if (showCount) {
const valueLength = [...value].length;
const dataCount = `${valueLength}${hasMaxlength ? ` / ${maxlength}` : ''}`;
textareaNode = (
<div
class={classNames(
`${prefixCls}-textarea`,
`${prefixCls}-textarea-show-count`,
customClass,
)}
style={style}
data-count={dataCount}
>
{textareaNode}
</div>
);
}
return textareaNode;
},
});

View File

@ -7,3 +7,5 @@ exports[`Input.Search should support suffix 1`] = `<span class="ant-input-search
exports[`TextArea should support disabled 1`] = `<textarea disabled="" class="ant-input ant-input-disabled"></textarea>`;
exports[`TextArea should support maxlength 1`] = `<textarea maxlength="10" class="ant-input"></textarea>`;
exports[`TextArea should support showCount 1`] = `<div class="ant-input-textarea ant-input-textarea-show-count" data-count="3 / 10"><textarea maxlength="10" class="ant-input"></textarea></div>`;

View File

@ -29,7 +29,7 @@ describe('Input', () => {
props: { allowClear: true, defaultValue: '111', disabled: true },
sync: false,
});
expect(wrapper.findAll('.ant-input-clear-icon').length).toBe(0);
expect(wrapper.findAll('.ant-input-clear-icon-hidden').length).toBeTruthy();
});
});
@ -68,6 +68,17 @@ describe('TextArea', () => {
expect(wrapper.html()).toMatchSnapshot();
});
});
it('should support showCount', async () => {
const wrapper = mount(TextArea, {
props: { showCount: true, defaultValue: '111', maxlength: 10 },
sync: false,
});
expect(wrapper.find('.ant-input-textarea-show-count')).toBeTruthy();
await asyncExpect(() => {
expect(wrapper.html()).toMatchSnapshot();
});
});
});
// describe('As Form Control', () => {

View File

@ -41,6 +41,14 @@
vertical-align: 0;
}
.@{ant-prefix}-input-clear-icon-hidden {
visibility: hidden;
}
.@{ant-prefix}-input-textarea-clear-icon-hidden {
visibility: hidden;
}
.@{ant-prefix}-input-textarea-clear-icon {
.clear-icon;
position: absolute;
@ -49,4 +57,13 @@
margin: 8px 8px 0 0;
}
.@{ant-prefix}-input-textarea {
&-show-count::after {
display: block;
color: @text-color-secondary;
text-align: right;
content: attr(data-count);
}
}
@import './search-input';

View File

@ -1,18 +1,17 @@
@import '../../style/themes/index';
@import '../../style/mixins/index';
@input-affix-margin: 4px;
@input-affix-width: 19px;
@input-affix-with-clear-btn-width: 38px;
// size mixins for input
.input-lg() {
height: @input-height-lg;
padding: @input-padding-vertical-lg @input-padding-horizontal-lg;
font-size: @font-size-lg;
}
.input-sm() {
height: @input-height-sm;
padding: @input-padding-vertical-sm @input-padding-horizontal-sm;
}
@ -47,7 +46,6 @@
position: relative;
display: inline-block;
width: 100%;
height: @input-height-base;
padding: @input-padding-vertical-base @input-padding-horizontal-base;
color: @input-color;
font-size: @font-size-base;
@ -264,12 +262,6 @@
height: @input-height-sm;
}
.@{inputClass}-affix-wrapper {
display: table-cell;
float: left;
width: 100%;
}
&&-compact {
display: block;
.clearfix;
@ -297,6 +289,10 @@
border-radius: 0;
}
& > .@{inputClass}-affix-wrapper {
display: inline-flex;
}
& > *:not(:last-child) {
margin-right: -@border-width-base;
border-right-width: @border-width-base;
@ -364,17 +360,44 @@
.input-affix-wrapper(@inputClass) {
position: relative;
display: inline-block;
display: inline-flex;
border: @border-width-base @border-style-base @input-border-color;
border-radius: @border-radius-base;
padding: @input-padding-vertical-base @input-padding-horizontal-base;
width: 100%;
text-align: start;
&:hover .@{inputClass}:not(.@{inputClass}-disabled) {
&:hover {
.hover();
}
&-disabled {
.disabled();
}
&-focused {
.active();
}
// Size
&-lg {
.input-lg();
}
&-sm {
.input-sm();
}
.@{inputClass} {
position: relative;
text-align: inherit;
border: none;
padding: 0;
&:focus {
border: none;
outline: none;
box-shadow: none;
}
}
// Should not break align of icon & text
@ -385,14 +408,10 @@
// https://codesandbox.io/embed/nifty-benz-gb7ml
.@{inputClass}-prefix,
.@{inputClass}-suffix {
position: absolute;
top: 50%;
z-index: 2;
display: flex;
align-items: center;
color: @input-color;
line-height: 0;
transform: translateY(-50%);
white-space: nowrap;
:not(.anticon) {
line-height: @line-height-base;
@ -407,27 +426,11 @@
}
.@{inputClass}-prefix {
left: @input-padding-horizontal-base + 1px;
margin-right: @input-affix-margin;
}
.@{inputClass}-suffix {
right: @input-padding-horizontal-base + 1px;
}
.@{inputClass}:not(:first-child) {
padding-left: @input-padding-horizontal-base + @input-affix-width;
}
.@{inputClass}:not(:last-child) {
padding-right: @input-padding-horizontal-base + @input-affix-width;
}
&.@{inputClass}-affix-wrapper-input-with-clear-btn .@{inputClass}:not(:last-child) {
padding-right: @input-padding-horizontal-base + @input-affix-with-clear-btn-width;
}
&.@{inputClass}-affix-wrapper-textarea-with-clear-btn .@{inputClass} {
padding-right: 22px;
margin-left: @input-affix-margin;
}
}
@ -438,7 +441,7 @@
// https://codesandbox.io/s/wizardly-sun-u10br
cursor: pointer;
transition: color 0.3s;
margin: 0 @input-affix-margin;
&:hover {
color: @text-color-secondary;
}

View File

@ -102,4 +102,12 @@ describe('Modal.confirm triggers callbacks correctly', () => {
expect($$(`.ant-modal-confirm-${type}`)).toHaveLength(0);
}
});
// it('should render title', async () => {
// open({
// title: () => <span>title</span>,
// });
// await sleep();
// expect($$('.ant-modal-confirm-title')[0].innerHTML).toBe('<span>title</span>');
// });
});

View File

@ -318,7 +318,7 @@
@input-padding-horizontal-lg: @input-padding-horizontal;
@input-padding-vertical-base: 4px;
@input-padding-vertical-sm: 1px;
@input-padding-vertical-lg: 6px;
@input-padding-vertical-lg: 6.5px;
@input-placeholder-color: hsv(0, 0, 75%);
@input-color: @text-color;
@input-border-color: @border-color-base;

View File

@ -163,7 +163,11 @@ export default defineComponent({
$slots[scopedSlots.switcherIcon] ||
$slots[slots.switcherIcon] ||
restProps.switcherIcon,
title: $slots[scopedSlots.title] || $slots[slots.title] || restProps[replaceFields.title],
title:
$slots[scopedSlots.title] ||
$slots[slots.title] ||
$slots.title ||
restProps[replaceFields.title],
dataRef: item,
key,
class: cls,