Skip to content

Commit d716421

Browse files
committed
feat: mentions add status
1 parent c6f6922 commit d716421

File tree

8 files changed

+124
-10
lines changed

8 files changed

+124
-10
lines changed

components/mentions/demo/index.vue

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
<readonly />
77
<placement />
88
<FormMentions />
9+
<statusVue />
910
</demo-sort>
1011
</template>
1112
<script>
@@ -15,6 +16,7 @@ import FormMentions from './form.vue';
1516
import Prefix from './prefix.vue';
1617
import Readonly from './readonly.vue';
1718
import Placement from './placement.vue';
19+
import statusVue from './status.vue';
1820
import CN from '../index.zh-CN.md';
1921
import US from '../index.en-US.md';
2022
import { defineComponent } from 'vue';
@@ -23,6 +25,7 @@ export default defineComponent({
2325
CN,
2426
US,
2527
components: {
28+
statusVue,
2629
Basic,
2730
Async,
2831
Prefix,

components/mentions/demo/status.vue

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
<docs>
2+
---
3+
order: 8
4+
title:
5+
zh-CN: 自定义状态
6+
en-US: Status
7+
---
8+
9+
## zh-CN
10+
11+
使用 `status` 为 Mentions 添加状态。可选 `error` 或者 `warning`。
12+
13+
## en-US
14+
15+
Add status to Mentions with `status`, which could be `error` or `warning`。
16+
17+
</docs>
18+
<template>
19+
<a-space direction="vertical">
20+
<a-mentions v-model:value="value" autofocus status="error" @select="onSelect">
21+
<a-mentions-option value="afc163">afc163</a-mentions-option>
22+
<a-mentions-option value="zombieJ">zombieJ</a-mentions-option>
23+
<a-mentions-option value="yesmeck">yesmeck</a-mentions-option>
24+
</a-mentions>
25+
<a-mentions v-model:value="value" autofocus status="warning" @select="onSelect">
26+
<a-mentions-option value="afc163">afc163</a-mentions-option>
27+
<a-mentions-option value="zombieJ">zombieJ</a-mentions-option>
28+
<a-mentions-option value="yesmeck">yesmeck</a-mentions-option>
29+
</a-mentions>
30+
</a-space>
31+
</template>
32+
<script lang="ts">
33+
import { defineComponent, ref, watch } from 'vue';
34+
export default defineComponent({
35+
setup() {
36+
const value = ref<string>('@afc163');
37+
watch(value, () => {
38+
console.log('value', value);
39+
});
40+
const onSelect = (option: { value: string }) => {
41+
console.log('select', option);
42+
};
43+
44+
return {
45+
value,
46+
onSelect,
47+
};
48+
},
49+
});
50+
</script>

components/mentions/index.en-US.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ When you need to mention someone or something.
1616
### Mention
1717

1818
| Property | Description | Type | Default |
19-
| --- | --- | --- | --- |
19+
| --- | --- | --- | --- | --- |
2020
| autofocus | Auto get focus when component mounted | boolean | `false` |
2121
| defaultValue | Default value | string | |
2222
| filterOption | Customize filter option logic | false \| (input: string, option: OptionProps) => boolean | |
@@ -25,6 +25,7 @@ When you need to mention someone or something.
2525
| placement | Set popup placement | `top` \| `bottom` | `bottom` |
2626
| prefix | Set trigger prefix keyword | string \| string\[] | '@' |
2727
| split | Set split string before and after selected mention | string | ' ' |
28+
| status | Set validation status | 'error' \| 'warning' \| 'success' \| 'validating' | - | 3.3.0 |
2829
| validateSearch | Customize trigger search logic | (text: string, props: MentionsProps) => void | |
2930
| value(v-model) | Set value of mentions | string | |
3031

components/mentions/index.tsx

Lines changed: 37 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,17 @@
11
import type { App, PropType, ExtractPropTypes } from 'vue';
2-
import { watch, ref, onMounted, defineComponent, nextTick } from 'vue';
2+
import { computed, watch, ref, onMounted, defineComponent, nextTick } from 'vue';
33
import classNames from '../_util/classNames';
44
import PropTypes from '../_util/vue-types';
55
import VcMentions, { Option } from '../vc-mentions';
66
import { mentionsProps as baseMentionsProps } from '../vc-mentions/src/mentionsProps';
77
import useConfigInject from '../_util/hooks/useConfigInject';
88
import { flattenChildren, getOptionProps } from '../_util/props-util';
9-
import { useInjectFormItemContext } from '../form/FormItemContext';
9+
import { FormItemInputContext, useInjectFormItemContext } from '../form/FormItemContext';
1010
import omit from '../_util/omit';
1111
import { optionProps } from '../vc-mentions/src/Option';
1212
import type { KeyboardEventHandler } from '../_util/EventInterface';
13+
import type { InputStatus } from '../_util/statusUtils';
14+
import { getStatusClassNames, getMergedStatus } from '../_util/statusUtils';
1315

1416
interface MentionsConfig {
1517
prefix?: string | string[];
@@ -83,6 +85,7 @@ export const mentionsProps = () => ({
8385
notFoundContent: PropTypes.any,
8486
defaultValue: String,
8587
id: String,
88+
status: String as PropType<InputStatus>,
8689
});
8790

8891
export type MentionsProps = Partial<ExtractPropTypes<ReturnType<typeof mentionsProps>>>;
@@ -98,6 +101,8 @@ const Mentions = defineComponent({
98101
const vcMentions = ref(null);
99102
const value = ref(props.value ?? props.defaultValue ?? '');
100103
const formItemContext = useInjectFormItemContext();
104+
const formItemInputContext = FormItemInputContext.useInject();
105+
const mergedStatus = computed(() => getMergedStatus(formItemInputContext.status, props.status));
101106
watch(
102107
() => props.value,
103108
val => {
@@ -174,14 +179,19 @@ const Mentions = defineComponent({
174179
id = formItemContext.id.value,
175180
...restProps
176181
} = props;
182+
const { hasFeedback, feedbackIcon } = formItemInputContext;
177183
const { class: className, ...otherAttrs } = attrs;
178184
const otherProps = omit(restProps, ['defaultValue', 'onUpdate:value', 'prefixCls']);
179185

180-
const mergedClassName = classNames(className, {
181-
[`${prefixCls.value}-disabled`]: disabled,
182-
[`${prefixCls.value}-focused`]: focused.value,
183-
[`${prefixCls.value}-rtl`]: direction.value === 'rtl',
184-
});
186+
const mergedClassName = classNames(
187+
{
188+
[`${prefixCls.value}-disabled`]: disabled,
189+
[`${prefixCls.value}-focused`]: focused.value,
190+
[`${prefixCls.value}-rtl`]: direction.value === 'rtl',
191+
},
192+
getStatusClassNames(prefixCls.value, mergedStatus.value),
193+
!hasFeedback && className,
194+
);
185195

186196
const mentionsProps = {
187197
prefixCls: prefixCls.value,
@@ -202,12 +212,31 @@ const Mentions = defineComponent({
202212
value: value.value,
203213
id,
204214
};
205-
return (
215+
const mentions = (
206216
<VcMentions
207217
{...mentionsProps}
208218
v-slots={{ notFoundContent: getNotFoundContent, option: slots.option }}
209219
></VcMentions>
210220
);
221+
if (hasFeedback) {
222+
return (
223+
<div
224+
class={classNames(
225+
`${prefixCls.value}-affix-wrapper`,
226+
getStatusClassNames(
227+
`${prefixCls.value}-affix-wrapper`,
228+
mergedStatus.value,
229+
hasFeedback,
230+
),
231+
className,
232+
)}
233+
>
234+
{mentions}
235+
<span class={`${prefixCls.value}-suffix`}>{feedbackIcon}</span>
236+
</div>
237+
);
238+
}
239+
return mentions;
211240
};
212241
},
213242
});

components/mentions/index.zh-CN.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ cover: https://gw.alipayobjects.com/zos/alicdn/jPE-itMFM/Mentions.svg
1717
### Mentions
1818

1919
| 参数 | 说明 | 类型 | 默认值 |
20-
| --- | --- | --- | --- |
20+
| --- | --- | --- | --- | --- |
2121
| autofocus | 自动获得焦点 | boolean | `false` |
2222
| defaultValue | 默认值 | string | |
2323
| filterOption | 自定义过滤逻辑 | false \| (input: string, option: OptionProps) => boolean | |
@@ -26,6 +26,7 @@ cover: https://gw.alipayobjects.com/zos/alicdn/jPE-itMFM/Mentions.svg
2626
| placement | 弹出层展示位置 | `top` \| `bottom` | `bottom` |
2727
| prefix | 设置触发关键字 | string \| string\[] | '@' |
2828
| split | 设置选中项前后分隔符 | string | ' ' |
29+
| status | 设置校验状态 | 'error' \| 'warning' | - | 3.3.0 |
2930
| validateSearch | 自定义触发验证逻辑 | (text: string, props: MentionsProps) => void | |
3031
| value(v-model) | 设置值 | string | |
3132

components/mentions/style/index.less

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
@import '../../style/themes/index';
22
@import '../../style/mixins/index';
33
@import '../../input/style/mixin';
4+
@import './status';
45

56
@mention-prefix-cls: ~'@{ant-prefix}-mentions';
67

@@ -162,6 +163,17 @@
162163
}
163164
}
164165
}
166+
167+
&-suffix {
168+
position: absolute;
169+
top: 0;
170+
right: @input-padding-horizontal-base;
171+
bottom: 0;
172+
z-index: 1;
173+
display: inline-flex;
174+
align-items: center;
175+
margin: auto;
176+
}
165177
}
166178

167179
@import './rtl';

components/mentions/style/index.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,5 @@ import './index.less';
33
// style dependencies
44
import '../../empty/style';
55
import '../../spin/style';
6+
7+
// deps-lint-skip: form

components/mentions/style/status.less

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
@import '../../input/style/mixin';
2+
3+
@mention-prefix-cls: ~'@{ant-prefix}-mentions';
4+
@input-prefix-cls: ~'@{ant-prefix}-input';
5+
6+
.@{mention-prefix-cls} {
7+
&-status-error {
8+
.status-color(@mention-prefix-cls, @error-color, @error-color, @input-bg, @error-color-hover, @error-color-outline);
9+
.status-color-common(@input-prefix-cls, @error-color, @error-color, @input-bg, @error-color-hover, @error-color-outline);
10+
}
11+
12+
&-status-warning {
13+
.status-color(@mention-prefix-cls, @warning-color, @warning-color, @input-bg, @warning-color-hover, @warning-color-outline);
14+
.status-color-common(@input-prefix-cls, @warning-color, @warning-color, @input-bg, @warning-color-hover, @warning-color-outline);
15+
}
16+
}

0 commit comments

Comments
 (0)