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 Notification from '../vc-notification';
import LoadingOutlined from '@ant-design/icons-vue/LoadingOutlined'; import LoadingOutlined from '@ant-design/icons-vue/LoadingOutlined';
import ExclamationCircleFilled from '@ant-design/icons-vue/ExclamationCircleFilled'; import ExclamationCircleFilled from '@ant-design/icons-vue/ExclamationCircleFilled';
import CloseCircleFilled from '@ant-design/icons-vue/CloseCircleFilled'; import CloseCircleFilled from '@ant-design/icons-vue/CloseCircleFilled';
import CheckCircleFilled from '@ant-design/icons-vue/CheckCircleFilled'; import CheckCircleFilled from '@ant-design/icons-vue/CheckCircleFilled';
import InfoCircleFilled from '@ant-design/icons-vue/InfoCircleFilled'; import InfoCircleFilled from '@ant-design/icons-vue/InfoCircleFilled';
import type { VueNode } from '../_util/type';
let defaultDuration = 3; let defaultDuration = 3;
let defaultTop: string; let defaultTop: string;
let messageInstance: any; let messageInstance: any;
let key = 1; let key = 1;
let prefixCls = 'ant-message'; let localPrefixCls = '';
let transitionName = 'move-up'; let transitionName = 'move-up';
let getContainer = () => document.body; let getContainer = () => document.body;
let maxCount: number; let maxCount: number;
function getMessageInstance(callback: (i: any) => void) { function getMessageInstance(args: MessageArgsProps, callback: (i: any) => void) {
if (messageInstance) { if (messageInstance) {
callback(messageInstance); callback(messageInstance);
return; return;
} }
Notification.newInstance( Notification.newInstance(
{ {
prefixCls, prefixCls: args.prefixCls || localPrefixCls,
rootPrefixCls: args.rootPrefixCls,
transitionName, transitionName,
style: { top: defaultTop }, // style: { top: defaultTop }, //
getContainer, getContainer,
@ -60,20 +62,21 @@ export interface MessageType {
} }
export interface MessageArgsProps { export interface MessageArgsProps {
content: VNodeTypes; content: string | (() => VueNode) | VueNode;
duration: number | null; duration: number | null;
type: NoticeType; type: NoticeType;
prefixCls?: string;
rootPrefixCls?: string;
onClose?: () => void; onClose?: () => void;
icon?: VNodeTypes; icon?: (() => VueNode) | VueNode;
key?: string | number; key?: string | number;
style?: CSSProperties; style?: CSSProperties;
class?: string; class?: string;
appContext?: any;
} }
function notice(args: MessageArgsProps): MessageType { function notice(args: MessageArgsProps): MessageType {
const duration = args.duration !== undefined ? args.duration : defaultDuration; const duration = args.duration !== undefined ? args.duration : defaultDuration;
const Icon = iconMap[args.type];
const iconNode = Icon ? <Icon /> : '';
const target = args.key || key++; const target = args.key || key++;
const closePromise = new Promise(resolve => { const closePromise = new Promise(resolve => {
@ -83,19 +86,22 @@ function notice(args: MessageArgsProps): MessageType {
} }
return resolve(true); return resolve(true);
}; };
getMessageInstance(instance => { getMessageInstance(args, instance => {
instance.notice({ instance.notice({
key: target, key: target,
duration, duration,
style: args.style || {}, style: args.style || {},
class: args.class, class: args.class,
content: () => { appContext: args.appContext,
content: ({ prefixCls }) => {
const Icon = iconMap[args.type];
const iconNode = Icon ? <Icon /> : '';
return ( return (
<div <div
class={`${prefixCls}-custom-content${args.type ? ` ${prefixCls}-${args.type}` : ''}`} class={`${prefixCls}-custom-content${args.type ? ` ${prefixCls}-${args.type}` : ''}`}
> >
{args.icon || iconNode} {typeof args.icon === 'function' ? args.icon : args.icon || iconNode}
<span>{args.content}</span> <span>{typeof args.content === 'function' ? args.content() : args.content}</span>
</div> </div>
); );
}, },
@ -115,7 +121,7 @@ function notice(args: MessageArgsProps): MessageType {
} }
type ConfigDuration = number | (() => void); type ConfigDuration = number | (() => void);
type JointContent = VNodeTypes | MessageArgsProps; type JointContent = VueNode | MessageArgsProps;
export type ConfigOnClose = () => void; export type ConfigOnClose = () => void;
function isArgsProps(content: JointContent): content is MessageArgsProps { function isArgsProps(content: JointContent): content is MessageArgsProps {
@ -145,7 +151,7 @@ const api: any = {
defaultDuration = options.duration; defaultDuration = options.duration;
} }
if (options.prefixCls !== undefined) { if (options.prefixCls !== undefined) {
prefixCls = options.prefixCls; localPrefixCls = options.prefixCls;
} }
if (options.getContainer !== undefined) { if (options.getContainer !== undefined) {
getContainer = options.getContainer; 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 { defineComponent, inject, computed } from 'vue';
import classNames from '../_util/classNames'; import classNames from '../_util/classNames';
import Dialog from '../vc-dialog'; import Dialog from '../vc-dialog';
@ -13,6 +13,7 @@ import LocaleReceiver from '../locale-provider/LocaleReceiver';
import { getComponent, getSlot } from '../_util/props-util'; import { getComponent, getSlot } from '../_util/props-util';
import initDefaultProps from '../_util/props-util/initDefaultProps'; import initDefaultProps from '../_util/props-util/initDefaultProps';
import { defaultConfigProvider } from '../config-provider'; import { defaultConfigProvider } from '../config-provider';
import type { VueNode } from '../_util/type';
let mousePosition: { x: number; y: number } | null = null; let mousePosition: { x: number; y: number } | null = null;
// ref: https://github.com/ant-design/ant-design/issues/15795 // ref: https://github.com/ant-design/ant-design/issues/15795
@ -95,9 +96,9 @@ export interface ModalFuncProps {
prefixCls?: string; prefixCls?: string;
class?: string; class?: string;
visible?: boolean; visible?: boolean;
title?: string | (() => VNodeTypes) | VNodeTypes; title?: string | (() => VueNode) | VueNode;
closable?: boolean; closable?: boolean;
content?: string | (() => VNodeTypes) | VNodeTypes; content?: string | (() => VueNode) | VueNode;
// TODO: find out exact types // TODO: find out exact types
onOk?: (...args: any[]) => any; onOk?: (...args: any[]) => any;
onCancel?: (...args: any[]) => any; onCancel?: (...args: any[]) => any;
@ -105,10 +106,10 @@ export interface ModalFuncProps {
cancelButtonProps?: ButtonPropsType; cancelButtonProps?: ButtonPropsType;
centered?: boolean; centered?: boolean;
width?: string | number; width?: string | number;
okText?: string | (() => VNodeTypes) | VNodeTypes; okText?: string | (() => VueNode) | VueNode;
okType?: LegacyButtonType; okType?: LegacyButtonType;
cancelText?: string | (() => VNodeTypes) | VNodeTypes; cancelText?: string | (() => VueNode) | VueNode;
icon?: (() => VNodeTypes) | VNodeTypes; icon?: (() => VueNode) | VueNode;
/* Deprecated */ /* Deprecated */
iconType?: string; iconType?: string;
mask?: boolean; 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 PropTypes from '../_util/vue-types';
import { getComponent } from '../_util/props-util'; import { getComponent } from '../_util/props-util';
import BaseMixin from '../_util/BaseMixin'; import BaseMixin from '../_util/BaseMixin';
import createChainedFunction from '../_util/createChainedFunction'; import createChainedFunction from '../_util/createChainedFunction';
import Notice from './Notice'; import Notice from './Notice';
import { getTransitionGroupProps, TransitionGroup } from '../_util/transition'; import { getTransitionGroupProps, TransitionGroup } from '../_util/transition';
import ConfigProvider, { globalConfig } from '../config-provider';
function noop() {} function noop() {}
@ -95,7 +96,9 @@ const Notification = defineComponent({
key, key,
}; };
return ( return (
<Notice {...noticeProps}>{typeof content === 'function' ? content() : content}</Notice> <Notice {...noticeProps}>
{typeof content === 'function' ? content({ prefixCls }) : content}
</Notice>
); );
}); });
const className = { const className = {
@ -120,7 +123,13 @@ const Notification = defineComponent({
}); });
Notification.newInstance = function newNotificationInstance(properties, callback) { 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'); const div = document.createElement('div');
if (getContainer) { if (getContainer) {
const root = getContainer(); const root = getContainer();
@ -128,37 +137,43 @@ Notification.newInstance = function newNotificationInstance(properties, callback
} else { } else {
document.body.appendChild(div); document.body.appendChild(div);
} }
const app = createApp({ let vm = null;
mounted() { const Wrapper = defineComponent({
const self = this; setup(_props, { attrs }) {
this.$nextTick(() => { const notiRef = ref();
callback({ onMounted(() => {
notice(noticeProps) { nextTick(() => {
self.$refs.notification.add(noticeProps); callback({
}, notice(noticeProps) {
removeNotice(key) { notiRef.value?.add(noticeProps);
self.$refs.notification.remove(key); },
}, removeNotice(key) {
component: self, notiRef.value?.remove(key);
destroy() { },
app.unmount(div); destroy() {
if (div.parentNode) { vm?.unmount(div);
div.parentNode.removeChild(div); if (div.parentNode) {
} div.parentNode.removeChild(div);
}, }
},
});
}); });
}); });
}, return () => {
render() { const { getPrefixCls, getRootPrefixCls } = globalConfig();
const p = { const prefixCls = getPrefixCls('message', customizePrefixCls);
...props, const rootPrefixCls = getRootPrefixCls(customRootPrefixCls, prefixCls);
ref: 'notification', return (
style, <ConfigProvider prefixCls={rootPrefixCls}>
class: className, <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; export default Notification;