-
Notifications
You must be signed in to change notification settings - Fork 297
/
Copy pathModalPortal.js
109 lines (90 loc) · 2.48 KB
/
ModalPortal.js
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
import React from 'react';
import BaseModal from './components/BaseModal';
import BottomModal from './components/BottomModal';
let modal
class ModalPortal extends React.Component {
constructor(props) {
super(props);
this.state = { stack: [] };
this.id = 0;
modal = this;
}
static get ref() {
return modal;
}
static get size() {
return modal.state.stack.length;
}
static show(children, props) {
return modal.show({ children, ...props });
}
static update(key, props) {
modal.update(key, props);
}
static dismiss(key) {
modal.dismiss(key);
}
static dismissAll() {
modal.dismissAll();
}
get current() {
if (this.state.stack.length) {
return this.state.stack[this.state.stack.length-1].key;
}
}
generateKey = () => `modal-${this.id++}`
getIndex = key => this.state.stack.findIndex(i => i.key === key)
getProps = (props) => {
const key = props.key || this.generateKey();
return { visible: true, ...props, key };
}
show = (props) => {
const mergedProps = this.getProps(props);
this.setState(({ stack }) => {
return { stack: stack.concat(mergedProps) };
});
return mergedProps.key;
}
update = (key, props) => {
const mergedProps = this.getProps({ ...props, key });
this.setState(({ stack }) => {
const index = this.getIndex(key);
stack[index] = { ...stack[index], ...mergedProps };
return { stack };
});
}
dismiss = (key = this.current) => {
if (!key) return;
const props = { ...this.state.stack[this.getIndex(key)], visible: false };
this.update(key, props);
}
dismissAll = () => this.state.stack.forEach(({ key }) => this.dismiss(key));
dismissHandler = (key) => {
// dismiss hander: which will remove data from stack and call onDismissed callback
const { onDismiss = () => {} } = this.state.stack[this.getIndex(key)];
this.setState(({ stack }) => {
return { stack: stack.filter(i => i.key !== key) };
}, onDismiss);
}
renderModal = ({ type = 'modal', ...props }) => {
if (type === 'modal') {
return (
<BaseModal
{...props}
onDismiss={() => this.dismissHandler(props.key)}
/>
);
} else if (type === 'bottomModal') {
return (
<BottomModal
{...props}
onDismiss={() => this.dismissHandler(props.key)}
/>
);
}
}
render() {
return this.state.stack.map(this.renderModal);
}
}
export default ModalPortal;