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
|
import { CSSProperties, ReactNode, useState, createContext } from "react";
import CloseIcon from '@material-ui/icons/Close';
function ToastArea(props: {
style?: CSSProperties
children?: ReactNode
rerender?: boolean;
}) {
return <div id="ToastArea" style={{
position: "fixed",
whiteSpace: "nowrap",
bottom: 12,
left: "50%",
transform: "translateX(-50%)",
zIndex: 1,
maxWidth: 600,
width: "calc(100% - 48px - 48px)",
margin: "0 24px",
...props.style
}}>{props.children}</div>
}
function Toast(props: {
text?: string
icon?: ReactNode
children?: ReactNode
type?: "normal"|"confirmation"|"error"
style?: CSSProperties
}) {
var [visible, setVisibility] = useState(true);
setTimeout(() => setVisibility(false), 10e3);
return visible && <div style={{
padding: 0,
marginBottom: 12,
borderRadius: 8,
boxShadow: "0 8px 12px -4px #00000033",
color:
props.type === "confirmation" ? "var(--background)" : "var(--text)",
backgroundColor:
props.type === "normal" ? "var(--background)" :
props.type === "confirmation" ? "var(--disk-b)" :
props.type === "error" ? "var(--disk-a)" : "var(--background)",
...props.style
}}>
{
props.children ||
<div style={{ lineHeight: 0 }}>
<div style={{
fontSize: 0,
margin: 16,
display: "inline-block",
verticalAlign: "top",
width: 32, height: 32
}}>{props.icon}</div>
<h2 style={{
margin: "20px 0",
display: "inline-block",
width: "calc(100% - 128px)",
verticalAlign: "top",
fontSize: 20,
userSelect: "none"
}}>{props.text}</h2>
<div style={{
padding: 20,
display: "inline-block",
cursor: "pointer"
}} onClick={() => setVisibility(false)}>
<CloseIcon/>
</div>
</div>
}
</div>
}
export var ToastContext = createContext<{ toast?: (message: string,
type: "confirmation"|"normal"|"error",
icon?: ReactNode ) => void }>({});
var toasts: Array<JSX.Element> = [];
export function ToastContextWrapper(props: { children?: ReactNode }) {
var [dummyState, rerender] = useState(false);
return <ToastContext.Provider value={{ toast: (message: string,
type: "confirmation"|"normal"|"error",
icon?: ReactNode ) => {
toasts.push(<Toast type={type} text={message} icon={icon}/>);
rerender(!dummyState);
} }}>
{ props.children }
<ToastArea rerender={dummyState}>
{toasts}
</ToastArea>
</ToastContext.Provider>
}
|