feat: mentions
parent
0910df5a95
commit
a53768fa9a
|
@ -35,3 +35,7 @@ v-model -> v-model:visible
|
|||
v-model -> v-model:visible
|
||||
|
||||
okButtonProps、cancelButtonProps 扁平化处理
|
||||
|
||||
## Mentions
|
||||
|
||||
v-model -> v-model:value
|
||||
|
|
|
@ -1,19 +1,16 @@
|
|||
import { inject } from 'vue';
|
||||
import PropTypes from '../_util/vue-types';
|
||||
import Empty from '../empty';
|
||||
import { ConfigConsumerProps } from './';
|
||||
|
||||
const RenderEmpty = {
|
||||
functional: true,
|
||||
inject: {
|
||||
configProvider: { default: () => ConfigConsumerProps },
|
||||
},
|
||||
props: {
|
||||
componentName: PropTypes.string,
|
||||
},
|
||||
render(createElement, context) {
|
||||
const { props, injections } = context;
|
||||
setup(props) {
|
||||
const configProvider = inject('configProvider', ConfigConsumerProps);
|
||||
function renderHtml(componentName) {
|
||||
const getPrefixCls = injections.configProvider.getPrefixCls;
|
||||
const getPrefixCls = configProvider.getPrefixCls;
|
||||
const prefix = getPrefixCls('empty');
|
||||
switch (componentName) {
|
||||
case 'Table':
|
||||
|
@ -31,11 +28,11 @@ const RenderEmpty = {
|
|||
return <Empty />;
|
||||
}
|
||||
}
|
||||
return renderHtml(props.componentName);
|
||||
return () => renderHtml(props.componentName);
|
||||
},
|
||||
};
|
||||
|
||||
function renderEmpty(h, componentName) {
|
||||
function renderEmpty(componentName) {
|
||||
return <RenderEmpty componentName={componentName} />;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import { inject, nextTick } from 'vue';
|
||||
import classNames from 'classnames';
|
||||
import omit from 'omit.js';
|
||||
import PropTypes from '../_util/vue-types';
|
||||
|
@ -7,12 +8,7 @@ import Base from '../base';
|
|||
import Spin from '../spin';
|
||||
import BaseMixin from '../_util/BaseMixin';
|
||||
import { ConfigConsumerProps } from '../config-provider';
|
||||
import {
|
||||
getOptionProps,
|
||||
getComponentFromProp,
|
||||
getListeners,
|
||||
filterEmpty,
|
||||
} from '../_util/props-util';
|
||||
import { getOptionProps, getComponent, filterEmpty } from '../_util/props-util';
|
||||
|
||||
const { Option } = VcMentions;
|
||||
|
||||
|
@ -53,18 +49,16 @@ const Mentions = {
|
|||
name: 'AMentions',
|
||||
mixins: [BaseMixin],
|
||||
inheritAttrs: false,
|
||||
model: {
|
||||
prop: 'value',
|
||||
event: 'change',
|
||||
},
|
||||
Option: { ...Option, name: 'AMentionsOption' },
|
||||
getMentions,
|
||||
props: {
|
||||
...mentionsProps,
|
||||
loading: PropTypes.bool,
|
||||
},
|
||||
inject: {
|
||||
configProvider: { default: () => ConfigConsumerProps },
|
||||
setup() {
|
||||
return {
|
||||
configProvider: inject('configProvider', ConfigConsumerProps),
|
||||
};
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
|
@ -72,7 +66,7 @@ const Mentions = {
|
|||
};
|
||||
},
|
||||
mounted() {
|
||||
this.$nextTick(() => {
|
||||
nextTick(() => {
|
||||
if (this.autoFocus) {
|
||||
this.focus();
|
||||
}
|
||||
|
@ -99,19 +93,19 @@ const Mentions = {
|
|||
},
|
||||
onChange(val) {
|
||||
this.$emit('change', val);
|
||||
this.$emit('update:value', val);
|
||||
},
|
||||
getNotFoundContent(renderEmpty) {
|
||||
const h = this.$createElement;
|
||||
const notFoundContent = getComponentFromProp(this, 'notFoundContent');
|
||||
const notFoundContent = getComponent(this, 'notFoundContent');
|
||||
if (notFoundContent !== undefined) {
|
||||
return notFoundContent;
|
||||
}
|
||||
|
||||
return renderEmpty(h, 'Select');
|
||||
return renderEmpty('Select');
|
||||
},
|
||||
getOptions() {
|
||||
const { loading } = this.$props;
|
||||
const children = filterEmpty(this.$slots.default || []);
|
||||
const children = filterEmpty(this.$slots.default?.() || []);
|
||||
|
||||
if (loading) {
|
||||
return (
|
||||
|
@ -154,24 +148,20 @@ const Mentions = {
|
|||
});
|
||||
|
||||
const mentionsProps = {
|
||||
props: {
|
||||
prefixCls,
|
||||
notFoundContent: this.getNotFoundContent(renderEmpty),
|
||||
...otherProps,
|
||||
disabled,
|
||||
filterOption: this.getFilterOption(),
|
||||
getPopupContainer,
|
||||
children: this.getOptions(),
|
||||
},
|
||||
prefixCls,
|
||||
notFoundContent: this.getNotFoundContent(renderEmpty),
|
||||
...otherProps,
|
||||
disabled,
|
||||
filterOption: this.getFilterOption(),
|
||||
getPopupContainer,
|
||||
children: this.getOptions(),
|
||||
class: mergedClassName,
|
||||
attrs: { rows: 1, ...this.$attrs },
|
||||
on: {
|
||||
...getListeners(this),
|
||||
change: this.onChange,
|
||||
select: this.onSelect,
|
||||
focus: this.onFocus,
|
||||
blur: this.onBlur,
|
||||
},
|
||||
rows: 1,
|
||||
...this.$attrs,
|
||||
onChange: this.onChange,
|
||||
onSelect: this.onSelect,
|
||||
onFocus: this.onFocus,
|
||||
onBlur: this.onBlur,
|
||||
ref: 'vcMentions',
|
||||
};
|
||||
|
||||
|
@ -180,10 +170,10 @@ const Mentions = {
|
|||
};
|
||||
|
||||
/* istanbul ignore next */
|
||||
Mentions.install = function(Vue) {
|
||||
Vue.use(Base);
|
||||
Vue.component(Mentions.name, Mentions);
|
||||
Vue.component(Mentions.Option.name, Mentions.Option);
|
||||
Mentions.install = function(app) {
|
||||
app.use(Base);
|
||||
app.component(Mentions.name, Mentions);
|
||||
app.component(Mentions.Option.name, Mentions.Option);
|
||||
};
|
||||
|
||||
export default Mentions;
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import { nextTick } from 'vue';
|
||||
import PropTypes from '../_util/vue-types';
|
||||
import { alignElement, alignPoint } from 'dom-align';
|
||||
import addEventListener from '../vc-util/Dom/addEventListener';
|
||||
|
@ -30,7 +31,7 @@ export default {
|
|||
return {};
|
||||
},
|
||||
mounted() {
|
||||
this.$nextTick(() => {
|
||||
nextTick(() => {
|
||||
this.prevProps = { ...this.$props };
|
||||
const props = this.$props;
|
||||
// if parent ref not attached .... use document.getElementById
|
||||
|
@ -41,7 +42,7 @@ export default {
|
|||
});
|
||||
},
|
||||
updated() {
|
||||
this.$nextTick(() => {
|
||||
nextTick(() => {
|
||||
const prevProps = this.prevProps;
|
||||
const props = this.$props;
|
||||
let reAlign = false;
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import Menu, { MenuItem } from '../../vc-menu';
|
||||
import PropTypes from '../../_util/vue-types';
|
||||
import { OptionProps } from './Option';
|
||||
import { inject } from 'vue';
|
||||
|
||||
function noop() {}
|
||||
export default {
|
||||
|
@ -9,10 +10,11 @@ export default {
|
|||
prefixCls: PropTypes.string,
|
||||
options: PropTypes.arrayOf(OptionProps),
|
||||
},
|
||||
inject: {
|
||||
mentionsContext: { default: {} },
|
||||
setup() {
|
||||
return {
|
||||
mentionsContext: inject('mentionsContext'),
|
||||
};
|
||||
},
|
||||
|
||||
render() {
|
||||
const {
|
||||
notFoundContent,
|
||||
|
@ -27,37 +29,36 @@ export default {
|
|||
|
||||
return (
|
||||
<Menu
|
||||
{...{
|
||||
props: {
|
||||
prefixCls: `${prefixCls}-menu`,
|
||||
activeKey: activeOption.value,
|
||||
},
|
||||
on: {
|
||||
select: ({ key }) => {
|
||||
const option = options.find(({ value }) => value === key);
|
||||
selectOption(option);
|
||||
},
|
||||
focus: onFocus,
|
||||
blur: onBlur,
|
||||
},
|
||||
prefixCls={`${prefixCls}-menu`}
|
||||
activeKey={activeOption.value}
|
||||
onSelect={({ key }) => {
|
||||
const option = options.find(({ value }) => value === key);
|
||||
selectOption(option);
|
||||
}}
|
||||
>
|
||||
{options.map((option, index) => {
|
||||
const { value, disabled, children } = option;
|
||||
return (
|
||||
<MenuItem
|
||||
key={value}
|
||||
disabled={disabled}
|
||||
onMouseenter={() => {
|
||||
setActiveIndex(index);
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
onBlur={onBlur}
|
||||
onFocus={onFocus}
|
||||
children={[
|
||||
...options.map((option, index) => {
|
||||
const { value, disabled, children } = option;
|
||||
return (
|
||||
<MenuItem
|
||||
key={value}
|
||||
disabled={disabled}
|
||||
onMouseenter={() => {
|
||||
setActiveIndex(index);
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
</MenuItem>
|
||||
);
|
||||
}),
|
||||
!options.length && (
|
||||
<MenuItem key="notFoundContent" disabled>
|
||||
{notFoundContent}
|
||||
</MenuItem>
|
||||
);
|
||||
})}
|
||||
{!options.length && <MenuItem disabled>{notFoundContent}</MenuItem>}
|
||||
</Menu>
|
||||
),
|
||||
].filter(Boolean)}
|
||||
/>
|
||||
);
|
||||
},
|
||||
};
|
||||
|
|
|
@ -49,7 +49,7 @@ export default {
|
|||
|
||||
const { $slots } = this;
|
||||
|
||||
const children = $slots.default;
|
||||
const children = $slots.default?.();
|
||||
|
||||
const popupElement = this.getDropdownElement();
|
||||
|
||||
|
|
|
@ -1,13 +1,8 @@
|
|||
import { provide, nextTick } from 'vue';
|
||||
import omit from 'omit.js';
|
||||
import KeyCode from '../../_util/KeyCode';
|
||||
import BaseMixin from '../../_util/BaseMixin';
|
||||
import {
|
||||
getSlots,
|
||||
hasProp,
|
||||
getOptionProps,
|
||||
getListeners,
|
||||
initDefaultProps,
|
||||
} from '../../_util/props-util';
|
||||
import { hasProp, getOptionProps, initDefaultProps } from '../../_util/props-util';
|
||||
import warning from 'warning';
|
||||
import {
|
||||
getBeforeSelectionText,
|
||||
|
@ -24,15 +19,9 @@ const Mentions = {
|
|||
name: 'Mentions',
|
||||
mixins: [BaseMixin],
|
||||
inheritAttrs: false,
|
||||
model: {
|
||||
prop: 'value',
|
||||
event: 'change',
|
||||
},
|
||||
props: initDefaultProps(vcMentionsProps, defaultProps),
|
||||
provide() {
|
||||
return {
|
||||
mentionsContext: this,
|
||||
};
|
||||
created() {
|
||||
this.mentionsContext = provide('mentionsContext', this);
|
||||
},
|
||||
data() {
|
||||
const { value = '', defaultValue = '' } = this.$props;
|
||||
|
@ -53,7 +42,7 @@ const Mentions = {
|
|||
},
|
||||
},
|
||||
updated() {
|
||||
this.$nextTick(() => {
|
||||
nextTick(() => {
|
||||
const { measuring } = this.$data;
|
||||
|
||||
// Sync measure div top with textarea for rc-trigger usage
|
||||
|
@ -215,8 +204,7 @@ const Mentions = {
|
|||
const { filterOption, children = [] } = this.$props;
|
||||
const list = (Array.isArray(children) ? children : [children])
|
||||
.map(item => {
|
||||
const children = getSlots(item).default;
|
||||
return { ...getOptionProps(item), children };
|
||||
return { ...getOptionProps(item), children: item.children.default?.() || item.children };
|
||||
})
|
||||
.filter(option => {
|
||||
/** Return all result if `filterOption` is false. */
|
||||
|
@ -283,21 +271,17 @@ const Mentions = {
|
|||
<textarea
|
||||
ref="textarea"
|
||||
{...{
|
||||
directives: [{ name: 'ant-input' }],
|
||||
attrs: { ...inputProps, ...this.$attrs },
|
||||
domProps: {
|
||||
value,
|
||||
},
|
||||
on: {
|
||||
...getListeners(this),
|
||||
select: noop,
|
||||
change: noop,
|
||||
input: this.onChange,
|
||||
keydown: this.onKeyDown,
|
||||
keyup: this.onKeyUp,
|
||||
blur: this.onInputBlur,
|
||||
},
|
||||
...inputProps,
|
||||
...this.$attrs,
|
||||
onChange: noop,
|
||||
onSelect: noop,
|
||||
}}
|
||||
value={value}
|
||||
onInput={this.onChange}
|
||||
onBlur={this.onInputBlur}
|
||||
onKeyDown={this.onKeyDown}
|
||||
onKeyUp={this.onKeyUp}
|
||||
onFocus={this.onInputFocus}
|
||||
/>
|
||||
{measuring && (
|
||||
<div ref="measure" class={`${prefixCls}-measure`}>
|
||||
|
|
|
@ -13,7 +13,6 @@ const Menu = {
|
|||
selectable: PropTypes.bool.def(true),
|
||||
},
|
||||
mixins: [BaseMixin],
|
||||
|
||||
data() {
|
||||
const props = getOptionProps(this);
|
||||
let selectedKeys = props.defaultSelectedKeys;
|
||||
|
|
|
@ -281,7 +281,7 @@ export default {
|
|||
align={align}
|
||||
onAlign={this.onAlign}
|
||||
>
|
||||
<PopupInner {...popupInnerProps}>{$slots.default && $slots.default()}</PopupInner>
|
||||
<PopupInner {...popupInnerProps}>{$slots.default?.()}</PopupInner>
|
||||
</Align>
|
||||
</Transition>
|
||||
);
|
||||
|
|
Loading…
Reference in New Issue