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 (
e.preventDefault()}
class={classNames(
{
[`${className}-hidden`]: !needClear,
[`${className}-has-suffix`]: !!suffix,
},
className,
)}
role="button"
tabindex={-1}
>
{iconNode}
);
};
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) && (
{getClearIcon()}
{suffix}
);
element = (
{prefix && {prefix}}
{cloneElement(inputElement, {
style: null,
value,
hidden: null,
})}
{suffixNode}
);
}
// ================== 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 (
{addonBefore && {addonBefore}}
{cloneElement(element, { style: null, hidden: null })}
{addonAfter && {addonAfter}}
);
}
return element;
};
},
});