feat: message support configprovider.config

pull/4675/head
tangjinzhou 2021-09-18 19:23:52 +08:00
parent bcd69f0008
commit 322158d2be
3 changed files with 72 additions and 50 deletions

View File

@ -1,28 +1,30 @@
import type { CSSProperties, VNodeTypes } from 'vue';
import type { CSSProperties } from 'vue';
import Notification from '../vc-notification';
import LoadingOutlined from '@ant-design/icons-vue/LoadingOutlined';
import ExclamationCircleFilled from '@ant-design/icons-vue/ExclamationCircleFilled';
import CloseCircleFilled from '@ant-design/icons-vue/CloseCircleFilled';
import CheckCircleFilled from '@ant-design/icons-vue/CheckCircleFilled';
import InfoCircleFilled from '@ant-design/icons-vue/InfoCircleFilled';
import type { VueNode } from '../_util/type';
let defaultDuration = 3;
let defaultTop: string;
let messageInstance: any;
let key = 1;
let prefixCls = 'ant-message';
let localPrefixCls = '';
let transitionName = 'move-up';
let getContainer = () => document.body;
let maxCount: number;
function getMessageInstance(callback: (i: any) => void) {
function getMessageInstance(args: MessageArgsProps, callback: (i: any) => void) {
if (messageInstance) {
callback(messageInstance);
return;
}
Notification.newInstance(
{
prefixCls,
prefixCls: args.prefixCls || localPrefixCls,
rootPrefixCls: args.rootPrefixCls,
transitionName,
style: { top: defaultTop }, //
getContainer,
@ -60,20 +62,21 @@ export interface MessageType {
}
export interface MessageArgsProps {
content: VNodeTypes;
content: string | (() => VueNode) | VueNode;
duration: number | null;
type: NoticeType;
prefixCls?: string;
rootPrefixCls?: string;
onClose?: () => void;
icon?: VNodeTypes;
icon?: (() => VueNode) | VueNode;
key?: string | number;
style?: CSSProperties;
class?: string;
appContext?: any;
}
function notice(args: MessageArgsProps): MessageType {
const duration = args.duration !== undefined ? args.duration : defaultDuration;
const Icon = iconMap[args.type];
const iconNode = Icon ? <Icon /> : '';
const target = args.key || key++;
const closePromise = new Promise(resolve => {
@ -83,19 +86,22 @@ function notice(args: MessageArgsProps): MessageType {
}
return resolve(true);
};
getMessageInstance(instance => {
getMessageInstance(args, instance => {
instance.notice({
key: target,
duration,
style: args.style || {},
class: args.class,
content: () => {
appContext: args.appContext,
content: ({ prefixCls }) => {
const Icon = iconMap[args.type];
const iconNode = Icon ? <Icon /> : '';
return (
<div
class={`${prefixCls}-custom-content${args.type ? ` ${prefixCls}-${args.type}` : ''}`}
>
{args.icon || iconNode}
<span>{args.content}</span>
{typeof args.icon === 'function' ? args.icon : args.icon || iconNode}
<span>{typeof args.content === 'function' ? args.content() : args.content}</span>
</div>
);
},
@ -115,7 +121,7 @@ function notice(args: MessageArgsProps): MessageType {
}
type ConfigDuration = number | (() => void);
type JointContent = VNodeTypes | MessageArgsProps;
type JointContent = VueNode | MessageArgsProps;
export type ConfigOnClose = () => void;
function isArgsProps(content: JointContent): content is MessageArgsProps {
@ -145,7 +151,7 @@ const api: any = {
defaultDuration = options.duration;
}
if (options.prefixCls !== undefined) {
prefixCls = options.prefixCls;
localPrefixCls = options.prefixCls;
}
if (options.getContainer !== undefined) {
getContainer = options.getContainer;

View File

@ -1,4 +1,4 @@
import type { ExtractPropTypes, VNodeTypes, CSSProperties, PropType } from 'vue';
import type { ExtractPropTypes, CSSProperties, PropType } from 'vue';
import { defineComponent, inject, computed } from 'vue';
import classNames from '../_util/classNames';
import Dialog from '../vc-dialog';
@ -13,6 +13,7 @@ import LocaleReceiver from '../locale-provider/LocaleReceiver';
import { getComponent, getSlot } from '../_util/props-util';
import initDefaultProps from '../_util/props-util/initDefaultProps';
import { defaultConfigProvider } from '../config-provider';
import type { VueNode } from '../_util/type';
let mousePosition: { x: number; y: number } | null = null;
// ref: https://github.com/ant-design/ant-design/issues/15795
@ -95,9 +96,9 @@ export interface ModalFuncProps {
prefixCls?: string;
class?: string;
visible?: boolean;
title?: string | (() => VNodeTypes) | VNodeTypes;
title?: string | (() => VueNode) | VueNode;
closable?: boolean;
content?: string | (() => VNodeTypes) | VNodeTypes;
content?: string | (() => VueNode) | VueNode;
// TODO: find out exact types
onOk?: (...args: any[]) => any;
onCancel?: (...args: any[]) => any;
@ -105,10 +106,10 @@ export interface ModalFuncProps {
cancelButtonProps?: ButtonPropsType;
centered?: boolean;
width?: string | number;
okText?: string | (() => VNodeTypes) | VNodeTypes;
okText?: string | (() => VueNode) | VueNode;
okType?: LegacyButtonType;
cancelText?: string | (() => VNodeTypes) | VNodeTypes;
icon?: (() => VNodeTypes) | VNodeTypes;
cancelText?: string | (() => VueNode) | VueNode;
icon?: (() => VueNode) | VueNode;
/* Deprecated */
iconType?: string;
mask?: boolean;

View File

@ -1,10 +1,11 @@
import { createApp, defineComponent } from 'vue';
import { defineComponent, createVNode, render as vueRender, onMounted, ref, nextTick } from 'vue';
import PropTypes from '../_util/vue-types';
import { getComponent } from '../_util/props-util';
import BaseMixin from '../_util/BaseMixin';
import createChainedFunction from '../_util/createChainedFunction';
import Notice from './Notice';
import { getTransitionGroupProps, TransitionGroup } from '../_util/transition';
import ConfigProvider, { globalConfig } from '../config-provider';
function noop() {}
@ -95,7 +96,9 @@ const Notification = defineComponent({
key,
};
return (
<Notice {...noticeProps}>{typeof content === 'function' ? content() : content}</Notice>
<Notice {...noticeProps}>
{typeof content === 'function' ? content({ prefixCls }) : content}
</Notice>
);
});
const className = {
@ -120,7 +123,13 @@ const Notification = defineComponent({
});
Notification.newInstance = function newNotificationInstance(properties, callback) {
const { getContainer, style, class: className, ...props } = properties || {};
const {
getContainer,
appContext,
prefixCls: customizePrefixCls,
rootPrefixCls: customRootPrefixCls,
...props
} = properties || {};
const div = document.createElement('div');
if (getContainer) {
const root = getContainer();
@ -128,37 +137,43 @@ Notification.newInstance = function newNotificationInstance(properties, callback
} else {
document.body.appendChild(div);
}
const app = createApp({
mounted() {
const self = this;
this.$nextTick(() => {
callback({
notice(noticeProps) {
self.$refs.notification.add(noticeProps);
},
removeNotice(key) {
self.$refs.notification.remove(key);
},
component: self,
destroy() {
app.unmount(div);
if (div.parentNode) {
div.parentNode.removeChild(div);
}
},
let vm = null;
const Wrapper = defineComponent({
setup(_props, { attrs }) {
const notiRef = ref();
onMounted(() => {
nextTick(() => {
callback({
notice(noticeProps) {
notiRef.value?.add(noticeProps);
},
removeNotice(key) {
notiRef.value?.remove(key);
},
destroy() {
vm?.unmount(div);
if (div.parentNode) {
div.parentNode.removeChild(div);
}
},
});
});
});
},
render() {
const p = {
...props,
ref: 'notification',
style,
class: className,
return () => {
const { getPrefixCls, getRootPrefixCls } = globalConfig();
const prefixCls = getPrefixCls('message', customizePrefixCls);
const rootPrefixCls = getRootPrefixCls(customRootPrefixCls, prefixCls);
return (
<ConfigProvider prefixCls={rootPrefixCls}>
<Notification ref={notiRef} {...attrs} prefixCls={prefixCls} />
</ConfigProvider>
);
};
return <Notification {...p} />;
},
});
app.mount(div);
vm = createVNode(Wrapper, props);
vm.appContext = appContext || vm.appContext;
vueRender(vm, div);
};
export default Notification;