Skip to content

Commit 3479422

Browse files
committed
feat(Message): add useMessage hook
1 parent ac93c47 commit 3479422

File tree

5 files changed

+378
-2
lines changed

5 files changed

+378
-2
lines changed

components/_util/util.ts

+19
Original file line numberDiff line numberDiff line change
@@ -78,5 +78,24 @@ export function renderHelper<T = Record<string, any>>(
7878
}
7979
return v ?? defaultV;
8080
}
81+
export function wrapPromiseFn(openFn: (resolve: VoidFunction) => VoidFunction) {
82+
let closeFn: VoidFunction;
83+
84+
const closePromise = new Promise<boolean>(resolve => {
85+
closeFn = openFn(() => {
86+
resolve(true);
87+
});
88+
});
89+
90+
const result: any = () => {
91+
closeFn?.();
92+
};
93+
94+
result.then = (filled: VoidFunction, rejected: VoidFunction) =>
95+
closePromise.then(filled, rejected);
96+
result.promise = closePromise;
97+
98+
return result;
99+
}
81100

82101
export { isOn, cacheStringFunction, camelize, hyphenate, capitalize, resolvePropValue };

components/message/PurePanel.tsx

+79
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
import Notice from '../vc-notification/Notice';
2+
import type { NoticeProps } from '../vc-notification/Notice';
3+
import useStyle from './style';
4+
import type { NoticeType } from './interface';
5+
import {
6+
CheckCircleFilled,
7+
CloseCircleFilled,
8+
ExclamationCircleFilled,
9+
InfoCircleFilled,
10+
LoadingOutlined,
11+
} from '@ant-design/icons-vue';
12+
import type { VueNode } from '../_util/type';
13+
import classNames from '../_util/classNames';
14+
import { useConfigContextInject } from '../config-provider/context';
15+
import { computed, defineComponent } from 'vue';
16+
17+
export const TypeIcon = {
18+
info: <InfoCircleFilled />,
19+
success: <CheckCircleFilled />,
20+
error: <CloseCircleFilled />,
21+
warning: <ExclamationCircleFilled />,
22+
loading: <LoadingOutlined />,
23+
};
24+
25+
export interface PureContentProps {
26+
prefixCls: string;
27+
type?: NoticeType;
28+
icon?: VueNode;
29+
children: VueNode;
30+
}
31+
32+
export const PureContent = defineComponent({
33+
name: 'PureContent',
34+
inheritAttrs: false,
35+
props: ['prefixCls', 'type', 'icon'] as any,
36+
37+
setup(props, { slots }) {
38+
return () => (
39+
<div
40+
class={classNames(`${props.prefixCls}-custom-content`, `${props.prefixCls}-${props.type}`)}
41+
>
42+
{props.icon || TypeIcon[props.type!]}
43+
<span>{slots.default?.()}</span>
44+
</div>
45+
);
46+
},
47+
});
48+
49+
export interface PurePanelProps
50+
extends Omit<NoticeProps, 'prefixCls' | 'eventKey'>,
51+
Omit<PureContentProps, 'prefixCls' | 'children'> {
52+
prefixCls?: string;
53+
}
54+
55+
/** @private Internal Component. Do not use in your production. */
56+
57+
export default defineComponent({
58+
name: 'PurePanel',
59+
inheritAttrs: false,
60+
props: ['prefixCls', 'class', 'type', 'icon', 'content'] as any,
61+
setup(props, { slots, attrs }) {
62+
const { getPrefixCls } = useConfigContextInject();
63+
const prefixCls = computed(() => props.staticPrefixCls || getPrefixCls('message'));
64+
const [, hashId] = useStyle(prefixCls);
65+
return (
66+
<Notice
67+
{...attrs}
68+
prefixCls={prefixCls.value}
69+
class={classNames(hashId, `${prefixCls.value}-notice-pure-panel`)}
70+
noticeKey="pure"
71+
duration={null}
72+
>
73+
<PureContent prefixCls={props.prefixCls} type={props.type} icon={props.icon}>
74+
{slots.default?.()}
75+
</PureContent>
76+
</Notice>
77+
);
78+
},
79+
});

components/message/index.tsx

+4-2
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import type { Key, VueNode } from '../_util/type';
99
import type { NotificationInstance } from '../vc-notification/Notification';
1010
import classNames from '../_util/classNames';
1111
import useStyle from './style';
12-
12+
import useMessage from './useMessage';
1313
let defaultDuration = 3;
1414
let defaultTop: string;
1515
let messageInstance: NotificationInstance;
@@ -70,6 +70,7 @@ function getMessageInstance(args: MessageArgsProps, callback: (i: NotificationIn
7070
callback(messageInstance);
7171
return;
7272
}
73+
7374
Notification.newInstance(
7475
{
7576
appContext: args.appContext,
@@ -225,14 +226,15 @@ export function attachTypeApi(originalApi: MessageApi, type: NoticeType) {
225226
typeList.forEach(type => attachTypeApi(api, type));
226227

227228
api.warn = api.warning;
228-
229+
api.useMessage = useMessage;
229230
export interface MessageInstance {
230231
info(content: JointContent, duration?: ConfigDuration, onClose?: ConfigOnClose): MessageType;
231232
success(content: JointContent, duration?: ConfigDuration, onClose?: ConfigOnClose): MessageType;
232233
error(content: JointContent, duration?: ConfigDuration, onClose?: ConfigOnClose): MessageType;
233234
warning(content: JointContent, duration?: ConfigDuration, onClose?: ConfigOnClose): MessageType;
234235
loading(content: JointContent, duration?: ConfigDuration, onClose?: ConfigOnClose): MessageType;
235236
open(args: MessageArgsProps): MessageType;
237+
useMessage: typeof useMessage;
236238
}
237239

238240
export interface MessageApi extends MessageInstance {

components/message/interface.ts

+48
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
import type { CSSProperties } from 'vue';
2+
import type { Key, VueNode } from '../_util/type';
3+
4+
export type NoticeType = 'info' | 'success' | 'error' | 'warning' | 'loading';
5+
6+
export interface ConfigOptions {
7+
top?: number;
8+
duration?: number;
9+
prefixCls?: string;
10+
getContainer?: () => HTMLElement;
11+
transitionName?: string;
12+
maxCount?: number;
13+
rtl?: boolean;
14+
}
15+
16+
export interface ArgsProps {
17+
content: VueNode;
18+
duration?: number;
19+
type?: NoticeType;
20+
onClose?: () => void;
21+
icon?: VueNode;
22+
key?: string | number;
23+
style?: CSSProperties;
24+
className?: string;
25+
onClick?: (e: Event) => void;
26+
}
27+
28+
export type JointContent = VueNode | ArgsProps;
29+
30+
export interface MessageType extends PromiseLike<boolean> {
31+
(): void;
32+
}
33+
34+
export type TypeOpen = (
35+
content: JointContent,
36+
duration?: number | VoidFunction, // Also can use onClose directly
37+
onClose?: VoidFunction,
38+
) => MessageType;
39+
40+
export interface MessageInstance {
41+
info: TypeOpen;
42+
success: TypeOpen;
43+
error: TypeOpen;
44+
warning: TypeOpen;
45+
loading: TypeOpen;
46+
open(args: ArgsProps): MessageType;
47+
destroy(key?: Key): void;
48+
}

0 commit comments

Comments
 (0)