You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
ant-design-vue/components/vc-input/BaseInput.tsx

153 lines
4.5 KiB

import type { CSSProperties } from 'vue';
import { defineComponent, ref } from 'vue';
import classNames from '../_util/classNames';
import type { MouseEventHandler } from '../_util/EventInterface';
import { cloneElement } from '../_util/vnode';
import { baseInputProps } from './inputProps';
import { hasAddon, hasPrefixSuffix } from './utils/commonUtils';
export default defineComponent({
name: 'BaseInput',
inheritAttrs: false,
props: baseInputProps(),
setup(props, { slots, attrs }) {
const containerRef = ref();
const onInputMouseDown: MouseEventHandler = e => {
if (containerRef.value?.contains(e.target as Element)) {
const { triggerFocus } = props;
triggerFocus?.();
}
};
const getClearIcon = () => {
const {
allowClear,
value,
disabled,
readonly,
handleReset,
suffix = slots.suffix,
prefixCls,
} = props;
if (!allowClear) {
return null;
}
const needClear = !disabled && !readonly && value;
const className = `${prefixCls}-clear-icon`;
const iconNode = slots.clearIcon?.() || '*';
return (
<span
onClick={handleReset}
// Do not trigger onBlur when clear input
onMousedown={e => e.preventDefault()}
class={classNames(
{
[`${className}-hidden`]: !needClear,
[`${className}-has-suffix`]: !!suffix,
},
className,
)}
role="button"
tabindex={-1}
>
{iconNode}
</span>
);
};
return () => {
const {
focused,
value,
disabled,
allowClear,
readonly,
hidden,
prefixCls,
prefix = slots.prefix?.(),
suffix = slots.suffix?.(),
addonAfter = slots.addonAfter,
addonBefore = slots.addonBefore,
inputElement,
affixWrapperClassName,
wrapperClassName,
groupClassName,
} = props;
let element = cloneElement(inputElement, {
value,
hidden,
});
// ================== Prefix & Suffix ================== //
if (hasPrefixSuffix({ prefix, suffix, allowClear })) {
const affixWrapperPrefixCls = `${prefixCls}-affix-wrapper`;
const affixWrapperCls = classNames(
affixWrapperPrefixCls,
{
[`${affixWrapperPrefixCls}-disabled`]: disabled,
[`${affixWrapperPrefixCls}-focused`]: focused,
[`${affixWrapperPrefixCls}-readonly`]: readonly,
[`${affixWrapperPrefixCls}-input-with-clear-btn`]: suffix && allowClear && value,
},
!hasAddon({ addonAfter, addonBefore }) && attrs.class,
affixWrapperClassName,
);
const suffixNode = (suffix || allowClear) && (
<span class={`${prefixCls}-suffix`}>
{getClearIcon()}
{suffix}
</span>
);
element = (
<span
class={affixWrapperCls}
style={attrs.style as CSSProperties}
hidden={!hasAddon({ addonAfter, addonBefore }) && hidden}
onMousedown={onInputMouseDown}
ref={containerRef}
>
{prefix && <span class={`${prefixCls}-prefix`}>{prefix}</span>}
{cloneElement(inputElement, {
style: null,
value,
hidden: null,
})}
{suffixNode}
</span>
);
}
// ================== Addon ================== //
if (hasAddon({ addonAfter, addonBefore })) {
const wrapperCls = `${prefixCls}-group`;
const addonCls = `${wrapperCls}-addon`;
const mergedWrapperClassName = classNames(
`${prefixCls}-wrapper`,
wrapperCls,
wrapperClassName,
);
const mergedGroupClassName = classNames(
`${prefixCls}-group-wrapper`,
attrs.class,
groupClassName,
);
// Need another wrapper for changing display:table to display:inline-block
// and put style prop in wrapper
return (
<span class={mergedGroupClassName} style={attrs.style as CSSProperties} hidden={hidden}>
<span class={mergedWrapperClassName}>
{addonBefore && <span class={addonCls}>{addonBefore}</span>}
{cloneElement(element, { style: null, hidden: null })}
{addonAfter && <span class={addonCls}>{addonAfter}</span>}
</span>
</span>
);
}
return element;
};
},
});