import classNames from '../_util/classNames';
import CloseCircleFilled from '@ant-design/icons-vue/CloseCircleFilled';
import { getInputClassName } from './Input';
import PropTypes from '../_util/vue-types';
import { cloneElement } from '../_util/vnode';
import { getComponent } from '../_util/props-util';
import { defineComponent, VNode } from 'vue';
import { tuple } from '../_util/type';
export function hasPrefixSuffix(instance: any) {
return !!(
getComponent(instance, 'prefix') ||
getComponent(instance, 'suffix') ||
instance.$props.allowClear
);
}
const ClearableInputType = ['text', 'input'];
const ClearableLabeledInput = defineComponent({
name: 'ClearableLabeledInput',
inheritAttrs: false,
props: {
prefixCls: PropTypes.string,
inputType: PropTypes.oneOf(tuple('text', 'input')),
value: PropTypes.any,
defaultValue: PropTypes.any,
allowClear: PropTypes.looseBool,
element: PropTypes.VNodeChild,
handleReset: PropTypes.func,
disabled: PropTypes.looseBool,
size: PropTypes.oneOf(tuple('small', 'large', 'default')),
suffix: PropTypes.VNodeChild,
prefix: PropTypes.VNodeChild,
addonBefore: PropTypes.VNodeChild,
addonAfter: PropTypes.VNodeChild,
readonly: PropTypes.looseBool,
},
methods: {
renderClearIcon(prefixCls: string) {
const { allowClear, value, disabled, readonly, inputType, handleReset } = this.$props;
if (
!allowClear ||
disabled ||
readonly ||
value === undefined ||
value === null ||
value === ''
) {
return null;
}
const className =
inputType === ClearableInputType[0]
? `${prefixCls}-textarea-clear-icon`
: `${prefixCls}-clear-icon`;
return ;
},
renderSuffix(prefixCls: string) {
const { suffix, allowClear } = this.$props;
if (suffix || allowClear) {
return (
{this.renderClearIcon(prefixCls)}
{suffix}
);
}
return null;
},
renderLabeledIcon(prefixCls: string, element: VNode): VNode {
const props = this.$props;
const suffix = this.renderSuffix(prefixCls);
if (!hasPrefixSuffix(this)) {
return cloneElement(element, {
value: props.value,
});
}
const prefix = props.prefix ? (
{props.prefix}
) : null;
const affixWrapperCls = classNames(this.$attrs?.class, `${prefixCls}-affix-wrapper`, {
[`${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 (
{prefix}
{cloneElement(element, {
style: null,
value: props.value,
class: getInputClassName(prefixCls, props.size, props.disabled),
})}
{suffix}
) as VNode;
},
renderInputWithLabel(prefixCls: string, labeledElement: VNode) {
const { addonBefore, addonAfter, size } = this.$props;
const { style, class: className } = this.$attrs;
// Not wrap when there is not addons
if (!addonBefore && !addonAfter) {
return labeledElement;
}
const wrapperClassName = `${prefixCls}-group`;
const addonClassName = `${wrapperClassName}-addon`;
const addonBeforeNode = addonBefore ? (
{addonBefore}
) : null;
const addonAfterNode = addonAfter ? {addonAfter} : null;
const mergedWrapperClassName = classNames(`${prefixCls}-wrapper`, {
[wrapperClassName]: addonBefore || addonAfter,
});
const mergedGroupClassName = classNames(className, `${prefixCls}-group-wrapper`, {
[`${prefixCls}-group-wrapper-sm`]: size === 'small',
[`${prefixCls}-group-wrapper-lg`]: size === 'large',
});
// Need another wrapper for changing display:table to display:inline-block
// and put style prop in wrapper
return (
{addonBeforeNode}
{cloneElement(labeledElement, { style: null })}
{addonAfterNode}
);
},
renderTextAreaWithClearIcon(prefixCls: string, element: VNode) {
const { value, allowClear } = this.$props;
const { style, class: className } = this.$attrs;
if (!allowClear) {
return cloneElement(element, { value });
}
const affixWrapperCls = classNames(
className,
`${prefixCls}-affix-wrapper`,
`${prefixCls}-affix-wrapper-textarea-with-clear-btn`,
);
return (
{cloneElement(element, {
style: null,
value,
})}
{this.renderClearIcon(prefixCls)}
);
},
renderClearableLabeledInput() {
const { prefixCls, inputType, element } = this.$props as any;
if (inputType === ClearableInputType[0]) {
return this.renderTextAreaWithClearIcon(prefixCls, element);
}
return this.renderInputWithLabel(prefixCls, this.renderLabeledIcon(prefixCls, element));
},
},
render() {
return this.renderClearableLabeledInput();
},
});
export default ClearableLabeledInput;