-
Notifications
You must be signed in to change notification settings - Fork 104
/
AlertsHost.token.ts
117 lines (92 loc) · 2.35 KB
/
AlertsHost.token.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
import { noop } from '@tok/ui/utility/noop';
import { InjectionKey, Ref, ref } from 'vue';
type Component = any;
export type AlertHostParams<T = unknown> = {
// default: success
type?: 'success' | 'error' | 'telegram' | string;
// default: true
autoClose?: boolean | number;
// default: true
hasClose?: boolean;
data?: T;
onClose?: () => void;
};
type InternalAlert = {
id: string;
content: Component | string;
type: NonNullable<AlertHostParams['type']>;
closable: boolean;
data: unknown;
onClose?: () => void;
};
const DEFAULT_CLOSE_TIMEOUT = 5000;
export const AlertHostDefaultParams: Required<AlertHostParams> = {
type: 'success',
autoClose: 5000,
data: undefined,
hasClose: true,
onClose: noop,
};
type AlertsConnector = {
alerts: Ref<InternalAlert[]>;
show: (
id: string,
content: string | Component,
params?: AlertHostParams
) => void;
close: (id: string) => void;
closeLast: () => void;
};
export function createAlertsConnector(): AlertsConnector {
const alerts = ref<InternalAlert[]>([]);
const timeoutDict = new Map<string, ReturnType<typeof setTimeout>>();
const close: AlertsConnector['close'] = (id) => {
const timeout = timeoutDict.get(id);
if (timeout) {
clearTimeout(timeout);
}
timeoutDict.delete(id);
alerts.value = alerts.value.filter(({ id: alertId }) => alertId !== id);
};
const show: AlertsConnector['show'] = (
id,
content,
params = AlertHostDefaultParams
) => {
const {
type = AlertHostDefaultParams.type,
autoClose = AlertHostDefaultParams.autoClose,
hasClose = AlertHostDefaultParams.hasClose,
onClose,
} = params;
alerts.value = alerts.value.concat({
id,
content,
type: type,
closable: hasClose,
data: params.data,
onClose,
});
if (autoClose) {
const closeTimeout =
typeof autoClose === 'number' ? autoClose : DEFAULT_CLOSE_TIMEOUT;
const timeout = setTimeout(() => {
close(id);
}, closeTimeout);
timeoutDict.set(id, timeout);
}
};
const closeLast: AlertsConnector['closeLast'] = () => {
const last = alerts.value[0];
if (last) {
close(last.id);
}
};
return {
alerts,
close,
closeLast,
show,
};
}
export const ALERTS_HOST_TOKEN = Symbol() as InjectionKey<AlertsConnector>;