refactor: input

pull/5043/head
tangjinzhou 2021-12-15 20:48:24 +08:00
parent 7ec6831508
commit 5543ce6add
16 changed files with 810 additions and 491 deletions

View File

@ -39,7 +39,7 @@ export default defineComponent({
addonAfter: PropTypes.any, addonAfter: PropTypes.any,
readonly: PropTypes.looseBool, readonly: PropTypes.looseBool,
focused: PropTypes.looseBool, focused: PropTypes.looseBool,
bordered: PropTypes.looseBool, bordered: PropTypes.looseBool.def(true),
triggerFocus: { type: Function as PropType<() => void> }, triggerFocus: { type: Function as PropType<() => void> },
}, },
setup(props, { slots, attrs }) { setup(props, { slots, attrs }) {
@ -51,7 +51,7 @@ export default defineComponent({
} }
}; };
const renderClearIcon = (prefixCls: string) => { const renderClearIcon = (prefixCls: string) => {
const { allowClear, value, disabled, readonly, handleReset } = props; const { allowClear, value, disabled, readonly, handleReset, suffix = slots.suffix } = props;
if (!allowClear) { if (!allowClear) {
return null; return null;
} }
@ -60,9 +60,12 @@ export default defineComponent({
return ( return (
<CloseCircleFilled <CloseCircleFilled
onClick={handleReset} onClick={handleReset}
// Do not trigger onBlur when clear input
onMousedown={e => e.preventDefault()}
class={classNames( class={classNames(
{ {
[`${className}-hidden`]: !needClear, [`${className}-hidden`]: !needClear,
[`${className}-has-suffix`]: !!suffix,
}, },
className, className,
)} )}

View File

@ -29,7 +29,6 @@ export default defineComponent({
}; };
}); });
return () => { return () => {
const {} = props;
return ( return (
<span <span
class={cls.value} class={cls.value}

View File

@ -19,7 +19,6 @@ import { useInjectFormItemContext } from '../form/FormItemContext';
import omit from '../_util/omit'; import omit from '../_util/omit';
import useConfigInject from '../_util/hooks/useConfigInject'; import useConfigInject from '../_util/hooks/useConfigInject';
import type { ChangeEvent, FocusEventHandler } from '../_util/EventInterface'; import type { ChangeEvent, FocusEventHandler } from '../_util/EventInterface';
import { controlDefaultValue } from '../_util/util';
export function fixControlledValue(value: string | number) { export function fixControlledValue(value: string | number) {
if (typeof value === 'undefined' || value === null) { if (typeof value === 'undefined' || value === null) {
@ -134,13 +133,21 @@ export default defineComponent({
let removePasswordTimeout: any; let removePasswordTimeout: any;
const formItemContext = useInjectFormItemContext(); const formItemContext = useInjectFormItemContext();
const { direction, prefixCls, size, autocomplete } = useConfigInject('input', props); const { direction, prefixCls, size, autocomplete } = useConfigInject('input', props);
const stateValue = ref(props.value === controlDefaultValue ? props.defaultValue : props.value); const stateValue = ref(props.value === undefined ? props.defaultValue : props.value);
const focused = ref(false); const focused = ref(false);
watch( watch(
() => props.value, () => props.value,
() => { () => {
if (props.value !== controlDefaultValue) { if (props.value !== undefined) {
stateValue.value = props.value;
}
},
);
watch(
() => props.disabled,
() => {
if (props.value !== undefined) {
stateValue.value = props.value; stateValue.value = props.value;
} }
}, },
@ -181,7 +188,7 @@ export default defineComponent({
expose({ expose({
focus, focus,
blur, blur,
inputRef, input: inputRef,
stateValue, stateValue,
setSelectionRange, setSelectionRange,
select, select,
@ -217,7 +224,7 @@ export default defineComponent({
if (stateValue.value === value) { if (stateValue.value === value) {
return; return;
} }
if (props.value === controlDefaultValue) { if (props.value === undefined) {
stateValue.value = value; stateValue.value = value;
} else { } else {
instance.update(); instance.update();
@ -234,9 +241,10 @@ export default defineComponent({
}; };
const handleChange = (e: ChangeEvent) => { const handleChange = (e: ChangeEvent) => {
const { value, composing, isComposing } = e.target as any; const { value, composing } = e.target as any;
// https://github.com/vueComponent/ant-design-vue/issues/2203 // https://github.com/vueComponent/ant-design-vue/issues/2203
if (((isComposing || composing) && props.lazy) || stateValue.value === value) return; if ((((e as any).isComposing || composing) && props.lazy) || stateValue.value === value)
return;
const newVal = e.target.value; const newVal = e.target.value;
resolveOnChange(inputRef.value, e, triggerChange); resolveOnChange(inputRef.value, e, triggerChange);
setValue(newVal, () => { setValue(newVal, () => {
@ -270,6 +278,7 @@ export default defineComponent({
disabled, disabled,
bordered = true, bordered = true,
valueModifiers = {}, valueModifiers = {},
htmlSize,
} = props; } = props;
const otherProps = omit(props as InputProps & { inputType: any; placeholder: string }, [ const otherProps = omit(props as InputProps & { inputType: any; placeholder: string }, [
'prefixCls', 'prefixCls',
@ -285,9 +294,11 @@ export default defineComponent({
'size', 'size',
'inputType', 'inputType',
'bordered', 'bordered',
'htmlSize',
]); ]);
const inputProps = { const inputProps = {
...otherProps, ...otherProps,
...attrs,
autocomplete: autocomplete.value, autocomplete: autocomplete.value,
onChange: handleChange, onChange: handleChange,
onInput: handleChange, onInput: handleChange,
@ -302,6 +313,7 @@ export default defineComponent({
), ),
ref: inputRef, ref: inputRef,
key: 'ant-input', key: 'ant-input',
size: htmlSize,
}; };
if (valueModifiers.lazy) { if (valueModifiers.lazy) {
delete inputProps.onInput; delete inputProps.onInput;
@ -321,7 +333,7 @@ export default defineComponent({
inputType: 'input', inputType: 'input',
value: fixControlledValue(stateValue.value), value: fixControlledValue(stateValue.value),
handleReset, handleReset,
focused: focused.value, focused: focused.value && props.disabled,
}; };
return ( return (

View File

@ -1,125 +1,100 @@
import type { PropType, VNode } from 'vue'; import type { CSSProperties, VNode } from 'vue';
import { nextTick, defineComponent, withDirectives } from 'vue'; import {
getCurrentInstance,
watch,
onBeforeUnmount,
ref,
nextTick,
defineComponent,
withDirectives,
} from 'vue';
import ResizeObserver from '../vc-resize-observer'; import ResizeObserver from '../vc-resize-observer';
import classNames from '../_util/classNames'; import classNames from '../_util/classNames';
import calculateNodeHeight from './calculateNodeHeight'; import calculateNodeHeight from './calculateNodeHeight';
import raf from '../_util/raf'; import raf from '../_util/raf';
import warning from '../_util/warning'; import warning from '../_util/warning';
import BaseMixin from '../_util/BaseMixin'; import BaseMixin from '../_util/BaseMixin';
import inputProps from './inputProps';
import PropTypes from '../_util/vue-types';
import { getOptionProps } from '../_util/props-util';
import antInput from '../_util/antInputDirective'; import antInput from '../_util/antInputDirective';
import omit from '../_util/omit'; import omit from '../_util/omit';
import { textAreaProps } from './inputProps';
const RESIZE_STATUS_NONE = 0; const RESIZE_STATUS_NONE = 0;
const RESIZE_STATUS_RESIZING = 1; const RESIZE_STATUS_RESIZING = 1;
const RESIZE_STATUS_RESIZED = 2; const RESIZE_STATUS_RESIZED = 2;
export interface AutoSizeType {
minRows?: number;
maxRows?: number;
}
const TextAreaProps = {
...inputProps,
autosize: { type: [Boolean, Object] as PropType<AutoSizeType>, default: undefined },
autoSize: { type: [Boolean, Object] as PropType<AutoSizeType>, default: undefined },
onResize: PropTypes.func,
};
const ResizableTextArea = defineComponent({ const ResizableTextArea = defineComponent({
name: 'ResizableTextArea', name: 'ResizableTextArea',
mixins: [BaseMixin], mixins: [BaseMixin],
inheritAttrs: false, inheritAttrs: false,
props: TextAreaProps, props: textAreaProps,
setup() { setup(props, { attrs, emit, expose }) {
return { let nextFrameActionId: any;
nextFrameActionId: undefined, let resizeFrameId: any;
textArea: null, const textAreaRef = ref();
resizeFrameId: undefined, const textareaStyles = ref({});
}; const resizeStatus = ref(RESIZE_STATUS_NONE);
}, onBeforeUnmount(() => {
data() { raf.cancel(nextFrameActionId);
return { raf.cancel(resizeFrameId);
textareaStyles: {},
resizeStatus: RESIZE_STATUS_NONE,
};
},
watch: {
value() {
nextTick(() => {
this.resizeTextarea();
}); });
},
},
mounted() {
this.resizeTextarea();
},
beforeUnmount() {
raf.cancel(this.nextFrameActionId);
raf.cancel(this.resizeFrameId);
},
methods: {
saveTextArea(textArea: HTMLTextAreaElement) {
this.textArea = textArea;
},
handleResize(size: { width: number; height: number }) {
const { resizeStatus } = this.$data;
if (resizeStatus !== RESIZE_STATUS_NONE) {
return;
}
this.$emit('resize', size);
},
resizeOnNextFrame() {
raf.cancel(this.nextFrameActionId);
this.nextFrameActionId = raf(this.resizeTextarea);
},
resizeTextarea() {
const autoSize = this.$props.autoSize || this.$props.autosize;
if (!autoSize || !this.textArea) {
return;
}
const { minRows, maxRows } = autoSize;
const textareaStyles = calculateNodeHeight(this.textArea, false, minRows, maxRows);
this.setState({ textareaStyles, resizeStatus: RESIZE_STATUS_RESIZING }, () => {
raf.cancel(this.resizeFrameId);
this.resizeFrameId = raf(() => {
this.setState({ resizeStatus: RESIZE_STATUS_RESIZED }, () => {
this.resizeFrameId = raf(() => {
this.setState({ resizeStatus: RESIZE_STATUS_NONE });
this.fixFirefoxAutoScroll();
});
});
});
});
},
// https://github.com/ant-design/ant-design/issues/21870 // https://github.com/ant-design/ant-design/issues/21870
fixFirefoxAutoScroll() { const fixFirefoxAutoScroll = () => {
try { try {
if (document.activeElement === this.textArea) { if (document.activeElement === textAreaRef.value) {
const currentStart = this.textArea.selectionStart; const currentStart = textAreaRef.value.selectionStart;
const currentEnd = this.textArea.selectionEnd; const currentEnd = textAreaRef.value.selectionEnd;
this.textArea.setSelectionRange(currentStart, currentEnd); textAreaRef.value.setSelectionRange(currentStart, currentEnd);
} }
} catch (e) { } catch (e) {
// Fix error in Chrome: // Fix error in Chrome:
// Failed to read the 'selectionStart' property from 'HTMLInputElement' // Failed to read the 'selectionStart' property from 'HTMLInputElement'
// http://stackoverflow.com/q/21177489/3040605 // http://stackoverflow.com/q/21177489/3040605
} }
}, };
renderTextArea() { const resizeTextarea = () => {
const props: any = { ...getOptionProps(this), ...this.$attrs }; const autoSize = props.autoSize || props.autosize;
const { prefixCls, autoSize, autosize, disabled, class: className } = props; if (!autoSize || !textAreaRef.value) {
const { textareaStyles, resizeStatus } = this.$data; return;
}
const { minRows, maxRows } = autoSize;
textareaStyles.value = calculateNodeHeight(textAreaRef.value, false, minRows, maxRows);
resizeStatus.value = RESIZE_STATUS_RESIZING;
raf.cancel(resizeFrameId);
resizeFrameId = raf(() => {
resizeStatus.value = RESIZE_STATUS_RESIZED;
resizeFrameId = raf(() => {
resizeStatus.value = RESIZE_STATUS_NONE;
fixFirefoxAutoScroll();
});
});
};
const resizeOnNextFrame = () => {
raf.cancel(nextFrameActionId);
nextFrameActionId = raf(resizeTextarea);
};
const handleResize = (size: { width: number; height: number }) => {
if (resizeStatus.value !== RESIZE_STATUS_NONE) {
return;
}
emit('resize', size);
const autoSize = props.autoSize || props.autosize;
if (autoSize) {
resizeOnNextFrame();
}
};
warning( warning(
autosize === undefined, props.autosize === undefined,
'Input.TextArea', 'Input.TextArea',
'autosize is deprecated, please use autoSize instead.', 'autosize is deprecated, please use autoSize instead.',
); );
const renderTextArea = () => {
const { prefixCls, autoSize, autosize, disabled } = props;
const otherProps = omit(props, [ const otherProps = omit(props, [
'prefixCls', 'prefixCls',
'onPressEnter', 'onPressEnter',
@ -130,23 +105,19 @@ const ResizableTextArea = defineComponent({
'type', 'type',
'lazy', 'lazy',
]); ]);
const cls = classNames(prefixCls, className, { const cls = classNames(prefixCls, attrs.class, {
[`${prefixCls}-disabled`]: disabled, [`${prefixCls}-disabled`]: disabled,
}); });
// Fix https://github.com/ant-design/ant-design/issues/6776
// Make sure it could be reset when using form.getFieldDecorator
if ('value' in otherProps) {
otherProps.value = otherProps.value || '';
}
const style = { const style = {
...props.style, ...(attrs.style as CSSProperties),
...textareaStyles, ...textareaStyles.value,
...(resizeStatus === RESIZE_STATUS_RESIZING ...(resizeStatus.value === RESIZE_STATUS_RESIZING
? { overflowX: 'hidden', overflowY: 'hidden' } ? { overflowX: 'hidden', overflowY: 'hidden' }
: null), : null),
}; };
const textareaProps: any = { const textareaProps: any = {
...otherProps, ...otherProps,
...attrs,
style, style,
class: cls, class: cls,
}; };
@ -154,17 +125,32 @@ const ResizableTextArea = defineComponent({
delete textareaProps.autofocus; delete textareaProps.autofocus;
} }
return ( return (
<ResizeObserver onResize={this.handleResize} disabled={!(autoSize || autosize)}> <ResizeObserver onResize={handleResize} disabled={!(autoSize || autosize)}>
{withDirectives((<textarea {...textareaProps} ref={this.saveTextArea} />) as VNode, [ {withDirectives((<textarea {...textareaProps} ref={textAreaRef} />) as VNode, [
[antInput], [antInput],
])} ])}
</ResizeObserver> </ResizeObserver>
); );
}, };
},
render() { watch(
return this.renderTextArea(); () => props.value,
() => {
nextTick(() => {
resizeTextarea();
});
},
);
const instance = getCurrentInstance();
expose({
resizeTextarea,
textArea: textAreaRef,
instance,
});
return () => {
return renderTextArea();
};
}, },
}); });

View File

@ -49,7 +49,7 @@ export default defineComponent({
}; };
const onMousedown: MouseEventHandler = e => { const onMousedown: MouseEventHandler = e => {
if (document.activeElement === inputRef.value?.inputRef.value) { if (document.activeElement === inputRef.value?.input) {
e.preventDefault(); e.preventDefault();
} }
}; };
@ -84,7 +84,9 @@ export default defineComponent({
enterButtonAsElement.type.__ANT_BUTTON; enterButtonAsElement.type.__ANT_BUTTON;
if (isAntdButton || enterButtonAsElement.tagName === 'button') { if (isAntdButton || enterButtonAsElement.tagName === 'button') {
button = cloneElement(enterButtonAsElement, { button = cloneElement(
enterButtonAsElement,
{
onMousedown, onMousedown,
onClick: onSearch, onClick: onSearch,
key: 'enterButton', key: 'enterButton',
@ -94,7 +96,9 @@ export default defineComponent({
size: size.value, size: size.value,
} }
: {}), : {}),
}); },
false,
);
} else { } else {
button = ( button = (
<Button <Button

View File

@ -1,175 +1,209 @@
import { defineComponent, inject, nextTick } from 'vue'; import {
computed,
defineComponent,
getCurrentInstance,
nextTick,
onMounted,
ref,
watch,
watchEffect,
} from 'vue';
import ClearableLabeledInput from './ClearableLabeledInput'; import ClearableLabeledInput from './ClearableLabeledInput';
import ResizableTextArea from './ResizableTextArea'; import ResizableTextArea from './ResizableTextArea';
import inputProps from './inputProps'; import { textAreaProps } from './inputProps';
import { hasProp, getOptionProps } from '../_util/props-util'; import type { InputFocusOptions } from './Input';
import { defaultConfigProvider } from '../config-provider'; import { fixControlledValue, resolveOnChange, triggerFocus } from './Input';
import { fixControlledValue, resolveOnChange } from './Input';
import classNames from '../_util/classNames'; import classNames from '../_util/classNames';
import PropTypes, { withUndefined } from '../_util/vue-types';
import { useInjectFormItemContext } from '../form/FormItemContext'; import { useInjectFormItemContext } from '../form/FormItemContext';
import type { FocusEventHandler } from '../_util/EventInterface';
import useConfigInject from '../_util/hooks/useConfigInject';
import omit from '../_util/omit';
const TextAreaProps = { function fixEmojiLength(value: string, maxLength: number) {
...inputProps, return [...(value || '')].slice(0, maxLength).join('');
autosize: withUndefined(PropTypes.oneOfType([Object, Boolean])), }
autoSize: withUndefined(PropTypes.oneOfType([Object, Boolean])),
showCount: PropTypes.looseBool,
onCompositionstart: PropTypes.func,
onCompositionend: PropTypes.func,
valueModifiers: Object,
};
export default defineComponent({ export default defineComponent({
name: 'ATextarea', name: 'ATextarea',
inheritAttrs: false, inheritAttrs: false,
props: { props: textAreaProps,
...TextAreaProps, setup(props, { attrs, expose, emit }) {
},
setup() {
const formItemContext = useInjectFormItemContext(); const formItemContext = useInjectFormItemContext();
return { const stateValue = ref(props.value === undefined ? props.defaultValue : props.value);
configProvider: inject('configProvider', defaultConfigProvider), const resizableTextArea = ref();
resizableTextArea: null, const { prefixCls, size, direction } = useConfigInject('input', props);
clearableInput: null, const showCount = computed(() => {
formItemContext, return (props.showCount as any) === '' || props.showCount || false;
};
},
data() {
const value = typeof this.value === 'undefined' ? this.defaultValue : this.value;
return {
stateValue: typeof value === 'undefined' ? '' : value,
};
},
watch: {
value(val: string) {
this.stateValue = val;
},
},
mounted() {
nextTick(() => {
if (process.env.NODE_ENV === 'test') {
if (this.autofocus) {
this.focus();
}
}
}); });
// Max length value
const hasMaxLength = computed(() => Number(props.maxlength) > 0);
const compositing = ref(false);
const instance = getCurrentInstance();
watch(
() => props.value,
() => {
if ('value' in instance.vnode.props || {}) {
stateValue.value = props.value ?? '';
}
}, },
methods: { );
setValue(value: string, callback?: Function) {
if (!hasProp(this, 'value')) { const focus = (option?: InputFocusOptions) => {
this.stateValue = value; triggerFocus(resizableTextArea.value?.textArea, option);
};
const blur = () => {
resizableTextArea.value?.textArea?.blur();
};
const setValue = (value: string | number, callback?: Function) => {
if (stateValue.value === value) {
return;
}
if (props.value === undefined) {
stateValue.value = value;
} else { } else {
(this as any).$forceUpdate(); resizableTextArea.value?.instance.update?.();
} }
nextTick(() => { nextTick(() => {
callback && callback(); callback && callback();
}); });
},
handleKeyDown(e: KeyboardEvent) {
if (e.keyCode === 13) {
this.$emit('pressEnter', e);
}
this.$emit('keydown', e);
},
triggerChange(e: Event) {
this.$emit('update:value', (e.target as any).value);
this.$emit('change', e);
this.$emit('input', e);
this.formItemContext.onFieldChange();
},
handleChange(e: Event) {
const { value, composing, isComposing } = e.target as any;
if (((isComposing || composing) && this.lazy) || this.stateValue === value) return;
this.setValue((e.target as HTMLTextAreaElement).value, () => {
this.resizableTextArea?.resizeTextarea();
});
resolveOnChange(this.resizableTextArea.textArea, e, this.triggerChange);
},
focus() {
this.resizableTextArea.textArea.focus();
},
blur() {
this.resizableTextArea.textArea.blur();
},
saveTextArea(resizableTextArea: any) {
this.resizableTextArea = resizableTextArea;
},
saveClearableInput(clearableInput: HTMLTextAreaElement) {
this.clearableInput = clearableInput;
},
handleReset(e: Event) {
this.setValue('', () => {
this.resizableTextArea.renderTextArea();
this.focus();
});
resolveOnChange(this.resizableTextArea.textArea, e, this.triggerChange);
},
handleBlur(e: Event) {
this.$emit('blur', e);
this.formItemContext.onFieldBlur();
},
renderTextArea(prefixCls: string) {
const props = getOptionProps(this);
const { style, class: customClass } = this.$attrs;
const resizeProps = {
...props,
...this.$attrs,
style: !props.showCount && style,
class: !props.showCount && customClass,
showCount: null,
prefixCls,
onInput: this.handleChange,
onBlur: this.handleBlur,
onChange: this.handleChange,
onKeydown: this.handleKeyDown,
}; };
if (this.valueModifiers?.lazy) {
const handleKeyDown = (e: KeyboardEvent) => {
if (e.keyCode === 13) {
emit('pressEnter', e);
}
emit('keydown', e);
};
const onBlur: FocusEventHandler = e => {
const { onBlur } = props;
onBlur?.(e);
formItemContext.onFieldBlur();
};
const triggerChange = (e: Event) => {
emit('update:value', (e.target as HTMLInputElement).value);
emit('change', e);
emit('input', e);
formItemContext.onFieldChange();
};
const handleReset = (e: MouseEvent) => {
resolveOnChange(resizableTextArea.value.textArea, e, triggerChange);
setValue('', () => {
focus();
});
};
const handleChange = (e: Event) => {
const { value, composing } = e.target as any;
compositing.value = (e as any).isComposing || composing;
if ((compositing.value && props.lazy) || stateValue.value === value) return;
let triggerValue = (e.currentTarget as any).value;
if (hasMaxLength.value) {
triggerValue = fixEmojiLength(triggerValue, props.maxlength!);
}
resolveOnChange(e.currentTarget as any, e, triggerChange, triggerValue);
setValue(triggerValue);
};
const renderTextArea = () => {
const { style, class: customClass } = attrs;
const { bordered = true } = props;
const resizeProps = {
...omit(props, ['allowClear']),
...attrs,
style: showCount.value && style,
class: {
[`${prefixCls.value}-borderless`]: !bordered,
[`${customClass}`]: customClass && !showCount.value,
[`${prefixCls.value}-sm`]: size.value === 'small',
[`${prefixCls.value}-lg`]: size.value === 'large',
},
showCount: null,
prefixCls: prefixCls.value,
onInput: handleChange,
onChange: handleChange,
onBlur,
onKeydown: handleKeyDown,
};
if (props.valueModifiers?.lazy) {
delete resizeProps.onInput; delete resizeProps.onInput;
} }
return ( return (
<ResizableTextArea <ResizableTextArea
{...resizeProps} {...resizeProps}
id={resizeProps.id ?? this.formItemContext.id.value} id={resizeProps.id ?? formItemContext.id.value}
ref={this.saveTextArea} ref={resizableTextArea}
maxlength={props.maxlength}
/> />
); );
}, };
},
render() { onMounted(() => {
const { stateValue, prefixCls: customizePrefixCls, maxlength, showCount } = this; if (process.env.NODE_ENV === 'test') {
const { style, class: customClass } = this.$attrs; if (props.autofocus) {
const getPrefixCls = this.configProvider.getPrefixCls; focus();
const prefixCls = getPrefixCls('input', customizePrefixCls); }
let value = fixControlledValue(stateValue) as string; }
// Max length value });
const hasMaxlength = Number(maxlength) > 0; expose({
value = hasMaxlength ? value.slice(0, maxlength) : value; focus,
const props: any = { blur,
...getOptionProps(this), resizableTextArea,
...this.$attrs, });
prefixCls, const mergedValue = ref('');
watchEffect(() => {
let val = fixControlledValue(stateValue.value) as string;
if (
!compositing.value &&
hasMaxLength.value &&
(props.value === null || props.value === undefined)
) {
// fix #27612 value '😂'.length === 2 emoji
val = fixEmojiLength(val, props.maxlength);
}
mergedValue.value = val;
});
return () => {
const { maxlength, bordered = true } = props;
const { style, class: customClass } = attrs;
const inputProps: any = {
...props,
...attrs,
prefixCls: prefixCls.value,
inputType: 'text', inputType: 'text',
element: this.renderTextArea(prefixCls), handleReset,
handleReset: this.handleReset, direction: direction.value,
bordered,
style: showCount.value ? undefined : style,
}; };
let textareaNode = ( let textareaNode = (
<ClearableLabeledInput {...props} value={value} ref={this.saveClearableInput} /> <ClearableLabeledInput
{...inputProps}
value={mergedValue.value}
v-slots={{ element: renderTextArea }}
/>
); );
if (showCount) { if (showCount.value) {
const valueLength = [...value].length; const valueLength = [...mergedValue.value].length;
const dataCount = `${valueLength}${hasMaxlength ? ` / ${maxlength}` : ''}`; let dataCount = '';
if (typeof showCount.value === 'object') {
dataCount = showCount.value.formatter({ count: valueLength, maxlength });
} else {
dataCount = `${valueLength}${hasMaxLength.value ? ` / ${maxlength}` : ''}`;
}
textareaNode = ( textareaNode = (
<div <div
class={classNames( class={classNames(
`${prefixCls}-textarea`, `${prefixCls.value}-textarea`,
`${prefixCls}-textarea-show-count`, {
[`${prefixCls.value}-textarea-rtl`]: direction.value === 'rtl',
},
`${prefixCls.value}-textarea-show-count`,
customClass, customClass,
)} )}
style={style} style={style}
@ -180,5 +214,6 @@ export default defineComponent({
); );
} }
return textareaNode; return textareaNode;
};
}, },
}); });

View File

@ -1,5 +1,7 @@
// Thanks to https://github.com/andreypopp/react-textarea-autosize/ // Thanks to https://github.com/andreypopp/react-textarea-autosize/
import type { CSSProperties } from 'vue';
/** /**
* calculateNodeHeight(uiTextNode, useCache = false) * calculateNodeHeight(uiTextNode, useCache = false)
*/ */
@ -33,6 +35,7 @@ const SIZING_STYLE = [
'padding-right', 'padding-right',
'border-width', 'border-width',
'box-sizing', 'box-sizing',
'word-break',
]; ];
export interface NodeType { export interface NodeType {
@ -90,9 +93,11 @@ export default function calculateNodeHeight(
useCache = false, useCache = false,
minRows: number | null = null, minRows: number | null = null,
maxRows: number | null = null, maxRows: number | null = null,
) { ): CSSProperties {
if (!hiddenTextarea) { if (!hiddenTextarea) {
hiddenTextarea = document.createElement('textarea'); hiddenTextarea = document.createElement('textarea');
hiddenTextarea.setAttribute('tab-index', '-1');
hiddenTextarea.setAttribute('aria-hidden', 'true');
document.body.appendChild(hiddenTextarea); document.body.appendChild(hiddenTextarea);
} }
@ -120,7 +125,7 @@ export default function calculateNodeHeight(
let minHeight = Number.MIN_SAFE_INTEGER; let minHeight = Number.MIN_SAFE_INTEGER;
let maxHeight = Number.MAX_SAFE_INTEGER; let maxHeight = Number.MAX_SAFE_INTEGER;
let height = hiddenTextarea.scrollHeight; let height = hiddenTextarea.scrollHeight;
let overflowY: string; let overflowY: any;
if (boxSizing === 'border-box') { if (boxSizing === 'border-box') {
// border-box: add border, since height = content + padding + border // border-box: add border, since height = content + padding + border

View File

@ -1,7 +1,7 @@
import type { ExtractPropTypes, PropType } from 'vue'; import type { ExtractPropTypes, PropType } from 'vue';
import PropTypes from '../_util/vue-types'; import PropTypes from '../_util/vue-types';
import type { SizeType } from '../config-provider'; import type { SizeType } from '../config-provider';
import { controlDefaultValue } from '../_util/util'; import omit from '../_util/omit';
export const inputDefaultValue = Symbol() as unknown as string; export const inputDefaultValue = Symbol() as unknown as string;
const inputProps = { const inputProps = {
id: PropTypes.string, id: PropTypes.string,
@ -10,7 +10,7 @@ const inputProps = {
defaultValue: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), defaultValue: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
value: { value: {
type: [String, Number, Symbol] as PropType<string | number>, type: [String, Number, Symbol] as PropType<string | number>,
default: controlDefaultValue, default: undefined,
}, },
placeholder: { placeholder: {
type: [String, Number] as PropType<string | number>, type: [String, Number] as PropType<string | number>,
@ -57,6 +57,7 @@ const inputProps = {
maxlength: PropTypes.number, maxlength: PropTypes.number,
loading: PropTypes.looseBool, loading: PropTypes.looseBool,
bordered: PropTypes.looseBool, bordered: PropTypes.looseBool,
htmlSize: Number,
onPressEnter: PropTypes.func, onPressEnter: PropTypes.func,
onKeydown: PropTypes.func, onKeydown: PropTypes.func,
onKeyup: PropTypes.func, onKeyup: PropTypes.func,
@ -69,3 +70,25 @@ const inputProps = {
}; };
export default inputProps; export default inputProps;
export type InputProps = Partial<ExtractPropTypes<typeof inputProps>>; export type InputProps = Partial<ExtractPropTypes<typeof inputProps>>;
export interface AutoSizeType {
minRows?: number;
maxRows?: number;
}
interface ShowCountProps {
formatter: (args: { count: number; maxlength?: number }) => string;
}
const textAreaProps = {
...omit(inputProps, ['prefix', 'addonBefore', 'addonAfter', 'suffix']),
autosize: { type: [Boolean, Object] as PropType<AutoSizeType>, default: undefined },
autoSize: { type: [Boolean, Object] as PropType<AutoSizeType>, default: undefined },
showCount: { type: [Boolean, Object] as PropType<ShowCountProps> },
onResize: { type: Function as PropType<(size: { width: number; height: number }) => void> },
onCompositionstart: PropTypes.func,
onCompositionend: PropTypes.func,
valueModifiers: Object,
};
export { textAreaProps };
export type TextAreaProps = Partial<ExtractPropTypes<typeof textAreaProps>>;

View File

@ -0,0 +1,20 @@
// Fix Input component height issue in IE11
@media screen and (-ms-high-contrast: active), (-ms-high-contrast: none) {
.@{ant-prefix}-input {
height: @input-height-base;
&-lg {
height: @input-height-lg;
}
&-sm {
height: @input-height-sm;
}
&-affix-wrapper {
> input.@{ant-prefix}-input {
height: auto;
}
}
}
}

View File

@ -1,5 +1,6 @@
@import './index';
@import './mixin'; @import './mixin';
@import (reference) '../../style/themes/index';
@input-prefix-cls: ~'@{ant-prefix}-input';
@input-affix-margin: 4px; @input-affix-margin: 4px;
@ -8,6 +9,19 @@
.input(); .input();
display: inline-flex; display: inline-flex;
&:not(&-disabled):hover {
.hover();
z-index: 1;
.@{ant-prefix}-input-search-with-button & {
z-index: 0;
}
}
&-focused,
&:focus {
z-index: 1;
}
&-disabled { &-disabled {
.@{ant-prefix}-input[disabled] { .@{ant-prefix}-input[disabled] {
background: transparent; background: transparent;
@ -20,7 +34,7 @@
outline: none; outline: none;
&:focus { &:focus {
box-shadow: none; box-shadow: none !important;
} }
} }

View File

@ -0,0 +1,43 @@
@import (reference) '../../style/themes/index';
@input-prefix-cls: ~'@{ant-prefix}-input';
// ========================= Input =========================
.@{iconfont-css-prefix}.@{ant-prefix}-input-clear-icon {
margin: 0;
color: @disabled-color;
font-size: @font-size-sm;
vertical-align: -1px;
// https://github.com/ant-design/ant-design/pull/18151
// https://codesandbox.io/s/wizardly-sun-u10br
cursor: pointer;
transition: color 0.3s;
&:hover {
color: @text-color-secondary;
}
&:active {
color: @text-color;
}
&-hidden {
visibility: hidden;
}
&-has-suffix {
margin: 0 @input-affix-margin;
}
}
// ======================= TextArea ========================
.@{ant-prefix}-input-affix-wrapper-textarea-with-clear-btn {
padding: 0 !important;
border: 0 !important;
.@{ant-prefix}-input-clear-icon {
position: absolute;
top: 8px;
right: 8px;
z-index: 1;
}
}

View File

@ -1,18 +1,21 @@
@import '../../style/themes/index'; @import '../../style/themes/index';
@import '../../style/mixins/index'; @import '../../style/mixins/index';
@import './affix';
@import './mixin'; @import './mixin';
@import './affix';
@import './allow-clear';
@input-prefix-cls: ~'@{ant-prefix}-input';
// Input styles // Input styles
.@{ant-prefix}-input { .@{input-prefix-cls} {
.reset-component(); .reset-component();
.input(); .input();
}
//== Style for input-group: input with label, with button or dropdown... //== Style for input-group: input with label, with button or dropdown...
.@{ant-prefix}-input-group { &-group {
.reset-component(); .reset-component();
.input-group(~'@{ant-prefix}-input'); .input-group(~'@{input-prefix-cls}');
&-wrapper { &-wrapper {
display: inline-block; display: inline-block;
width: 100%; width: 100%;
@ -21,13 +24,7 @@
} }
} }
// Input with affix: prefix or suffix &-password-icon {
.@{ant-prefix}-input-affix-wrapper {
.reset-component();
.input-affix-wrapper(~'@{ant-prefix}-input');
}
.@{ant-prefix}-input-password-icon {
color: @text-color-secondary; color: @text-color-secondary;
cursor: pointer; cursor: pointer;
transition: all 0.3s; transition: all 0.3s;
@ -37,41 +34,35 @@
} }
} }
.@{ant-prefix}-input-clear-icon { &[type='color'] {
.clear-icon(); height: @input-height-base;
vertical-align: 0;
}
.@{ant-prefix}-input-clear-icon-hidden { &.@{input-prefix-cls}-lg {
visibility: hidden; height: @input-height-lg;
} }
&.@{input-prefix-cls}-sm {
.@{ant-prefix}-input-textarea-clear-icon-hidden { height: @input-height-sm;
visibility: hidden; padding-top: 3px;
} padding-bottom: 3px;
.@{ant-prefix}-input-affix-wrapper-textarea-with-clear-btn {
padding: 0 !important;
.@{ant-prefix}-input {
padding: @input-padding-vertical-base @input-padding-horizontal-base;
} }
} }
.@{ant-prefix}-input-textarea-clear-icon { &-textarea-show-count {
.clear-icon(); // https://github.com/ant-design/ant-design/issues/33049
position: absolute; > .@{input-prefix-cls} {
top: 0; height: 100%;
right: 0;
margin: 8px 8px 0 0;
} }
.@{ant-prefix}-input-textarea { &::after {
&-show-count::after { float: right;
display: block;
color: @text-color-secondary; color: @text-color-secondary;
text-align: right; white-space: nowrap;
content: attr(data-count); content: attr(data-count);
pointer-events: none;
}
} }
} }
@import './search-input'; @import './search-input';
@import './rtl';
@import './IE11';

View File

@ -1,8 +1,6 @@
@import '../../style/themes/index'; @import '../../style/themes/index';
@import '../../style/mixins/index'; @import '../../style/mixins/index';
@input-affix-margin: 4px;
@input-affix-width: 19px;
@input-affix-with-clear-btn-width: 38px; @input-affix-with-clear-btn-width: 38px;
// size mixins for input // size mixins for input
@ -16,23 +14,37 @@
} }
// input status // input status
// == when focus or actived // == when focus or active
.active(@color: @outline-color) { .active(@borderColor: @primary-color; @hoverBorderColor: @primary-color-hover; @outlineColor: @primary-color-outline) {
border-color: ~`colorPalette('@{color}', 5) `; & when (@theme = dark) {
border-color: @borderColor;
}
& when (not (@theme = dark) and not (@theme = variable)) {
border-color: @hoverBorderColor;
}
& when not (@theme = variable) {
box-shadow: @input-outline-offset @outline-blur-size @outline-width
fade(@borderColor, @outline-fade);
}
& when (@theme = variable) {
border-color: @hoverBorderColor;
box-shadow: @input-outline-offset @outline-blur-size @outline-width @outlineColor;
}
border-right-width: @border-width-base !important; border-right-width: @border-width-base !important;
outline: 0; outline: 0;
box-shadow: @input-outline-offset @outline-blur-size @outline-width fade(@color, 20%);
} }
// == when hoverd // == when hover
.hover(@color: @input-hover-border-color) { .hover(@color: @input-hover-border-color) {
border-color: @color; border-color: @color;
border-right-width: @border-width-base !important; border-right-width: @border-width-base !important;
} }
.disabled() { .disabled() {
color: @disabled-color; color: @input-disabled-color;
background-color: @input-disabled-bg; background-color: @input-disabled-bg;
border-color: @input-border-color;
box-shadow: none;
cursor: not-allowed; cursor: not-allowed;
opacity: 1; opacity: 1;
@ -46,6 +58,7 @@
position: relative; position: relative;
display: inline-block; display: inline-block;
width: 100%; width: 100%;
min-width: 0;
padding: @input-padding-vertical-base @input-padding-horizontal-base; padding: @input-padding-vertical-base @input-padding-horizontal-base;
color: @input-color; color: @input-color;
font-size: @font-size-base; font-size: @font-size-base;
@ -61,7 +74,8 @@
.hover(); .hover();
} }
&:focus { &:focus,
&-focused {
.active(); .active();
} }
@ -73,6 +87,19 @@
.disabled(); .disabled();
} }
&-borderless {
&,
&:hover,
&:focus,
&-focused,
&-disabled,
&[disabled] {
background-color: transparent;
border: none;
box-shadow: none;
}
}
// Reset height for `textarea`s // Reset height for `textarea`s
textarea& { textarea& {
max-width: 100%; // prevent textearea resize from coming out of its container max-width: 100%; // prevent textearea resize from coming out of its container
@ -151,6 +178,9 @@
&:hover { &:hover {
z-index: 1; z-index: 1;
border-right-width: 1px; border-right-width: 1px;
.@{ant-prefix}-input-search-with-button & {
z-index: 0;
}
} }
} }
@ -185,15 +215,15 @@
} }
} }
// Expand addon icon click area // https://github.com/ant-design/ant-design/issues/31333
// https://github.com/ant-design/ant-design/issues/3714 .@{ant-prefix}-cascader-picker {
> i:only-child::after { margin: -9px (-@control-padding-horizontal);
position: absolute; background-color: transparent;
top: 0; .@{ant-prefix}-cascader-input {
right: 0; text-align: left;
bottom: 0; border: 0;
left: 0; box-shadow: none;
content: ''; }
} }
} }
@ -262,6 +292,23 @@
height: @input-height-sm; height: @input-height-sm;
} }
.@{inputClass}-affix-wrapper {
&:not(:last-child) {
border-top-right-radius: 0;
border-bottom-right-radius: 0;
.@{ant-prefix}-input-search & {
border-top-left-radius: @border-radius-base;
border-bottom-left-radius: @border-radius-base;
}
}
&:not(:first-child),
.@{ant-prefix}-input-search &:not(:first-child) {
border-top-left-radius: 0;
border-bottom-left-radius: 0;
}
}
&&-compact { &&-compact {
display: block; display: block;
.clearfix(); .clearfix();
@ -293,6 +340,10 @@
display: inline-flex; display: inline-flex;
} }
& > .@{ant-prefix}-picker-range {
display: inline-flex;
}
& > *:not(:last-child) { & > *:not(:last-child) {
margin-right: -@border-width-base; margin-right: -@border-width-base;
border-right-width: @border-width-base; border-right-width: @border-width-base;
@ -305,11 +356,8 @@
// reset border for Select, DatePicker, AutoComplete, Cascader, Mention, TimePicker, Input // reset border for Select, DatePicker, AutoComplete, Cascader, Mention, TimePicker, Input
& > .@{ant-prefix}-select > .@{ant-prefix}-select-selector, & > .@{ant-prefix}-select > .@{ant-prefix}-select-selector,
& > .@{ant-prefix}-calendar-picker .@{ant-prefix}-input,
& > .@{ant-prefix}-select-auto-complete .@{ant-prefix}-input, & > .@{ant-prefix}-select-auto-complete .@{ant-prefix}-input,
& > .@{ant-prefix}-cascader-picker .@{ant-prefix}-input, & > .@{ant-prefix}-cascader-picker .@{ant-prefix}-input,
& > .@{ant-prefix}-mention-wrapper .@{ant-prefix}-mention-editor,
& > .@{ant-prefix}-time-picker .@{ant-prefix}-time-picker-input,
& > .@{ant-prefix}-input-group-wrapper .@{ant-prefix}-input { & > .@{ant-prefix}-input-group-wrapper .@{ant-prefix}-input {
border-right-width: @border-width-base; border-right-width: @border-width-base;
border-radius: 0; border-radius: 0;
@ -327,25 +375,23 @@
z-index: 1; z-index: 1;
} }
// update z-index for arrow icon
& > .@{ant-prefix}-select > .@{ant-prefix}-select-arrow {
z-index: 1; // https://github.com/ant-design/ant-design/issues/20371
}
& > *:first-child, & > *:first-child,
& > .@{ant-prefix}-select:first-child > .@{ant-prefix}-select-selector, & > .@{ant-prefix}-select:first-child > .@{ant-prefix}-select-selector,
& > .@{ant-prefix}-calendar-picker:first-child .@{ant-prefix}-input,
& > .@{ant-prefix}-select-auto-complete:first-child .@{ant-prefix}-input, & > .@{ant-prefix}-select-auto-complete:first-child .@{ant-prefix}-input,
& > .@{ant-prefix}-cascader-picker:first-child .@{ant-prefix}-input, & > .@{ant-prefix}-cascader-picker:first-child .@{ant-prefix}-input {
& > .@{ant-prefix}-mention-wrapper:first-child .@{ant-prefix}-mention-editor,
& > .@{ant-prefix}-time-picker:first-child .@{ant-prefix}-time-picker-input {
border-top-left-radius: @border-radius-base; border-top-left-radius: @border-radius-base;
border-bottom-left-radius: @border-radius-base; border-bottom-left-radius: @border-radius-base;
} }
& > *:last-child, & > *:last-child,
& > .@{ant-prefix}-select:last-child > .@{ant-prefix}-select-selector, & > .@{ant-prefix}-select:last-child > .@{ant-prefix}-select-selector,
& > .@{ant-prefix}-calendar-picker:last-child .@{ant-prefix}-input,
& > .@{ant-prefix}-select-auto-complete:last-child .@{ant-prefix}-input,
& > .@{ant-prefix}-cascader-picker:last-child .@{ant-prefix}-input, & > .@{ant-prefix}-cascader-picker:last-child .@{ant-prefix}-input,
& > .@{ant-prefix}-cascader-picker-focused:last-child .@{ant-prefix}-input, & > .@{ant-prefix}-cascader-picker-focused:last-child .@{ant-prefix}-input {
& > .@{ant-prefix}-mention-wrapper:last-child .@{ant-prefix}-mention-editor,
& > .@{ant-prefix}-time-picker:last-child .@{ant-prefix}-time-picker-input {
border-right-width: @border-width-base; border-right-width: @border-width-base;
border-top-right-radius: @border-radius-base; border-top-right-radius: @border-radius-base;
border-bottom-right-radius: @border-radius-base; border-bottom-right-radius: @border-radius-base;
@ -355,107 +401,24 @@
& > .@{ant-prefix}-select-auto-complete .@{ant-prefix}-input { & > .@{ant-prefix}-select-auto-complete .@{ant-prefix}-input {
vertical-align: top; vertical-align: top;
} }
.@{ant-prefix}-input-group-wrapper + .@{ant-prefix}-input-group-wrapper {
margin-left: -1px;
.@{ant-prefix}-input-affix-wrapper {
border-radius: 0;
} }
} }
.input-affix-wrapper(@inputClass) { .@{ant-prefix}-input-group-wrapper:not(:last-child) {
position: relative; &.@{ant-prefix}-input-search > .@{ant-prefix}-input-group {
display: inline-flex; & > .@{ant-prefix}-input-group-addon > .@{ant-prefix}-input-search-button {
border: @border-width-base @border-style-base @input-border-color; border-radius: 0;
border-radius: @border-radius-base;
padding: @input-padding-vertical-base @input-padding-horizontal-base;
width: 100%;
text-align: start;
background-color: @input-bg;
background-image: none;
color: @input-color;
font-size: @font-size-base;
line-height: @line-height-base;
&:hover {
.hover();
} }
&-disabled { & > .@{ant-prefix}-input {
.disabled(); border-radius: @border-radius-base 0 0 @border-radius-base;
}
&-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
// https://github.com/ant-design/ant-design/issues/18087
// https://github.com/ant-design/ant-design/issues/17414
// https://github.com/ant-design/ant-design/pull/17684
// https://codesandbox.io/embed/pensive-paper-di2wk
// https://codesandbox.io/embed/nifty-benz-gb7ml
.@{inputClass}-prefix,
.@{inputClass}-suffix {
display: flex;
align-items: center;
color: @input-color;
white-space: nowrap;
:not(.anticon) {
line-height: @line-height-base;
} }
} }
.@{inputClass}-disabled ~ .@{inputClass}-suffix {
.anticon {
color: @disabled-color;
cursor: not-allowed;
}
}
.@{inputClass}-prefix {
margin-right: @input-affix-margin;
}
.@{inputClass}-suffix {
margin-left: @input-affix-margin;
}
}
.clear-icon() {
color: @disabled-color;
font-size: @font-size-sm;
// https://github.com/ant-design/ant-design/pull/18151
// https://codesandbox.io/s/wizardly-sun-u10br
cursor: pointer;
transition: color 0.3s;
margin: 0 @input-affix-margin;
&:hover {
color: @text-color-secondary;
}
&:active {
color: @text-color;
}
+ i {
margin-left: 6px;
}
} }

View File

@ -0,0 +1,206 @@
@import '../../style/themes/index';
@import '../../style/mixins/index';
//== Style for input-group: input with label, with button or dropdown...
.@{ant-prefix}-input-group {
&-wrapper {
&-rtl {
direction: rtl;
}
}
&-rtl {
direction: rtl;
}
}
// affix
@input-affix-margin: 4px;
.@{ant-prefix}-input {
&-affix-wrapper&-affix-wrapper-rtl {
> input.@{ant-prefix}-input {
border: none;
outline: none;
}
}
&-affix-wrapper-rtl {
.@{ant-prefix}-input-prefix {
margin: 0 0 0 @input-affix-margin;
}
.@{ant-prefix}-input-suffix {
margin: 0 @input-affix-margin 0 0;
}
}
&-textarea {
&-rtl {
direction: rtl;
}
&-rtl&-show-count::after {
text-align: left;
}
}
}
// allow-clear
.@{ant-prefix}-input-clear-icon {
&-has-suffix {
.@{ant-prefix}-input-affix-wrapper-rtl & {
margin-right: 0;
margin-left: @input-affix-margin;
}
}
.@{ant-prefix}-input-affix-wrapper-rtl & {
right: auto;
left: 8px;
}
}
// mixin
@input-rtl-cls: ~'@{ant-prefix}-input-rtl';
.active() {
.@{input-rtl-cls} & {
border-right-width: 0;
border-left-width: @border-width-base !important;
}
}
.hover() {
.@{input-rtl-cls} & {
border-right-width: 0;
border-left-width: @border-width-base !important;
}
}
.input() {
&-rtl {
direction: rtl;
}
}
// label input
.input-group(@inputClass) {
> .@{inputClass}-rtl:first-child,
&-rtl &-addon:first-child {
border-radius: 0 @border-radius-base @border-radius-base 0;
}
&-addon:first-child {
.@{inputClass}-group-rtl & {
border-right: @border-width-base @border-style-base @input-border-color;
border-left: 0;
}
}
&-addon:last-child {
.@{inputClass}-group-rtl & {
border-right: 0;
border-left: @border-width-base @border-style-base @input-border-color;
}
}
> .@{inputClass}:last-child,
&-addon:last-child {
.@{inputClass}-group-rtl& {
border-radius: @border-radius-base 0 0 @border-radius-base;
}
}
.@{inputClass}-affix-wrapper {
&:not(:first-child) {
.@{inputClass}-group-rtl& {
border-radius: @border-radius-base 0 0 @border-radius-base;
}
}
&:not(:last-child) {
.@{inputClass}-group-rtl& {
border-radius: 0 @border-radius-base @border-radius-base 0;
}
}
}
&&-compact {
& > *:not(:last-child) {
.@{inputClass}-group-rtl& {
margin-right: 0;
margin-left: -@border-width-base;
border-left-width: @border-width-base;
}
}
& > *:first-child,
& > .@{ant-prefix}-select:first-child > .@{ant-prefix}-select-selector,
& > .@{ant-prefix}-select-auto-complete:first-child .@{ant-prefix}-input,
& > .@{ant-prefix}-cascader-picker:first-child .@{ant-prefix}-input {
.@{inputClass}-group-rtl& {
border-radius: 0 @border-radius-base @border-radius-base 0;
}
}
& > *:last-child,
& > .@{ant-prefix}-select:last-child > .@{ant-prefix}-select-selector,
& > .@{ant-prefix}-select-auto-complete:last-child .@{ant-prefix}-input,
& > .@{ant-prefix}-cascader-picker:last-child .@{ant-prefix}-input,
& > .@{ant-prefix}-cascader-picker-focused:last-child .@{ant-prefix}-input {
.@{inputClass}-group-rtl& {
border-left-width: @border-width-base;
border-radius: @border-radius-base 0 0 @border-radius-base;
}
}
.@{ant-prefix}-input-group-wrapper-rtl + .@{ant-prefix}-input-group-wrapper-rtl {
margin-right: -1px;
margin-left: 0;
}
.@{ant-prefix}-input-group-wrapper-rtl:not(:last-child) {
&.@{ant-prefix}-input-search > .@{ant-prefix}-input-group {
& > .@{ant-prefix}-input {
border-radius: 0 @border-radius-base @border-radius-base 0;
}
}
}
}
}
// search-input
@search-prefix: ~'@{ant-prefix}-input-search';
@search-rtl-cls: ~'@{search-prefix}-rtl';
.@{search-prefix}-rtl {
direction: rtl;
.@{ant-prefix}-input {
&:hover,
&:focus {
+ .@{ant-prefix}-input-group-addon .@{search-prefix}-button:not(.@{ant-prefix}-btn-primary) {
border-right-color: @input-hover-border-color;
border-left-color: @border-color-base;
}
}
}
> .@{ant-prefix}-input-group {
> .@{ant-prefix}-input-affix-wrapper {
&:hover,
&-focused {
border-right-color: @input-hover-border-color;
}
}
> .@{ant-prefix}-input-group-addon {
right: -1px;
left: auto;
.@{search-prefix}-button {
border-radius: @border-radius-base 0 0 @border-radius-base;
}
}
}
}

View File

@ -11,6 +11,9 @@
// -------- Colors ----------- // -------- Colors -----------
@primary-color: @blue-6; @primary-color: @blue-6;
@primary-color-hover: color(~`colorPalette('@{primary-color}', 5) `);
@primary-color-active: color(~`colorPalette('@{primary-color}', 7) `);
@primary-color-outline: fade(@primary-color, @outline-fade);
@info-color: @primary-color; @info-color: @primary-color;
@success-color: @green-6; @success-color: @green-6;
@processing-color: @blue-6; @processing-color: @blue-6;
@ -141,6 +144,7 @@
@outline-blur-size: 0; @outline-blur-size: 0;
@outline-width: 2px; @outline-width: 2px;
@outline-color: @primary-color; @outline-color: @primary-color;
@outline-fade: 20%;
@background-color-light: hsv(0, 0, 98%); // background of header and selected item @background-color-light: hsv(0, 0, 98%); // background of header and selected item
@background-color-base: hsv(0, 0, 96%); // Default grey background color @background-color-base: hsv(0, 0, 96%); // Default grey background color
@ -377,16 +381,26 @@
// Input // Input
// --- // ---
@input-height-base: 32px; @input-height-base: @height-base;
@input-height-lg: 40px; @input-height-lg: @height-lg;
@input-height-sm: 24px; @input-height-sm: @height-sm;
@input-padding-horizontal: @control-padding-horizontal - 1px; @input-padding-horizontal: @control-padding-horizontal - 1px;
@input-padding-horizontal-base: @input-padding-horizontal; @input-padding-horizontal-base: @input-padding-horizontal;
@input-padding-horizontal-sm: @control-padding-horizontal-sm - 1px; @input-padding-horizontal-sm: @control-padding-horizontal-sm - 1px;
@input-padding-horizontal-lg: @input-padding-horizontal; @input-padding-horizontal-lg: @input-padding-horizontal;
@input-padding-vertical-base: 4px; @input-padding-vertical-base: max(
@input-padding-vertical-sm: 0px; (round(((@input-height-base - @font-size-base * @line-height-base) / 2) * 10) / 10) -
@input-padding-vertical-lg: 6.5px; @border-width-base,
3px
);
@input-padding-vertical-sm: max(
(round(((@input-height-sm - @font-size-base * @line-height-base) / 2) * 10) / 10) -
@border-width-base,
0
);
@input-padding-vertical-lg: (
ceil(((@input-height-lg - @font-size-lg * @line-height-base) / 2) * 10) / 10
) - @border-width-base;
@input-placeholder-color: hsv(0, 0, 75%); @input-placeholder-color: hsv(0, 0, 75%);
@input-color: @text-color; @input-color: @text-color;
@input-icon-color: @input-color; @input-icon-color: @input-color;
@ -402,6 +416,7 @@
@input-disabled-bg: @disabled-bg; @input-disabled-bg: @disabled-bg;
@input-outline-offset: 0 0; @input-outline-offset: 0 0;
@input-icon-hover-color: fade(@black, 85%); @input-icon-hover-color: fade(@black, 85%);
@input-disabled-color: @disabled-color;
// Mentions // Mentions
// --- // ---