Skip to content

Commit ab5f9c9

Browse files
authored
refactor(mentions): use compositionAPI (#4313)
1 parent d5952c0 commit ab5f9c9

13 files changed

+496
-506
lines changed

components/mentions/index.tsx

+93-102
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,14 @@
11
import type { App, PropType, VNodeTypes, Plugin, ExtractPropTypes } from 'vue';
2-
import { defineComponent, inject, nextTick } from 'vue';
2+
import { ref, onMounted } from 'vue';
3+
import { defineComponent, nextTick } from 'vue';
34
import classNames from '../_util/classNames';
45
import omit from 'omit.js';
56
import PropTypes from '../_util/vue-types';
67
import VcMentions from '../vc-mentions';
78
import { mentionsProps as baseMentionsProps } from '../vc-mentions/src/mentionsProps';
89
import Spin from '../spin';
9-
import BaseMixin from '../_util/BaseMixin';
10-
import { defaultConfigProvider } from '../config-provider';
11-
import { getOptionProps, getComponent, getSlot } from '../_util/props-util';
1210
import type { RenderEmptyHandler } from '../config-provider/renderEmpty';
11+
import useConfigInject from '../_util/hooks/useConfigInject';
1312

1413
const { Option } = VcMentions;
1514

@@ -79,65 +78,46 @@ export type MentionsProps = Partial<ExtractPropTypes<typeof mentionsProps>>;
7978

8079
const Mentions = defineComponent({
8180
name: 'AMentions',
82-
mixins: [BaseMixin],
8381
inheritAttrs: false,
84-
Option: { ...Option, name: 'AMentionsOption' },
85-
getMentions,
8682
props: mentionsProps,
83+
getMentions,
8784
emits: ['update:value', 'change', 'focus', 'blur', 'select'],
88-
setup() {
89-
return {
90-
configProvider: inject('configProvider', defaultConfigProvider),
85+
setup(props, { slots, emit, attrs, expose }) {
86+
const { prefixCls, renderEmpty, direction } = useConfigInject('mentions', props);
87+
const focused = ref(false);
88+
const vcMentions = ref(null);
89+
90+
const handleFocus = (e: FocusEvent) => {
91+
focused.value = true;
92+
emit('focus', e);
9193
};
92-
},
93-
data() {
94-
return {
95-
focused: false,
94+
95+
const handleBlur = (e: FocusEvent) => {
96+
focused.value = false;
97+
emit('blur', e);
9698
};
97-
},
98-
mounted() {
99-
nextTick(() => {
100-
if (process.env.NODE_ENV === 'test') {
101-
if (this.autofocus) {
102-
this.focus();
103-
}
104-
}
105-
});
106-
},
107-
methods: {
108-
handleFocus(e: FocusEvent) {
109-
this.$emit('focus', e);
110-
this.setState({
111-
focused: true,
112-
});
113-
},
114-
handleBlur(e: FocusEvent) {
115-
this.$emit('blur', e);
116-
this.setState({
117-
focused: false,
118-
});
119-
},
120-
handleSelect(...args: [MentionsOptionProps, string]) {
121-
this.$emit('select', ...args);
122-
this.setState({
123-
focused: true,
124-
});
125-
},
126-
handleChange(val: string) {
127-
this.$emit('update:value', val);
128-
this.$emit('change', val);
129-
},
130-
getNotFoundContent(renderEmpty: RenderEmptyHandler) {
131-
const notFoundContent = getComponent(this, 'notFoundContent');
99+
100+
const handleSelect = (...args: [MentionsOptionProps, string]) => {
101+
emit('select', ...args);
102+
focused.value = true;
103+
};
104+
105+
const handleChange = (val: string) => {
106+
emit('update:value', val);
107+
emit('change', val);
108+
};
109+
110+
const getNotFoundContent = (renderEmpty: RenderEmptyHandler) => {
111+
const notFoundContent = props.notFoundContent;
132112
if (notFoundContent !== undefined) {
133113
return notFoundContent;
134114
}
135115

136116
return renderEmpty('Select');
137-
},
138-
getOptions() {
139-
const { loading } = this.$props;
140-
const children = getSlot(this);
117+
};
118+
119+
const getOptions = () => {
120+
const { loading } = props;
141121

142122
if (loading) {
143123
return (
@@ -146,71 +126,82 @@ const Mentions = defineComponent({
146126
</Option>
147127
);
148128
}
149-
return children;
150-
},
151-
getFilterOption() {
152-
const { filterOption, loading } = this.$props;
129+
return slots.default?.();
130+
};
131+
132+
const getFilterOption = () => {
133+
const { filterOption, loading } = props;
153134
if (loading) {
154135
return loadingFilterOption;
155136
}
156137
return filterOption;
157-
},
158-
focus() {
159-
(this.$refs.vcMentions as HTMLTextAreaElement).focus();
160-
},
161-
blur() {
162-
(this.$refs.vcMentions as HTMLTextAreaElement).blur();
163-
},
164-
},
165-
render() {
166-
const { focused } = this.$data;
167-
const { getPrefixCls, renderEmpty } = this.configProvider;
168-
const {
169-
prefixCls: customizePrefixCls,
170-
disabled,
171-
getPopupContainer,
172-
...restProps
173-
} = getOptionProps(this) as any;
174-
const { class: className, ...otherAttrs } = this.$attrs;
175-
const prefixCls = getPrefixCls('mentions', customizePrefixCls);
176-
const otherProps = omit(restProps, ['loading', 'onUpdate:value']);
177-
178-
const mergedClassName = classNames(className, {
179-
[`${prefixCls}-disabled`]: disabled,
180-
[`${prefixCls}-focused`]: focused,
181-
});
138+
};
182139

183-
const mentionsProps = {
184-
prefixCls,
185-
notFoundContent: this.getNotFoundContent(renderEmpty),
186-
...otherProps,
187-
disabled,
188-
filterOption: this.getFilterOption(),
189-
getPopupContainer,
190-
children: this.getOptions(),
191-
class: mergedClassName,
192-
rows: 1,
193-
...otherAttrs,
194-
onChange: this.handleChange,
195-
onSelect: this.handleSelect,
196-
onFocus: this.handleFocus,
197-
onBlur: this.handleBlur,
198-
ref: 'vcMentions',
140+
const focus = () => {
141+
(vcMentions.value as HTMLTextAreaElement).focus();
199142
};
143+
const blur = () => {
144+
(vcMentions.value as HTMLTextAreaElement).blur();
145+
};
146+
147+
expose({ focus, blur });
148+
149+
onMounted(() => {
150+
nextTick(() => {
151+
if (process.env.NODE_ENV === 'test') {
152+
if (props.autofocus) {
153+
focus();
154+
}
155+
}
156+
});
157+
});
158+
159+
return () => {
160+
const { disabled, getPopupContainer, ...restProps } = props;
161+
const { class: className, ...otherAttrs } = attrs;
162+
const otherProps = omit(restProps, ['loading', 'onUpdate:value', 'prefixCls']);
163+
164+
const mergedClassName = classNames(className, {
165+
[`${prefixCls.value}-disabled`]: disabled,
166+
[`${prefixCls.value}-focused`]: focused.value,
167+
[`${prefixCls}-rtl`]: direction.value === 'rtl',
168+
});
200169

201-
return <VcMentions {...mentionsProps} />;
170+
const mentionsProps = {
171+
prefixCls: prefixCls.value,
172+
notFoundContent: getNotFoundContent(renderEmpty.value),
173+
...otherProps,
174+
disabled,
175+
direction: direction.value,
176+
filterOption: getFilterOption(),
177+
getPopupContainer,
178+
children: getOptions(),
179+
class: mergedClassName,
180+
rows: 1,
181+
...otherAttrs,
182+
onChange: handleChange,
183+
onSelect: handleSelect,
184+
onFocus: handleFocus,
185+
onBlur: handleBlur,
186+
ref: vcMentions,
187+
};
188+
return <VcMentions {...mentionsProps} />;
189+
};
202190
},
203191
});
204192

193+
export const MentionsOption = {
194+
...Option,
195+
name: 'AMentionsOption',
196+
};
197+
205198
/* istanbul ignore next */
206199
Mentions.install = function (app: App) {
207200
app.component(Mentions.name, Mentions);
208-
app.component(Mentions.Option.name, Mentions.Option);
201+
app.component(MentionsOption.name, MentionsOption);
209202
return app;
210203
};
211204

212-
export const MentionsOption = Mentions.Option;
213-
214205
export default Mentions as typeof Mentions &
215206
Plugin & {
216207
readonly Option: typeof Option;

components/mentions/style/index.less

+4-6
Original file line numberDiff line numberDiff line change
@@ -64,10 +64,6 @@
6464
background-color: transparent;
6565
}
6666
.placeholder();
67-
68-
&:read-only {
69-
cursor: default;
70-
}
7167
}
7268

7369
&-measure {
@@ -123,7 +119,7 @@
123119
overflow: hidden;
124120
color: @text-color;
125121
font-weight: normal;
126-
line-height: 22px;
122+
line-height: @line-height-base;
127123
white-space: nowrap;
128124
text-overflow: ellipsis;
129125
cursor: pointer;
@@ -159,9 +155,11 @@
159155
}
160156

161157
&-active {
162-
background-color: @item-active-bg;
158+
background-color: @item-hover-bg;
163159
}
164160
}
165161
}
166162
}
167163
}
164+
165+
@import './rtl';

components/mentions/style/rtl.less

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
@import '../../style/themes/index';
2+
@import '../../style/mixins/index';
3+
4+
@mention-prefix-cls: ~'@{ant-prefix}-mentions';
5+
6+
.@{mention-prefix-cls} {
7+
&-rtl {
8+
direction: rtl;
9+
}
10+
}
File renamed without changes.

components/vc-mentions/src/DropdownMenu.jsx

-65
This file was deleted.

0 commit comments

Comments
 (0)