import classNames from 'classnames'; import Icon from '../icon'; import { getInputClassName } from './Input'; import PropTypes from '../_util/vue-types'; import { cloneElement } from '../_util/vnode'; import { getComponentFromProp } from '../_util/props-util'; export function hasPrefixSuffix(instance) { return !!( getComponentFromProp(instance, 'prefix') || getComponentFromProp(instance, 'suffix') || instance.$props.allowClear ); } const ClearableInputType = ['text', 'input']; const ClearableLabeledInput = { props: { prefixCls: PropTypes.string, inputType: PropTypes.oneOf(ClearableInputType), value: PropTypes.any, defaultValue: PropTypes.any, allowClear: PropTypes.bool, element: PropTypes.any, handleReset: PropTypes.func, disabled: PropTypes.bool, size: PropTypes.oneOf(['small', 'large', 'default']), suffix: PropTypes.any, prefix: PropTypes.any, addonBefore: PropTypes.any, addonAfter: PropTypes.any, className: PropTypes.string, readOnly: PropTypes.bool, }, methods: { renderClearIcon(prefixCls) { 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) { const { suffix, allowClear } = this.$props; if (suffix || allowClear) { return ( {this.renderClearIcon(prefixCls)} {suffix} ); } return null; }, renderLabeledIcon(prefixCls, element) { const props = this.$props; const suffix = this.renderSuffix(prefixCls); if (!hasPrefixSuffix(this)) { return cloneElement(element, { props: { value: props.value }, }); } const prefix = props.prefix ? ( {props.prefix} ) : null; const affixWrapperCls = classNames(props.className, `${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, props: { value: props.value }, class: getInputClassName(prefixCls, props.size, props.disabled), })} {suffix} ); }, renderInputWithLabel(prefixCls, labeledElement) { const { addonBefore, addonAfter, style, size, className } = this.$props; // 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, element) { const { value, allowClear, className, style } = this.$props; if (!allowClear) { return cloneElement(element, { props: { value }, }); } const affixWrapperCls = classNames( className, `${prefixCls}-affix-wrapper`, `${prefixCls}-affix-wrapper-textarea-with-clear-btn`, ); return ( {cloneElement(element, { style: null, props: { value }, })} {this.renderClearIcon(prefixCls)} ); }, renderClearableLabeledInput() { const { prefixCls, inputType, element } = this.$props; if (inputType === ClearableInputType[0]) { return this.renderTextAreaWithClearIcon(prefixCls, element); } return this.renderInputWithLabel(prefixCls, this.renderLabeledIcon(prefixCls, element)); }, }, render() { return this.renderClearableLabeledInput(); }, }; export default ClearableLabeledInput;