diff --git a/components/mentions/index.jsx b/components/mentions/index.tsx similarity index 75% rename from components/mentions/index.jsx rename to components/mentions/index.tsx index c5af332fc..afab4c8f8 100644 --- a/components/mentions/index.jsx +++ b/components/mentions/index.tsx @@ -1,4 +1,4 @@ -import { inject } from 'vue'; +import { App, defineComponent, inject, PropType, VNodeTypes } from 'vue'; import classNames from '../_util/classNames'; import omit from 'omit.js'; import PropTypes from '../_util/vue-types'; @@ -8,14 +8,27 @@ import Spin from '../spin'; import BaseMixin from '../_util/BaseMixin'; import { defaultConfigProvider } from '../config-provider'; import { getOptionProps, getComponent, getSlot } from '../_util/props-util'; +import { RenderEmptyHandler } from '../config-provider/renderEmpty'; const { Option } = VcMentions; +interface MentionsConfig { + prefix?: string | string[]; + split?: string; +} + +export interface OptionProps { + value: string; + disabled: boolean; + children: VNodeTypes; + [key: string]: any; +} + function loadingFilterOption() { return true; } -function getMentions(value = '', config) { +function getMentions(value: string = '', config: MentionsConfig) { const { prefix = '@', split = ' ' } = config || {}; const prefixList = Array.isArray(prefix) ? prefix : [prefix]; @@ -44,7 +57,7 @@ function getMentions(value = '', config) { .filter(entity => !!entity && !!entity.value); } -const Mentions = { +const Mentions = defineComponent({ name: 'AMentions', mixins: [BaseMixin], inheritAttrs: false, @@ -53,12 +66,20 @@ const Mentions = { props: { ...mentionsProps, loading: PropTypes.looseBool, - onFocus: PropTypes.func, - onBlur: PropTypes.func, - onSelect: PropTypes.func, - onChange: PropTypes.func, - 'onUpdate:value': PropTypes.func, + onFocus: { + type: Function as PropType<(e: FocusEvent) => void>, + }, + onBlur: { + type: Function as PropType<(e: FocusEvent) => void>, + }, + onSelect: { + type: Function as PropType<(option: OptionProps, prefix: string) => void>, + }, + onChange: { + type: Function as PropType<(text: string) => void>, + }, }, + emits: ['update:value', 'change', 'focus', 'blur', 'select'], setup() { return { configProvider: inject('configProvider', defaultConfigProvider), @@ -79,29 +100,29 @@ const Mentions = { }); }, methods: { - handleFocus(...args) { - this.$emit('focus', ...args); + handleFocus(e: FocusEvent) { + this.$emit('focus', e); this.setState({ focused: true, }); }, - handleBlur(...args) { - this.$emit('blur', ...args); + handleBlur(e: FocusEvent) { + this.$emit('blur', e); this.setState({ focused: false, }); }, - handleSelect(...args) { + handleSelect(...args: [OptionProps, string]) { this.$emit('select', ...args); this.setState({ focused: true, }); }, - handleChange(val) { + handleChange(val: string) { this.$emit('update:value', val); this.$emit('change', val); }, - getNotFoundContent(renderEmpty) { + getNotFoundContent(renderEmpty: RenderEmptyHandler) { const notFoundContent = getComponent(this, 'notFoundContent'); if (notFoundContent !== undefined) { return notFoundContent; @@ -130,10 +151,10 @@ const Mentions = { return filterOption; }, focus() { - this.$refs.vcMentions.focus(); + (this.$refs.vcMentions as any).focus(); }, blur() { - this.$refs.vcMentions.blur(); + (this.$refs.vcMentions as any).blur(); }, }, render() { @@ -144,7 +165,7 @@ const Mentions = { disabled, getPopupContainer, ...restProps - } = getOptionProps(this); + } = getOptionProps(this) as any; const { class: className, ...otherAttrs } = this.$attrs; const prefixCls = getPrefixCls('mentions', customizePrefixCls); const otherProps = omit(restProps, ['loading', 'onUpdate:value']); @@ -174,10 +195,10 @@ const Mentions = { return ; }, -}; +}); /* istanbul ignore next */ -Mentions.install = function(app) { +Mentions.install = function(app: App) { app.component(Mentions.name, Mentions); app.component(Mentions.Option.name, Mentions.Option); return app; diff --git a/components/mentions/style/index.js b/components/mentions/style/index.ts similarity index 100% rename from components/mentions/style/index.js rename to components/mentions/style/index.ts diff --git a/components/vc-mentions/src/mentionsProps.js b/components/vc-mentions/src/mentionsProps.ts similarity index 68% rename from components/vc-mentions/src/mentionsProps.js rename to components/vc-mentions/src/mentionsProps.ts index 8da68ca74..d2aacc16b 100644 --- a/components/vc-mentions/src/mentionsProps.js +++ b/components/vc-mentions/src/mentionsProps.ts @@ -1,5 +1,6 @@ +import { PropType } from 'vue'; import PropTypes from '../../_util/vue-types'; -import { initDefaultProps } from '../../_util/props-util'; +import initDefaultProps from '../../_util/props-util/initDefaultProps'; import { filterOption as defaultFilterOption, validateSearch as defaultValidateSearch, @@ -13,15 +14,21 @@ export const mentionsProps = { value: PropTypes.string, defaultValue: PropTypes.string, disabled: PropTypes.looseBool, - notFoundContent: PropTypes.any, + notFoundContent: PropTypes.VNodeChild, split: PropTypes.string, transitionName: PropTypes.string, placement: PropTypes.oneOf(PlaceMent), character: PropTypes.any, characterRender: PropTypes.func, - filterOption: PropTypes.func, - validateSearch: PropTypes.func, - getPopupContainer: PropTypes.func, + filterOption: { + type: [Boolean, Function] as PropType, + }, + validateSearch: { + type: Function as PropType, + }, + getPopupContainer: { + type: Function as PropType<() => HTMLElement>, + }, }; export const vcMentionsProps = { diff --git a/components/vc-mentions/src/placement.js b/components/vc-mentions/src/placement.js index 772cbcf33..6ee6165b8 100644 --- a/components/vc-mentions/src/placement.js +++ b/components/vc-mentions/src/placement.js @@ -1 +1,3 @@ -export const PlaceMent = ['top', 'bottom']; +import { tuple } from '../../_util/type'; + +export const PlaceMent = tuple('top', 'bottom');