diff --git a/components/mentions/demo/index.vue b/components/mentions/demo/index.vue index 9273b77f7..882b4098b 100644 --- a/components/mentions/demo/index.vue +++ b/components/mentions/demo/index.vue @@ -6,6 +6,7 @@ + diff --git a/components/mentions/index.en-US.md b/components/mentions/index.en-US.md index 98622483f..b28e913b5 100644 --- a/components/mentions/index.en-US.md +++ b/components/mentions/index.en-US.md @@ -16,7 +16,7 @@ When you need to mention someone or something. ### Mention | Property | Description | Type | Default | -| --- | --- | --- | --- | +| --- | --- | --- | --- | --- | | autofocus | Auto get focus when component mounted | boolean | `false` | | defaultValue | Default value | string | | | filterOption | Customize filter option logic | false \| (input: string, option: OptionProps) => boolean | | @@ -25,6 +25,7 @@ When you need to mention someone or something. | placement | Set popup placement | `top` \| `bottom` | `bottom` | | prefix | Set trigger prefix keyword | string \| string\[] | '@' | | split | Set split string before and after selected mention | string | ' ' | +| status | Set validation status | 'error' \| 'warning' \| 'success' \| 'validating' | - | 3.3.0 | | validateSearch | Customize trigger search logic | (text: string, props: MentionsProps) => void | | | value(v-model) | Set value of mentions | string | | diff --git a/components/mentions/index.tsx b/components/mentions/index.tsx index d4e14cfae..ad805776c 100644 --- a/components/mentions/index.tsx +++ b/components/mentions/index.tsx @@ -1,15 +1,17 @@ import type { App, PropType, ExtractPropTypes } from 'vue'; -import { watch, ref, onMounted, defineComponent, nextTick } from 'vue'; +import { computed, watch, ref, onMounted, defineComponent, nextTick } from 'vue'; import classNames from '../_util/classNames'; import PropTypes from '../_util/vue-types'; import VcMentions, { Option } from '../vc-mentions'; import { mentionsProps as baseMentionsProps } from '../vc-mentions/src/mentionsProps'; import useConfigInject from '../_util/hooks/useConfigInject'; import { flattenChildren, getOptionProps } from '../_util/props-util'; -import { useInjectFormItemContext } from '../form/FormItemContext'; +import { FormItemInputContext, useInjectFormItemContext } from '../form/FormItemContext'; import omit from '../_util/omit'; import { optionProps } from '../vc-mentions/src/Option'; import type { KeyboardEventHandler } from '../_util/EventInterface'; +import type { InputStatus } from '../_util/statusUtils'; +import { getStatusClassNames, getMergedStatus } from '../_util/statusUtils'; interface MentionsConfig { prefix?: string | string[]; @@ -83,6 +85,7 @@ export const mentionsProps = () => ({ notFoundContent: PropTypes.any, defaultValue: String, id: String, + status: String as PropType, }); export type MentionsProps = Partial>>; @@ -98,6 +101,8 @@ const Mentions = defineComponent({ const vcMentions = ref(null); const value = ref(props.value ?? props.defaultValue ?? ''); const formItemContext = useInjectFormItemContext(); + const formItemInputContext = FormItemInputContext.useInject(); + const mergedStatus = computed(() => getMergedStatus(formItemInputContext.status, props.status)); watch( () => props.value, val => { @@ -174,14 +179,19 @@ const Mentions = defineComponent({ id = formItemContext.id.value, ...restProps } = props; + const { hasFeedback, feedbackIcon } = formItemInputContext; const { class: className, ...otherAttrs } = attrs; const otherProps = omit(restProps, ['defaultValue', 'onUpdate:value', 'prefixCls']); - const mergedClassName = classNames(className, { - [`${prefixCls.value}-disabled`]: disabled, - [`${prefixCls.value}-focused`]: focused.value, - [`${prefixCls.value}-rtl`]: direction.value === 'rtl', - }); + const mergedClassName = classNames( + { + [`${prefixCls.value}-disabled`]: disabled, + [`${prefixCls.value}-focused`]: focused.value, + [`${prefixCls.value}-rtl`]: direction.value === 'rtl', + }, + getStatusClassNames(prefixCls.value, mergedStatus.value), + !hasFeedback && className, + ); const mentionsProps = { prefixCls: prefixCls.value, @@ -202,12 +212,31 @@ const Mentions = defineComponent({ value: value.value, id, }; - return ( + const mentions = ( ); + if (hasFeedback) { + return ( +
+ {mentions} + {feedbackIcon} +
+ ); + } + return mentions; }; }, }); diff --git a/components/mentions/index.zh-CN.md b/components/mentions/index.zh-CN.md index 54f407251..0afd11e1d 100644 --- a/components/mentions/index.zh-CN.md +++ b/components/mentions/index.zh-CN.md @@ -17,7 +17,7 @@ cover: https://gw.alipayobjects.com/zos/alicdn/jPE-itMFM/Mentions.svg ### Mentions | 参数 | 说明 | 类型 | 默认值 | -| --- | --- | --- | --- | +| --- | --- | --- | --- | --- | | autofocus | 自动获得焦点 | boolean | `false` | | defaultValue | 默认值 | string | | | filterOption | 自定义过滤逻辑 | false \| (input: string, option: OptionProps) => boolean | | @@ -26,6 +26,7 @@ cover: https://gw.alipayobjects.com/zos/alicdn/jPE-itMFM/Mentions.svg | placement | 弹出层展示位置 | `top` \| `bottom` | `bottom` | | prefix | 设置触发关键字 | string \| string\[] | '@' | | split | 设置选中项前后分隔符 | string | ' ' | +| status | 设置校验状态 | 'error' \| 'warning' | - | 3.3.0 | | validateSearch | 自定义触发验证逻辑 | (text: string, props: MentionsProps) => void | | | value(v-model) | 设置值 | string | | diff --git a/components/mentions/style/index.less b/components/mentions/style/index.less index c18683fca..06e2b1f29 100644 --- a/components/mentions/style/index.less +++ b/components/mentions/style/index.less @@ -1,6 +1,7 @@ @import '../../style/themes/index'; @import '../../style/mixins/index'; @import '../../input/style/mixin'; +@import './status'; @mention-prefix-cls: ~'@{ant-prefix}-mentions'; @@ -162,6 +163,17 @@ } } } + + &-suffix { + position: absolute; + top: 0; + right: @input-padding-horizontal-base; + bottom: 0; + z-index: 1; + display: inline-flex; + align-items: center; + margin: auto; + } } @import './rtl'; diff --git a/components/mentions/style/index.tsx b/components/mentions/style/index.tsx index 5fa72cf4f..b39860748 100644 --- a/components/mentions/style/index.tsx +++ b/components/mentions/style/index.tsx @@ -3,3 +3,5 @@ import './index.less'; // style dependencies import '../../empty/style'; import '../../spin/style'; + +// deps-lint-skip: form diff --git a/components/mentions/style/status.less b/components/mentions/style/status.less new file mode 100644 index 000000000..92d61e337 --- /dev/null +++ b/components/mentions/style/status.less @@ -0,0 +1,16 @@ +@import '../../input/style/mixin'; + +@mention-prefix-cls: ~'@{ant-prefix}-mentions'; +@input-prefix-cls: ~'@{ant-prefix}-input'; + +.@{mention-prefix-cls} { + &-status-error { + .status-color(@mention-prefix-cls, @error-color, @error-color, @input-bg, @error-color-hover, @error-color-outline); + .status-color-common(@input-prefix-cls, @error-color, @error-color, @input-bg, @error-color-hover, @error-color-outline); + } + + &-status-warning { + .status-color(@mention-prefix-cls, @warning-color, @warning-color, @input-bg, @warning-color-hover, @warning-color-outline); + .status-color-common(@input-prefix-cls, @warning-color, @warning-color, @input-bg, @warning-color-hover, @warning-color-outline); + } +}