@4i/modal-manager 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.babelrc +3 -0
- package/package.json +35 -0
- package/src/components/backdrop.css +44 -0
- package/src/components/modal-provider.tsx +108 -0
- package/src/index.ts +7 -0
- package/src/utils/config/modal-actions.ts +11 -0
- package/src/utils/config/modal-list.ts +11 -0
- package/src/utils/service/Manager.ts +30 -0
- package/src/utils/service/ModalManager.ts +30 -0
package/.babelrc
ADDED
package/package.json
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
{
|
2
|
+
"name": "@4i/modal-manager",
|
3
|
+
"version": "1.0.0",
|
4
|
+
"description": "",
|
5
|
+
"main": "src/index.js",
|
6
|
+
"scripts": {
|
7
|
+
"test": "echo \"Error: no test specified\" && exit 1",
|
8
|
+
"build": "babel src -d lib"
|
9
|
+
},
|
10
|
+
"repository": {
|
11
|
+
"type": "git",
|
12
|
+
"url": "git+https://github.com/tonichiga/modal-manager.git"
|
13
|
+
},
|
14
|
+
"keywords": [
|
15
|
+
"modal",
|
16
|
+
"manager"
|
17
|
+
],
|
18
|
+
"author": "Toni",
|
19
|
+
"license": "ISC",
|
20
|
+
"bugs": {
|
21
|
+
"url": "https://github.com/tonichiga/modal-manager/issues"
|
22
|
+
},
|
23
|
+
"homepage": "https://github.com/tonichiga/modal-manager#readme",
|
24
|
+
"dependencies": {
|
25
|
+
"react": "^18.2.0",
|
26
|
+
"uuid": "^9.0.1"
|
27
|
+
},
|
28
|
+
"devDependencies": {
|
29
|
+
"@babel/cli": "^7.23.4",
|
30
|
+
"@babel/core": "^7.23.5",
|
31
|
+
"@babel/preset-env": "^7.23.5",
|
32
|
+
"@babel/preset-react": "^7.23.3",
|
33
|
+
"@types/node": "^20.10.2"
|
34
|
+
}
|
35
|
+
}
|
@@ -0,0 +1,44 @@
|
|
1
|
+
@keyframes bg_opacity_scale {
|
2
|
+
from {
|
3
|
+
transform: scale(0.8);
|
4
|
+
}
|
5
|
+
to {
|
6
|
+
transform: scale(1);
|
7
|
+
}
|
8
|
+
}
|
9
|
+
|
10
|
+
@keyframes bg_opacity {
|
11
|
+
from {
|
12
|
+
opacity: 0;
|
13
|
+
}
|
14
|
+
to {
|
15
|
+
opacity: 1;
|
16
|
+
}
|
17
|
+
}
|
18
|
+
|
19
|
+
.backdrop_modal_manager {
|
20
|
+
position: absolute;
|
21
|
+
display: flex;
|
22
|
+
justify-content: center;
|
23
|
+
align-items: center;
|
24
|
+
top: 0;
|
25
|
+
left: 0;
|
26
|
+
right: 0;
|
27
|
+
bottom: 0;
|
28
|
+
width: 100%;
|
29
|
+
height: 100%;
|
30
|
+
background-color: rgba(0, 0, 0, 0.5);
|
31
|
+
position: fixed;
|
32
|
+
z-index: 1000;
|
33
|
+
opacity: 0;
|
34
|
+
animation: bg_opacity 150ms ease-in-out forwards;
|
35
|
+
}
|
36
|
+
|
37
|
+
.backdrop_modal_manager > div {
|
38
|
+
animation: bg_opacity_scale 150ms ease-in-out forwards;
|
39
|
+
}
|
40
|
+
|
41
|
+
.main_container_modal_manager {
|
42
|
+
opacity: 0;
|
43
|
+
animation: bg_opacity 250ms forwards;
|
44
|
+
}
|
@@ -0,0 +1,108 @@
|
|
1
|
+
import React, { useEffect, useRef, useState } from "react";
|
2
|
+
import manager from "../utils/service/ModalManager";
|
3
|
+
import "./backdrop.css";
|
4
|
+
import modal from "../utils/service/ModalManager";
|
5
|
+
import modalList from "../utils/config/modal-list";
|
6
|
+
|
7
|
+
interface ModalProviderProps {
|
8
|
+
CustomComponent?: React.ComponentType;
|
9
|
+
}
|
10
|
+
|
11
|
+
const ModalProvider = ({ CustomComponent }: ModalProviderProps) => {
|
12
|
+
const [data, setData] = useState([]);
|
13
|
+
const [names, setNames] = useState([]);
|
14
|
+
const modalRef = useRef([]);
|
15
|
+
|
16
|
+
useEffect(() => {
|
17
|
+
const handleOpenModal = (name, data) => {
|
18
|
+
setData((prev) => [...prev, data]);
|
19
|
+
setNames((prev) => [...prev, name]);
|
20
|
+
};
|
21
|
+
|
22
|
+
const handleClose = (position) => {
|
23
|
+
if (position === "all") {
|
24
|
+
setData([]);
|
25
|
+
setNames([]);
|
26
|
+
return;
|
27
|
+
}
|
28
|
+
|
29
|
+
if (position === -1) {
|
30
|
+
// remove last
|
31
|
+
setData((prev) => prev.filter((_, index) => index !== prev.length - 1));
|
32
|
+
setNames((prev) =>
|
33
|
+
prev.filter((_, index) => index !== prev.length - 1)
|
34
|
+
);
|
35
|
+
return;
|
36
|
+
}
|
37
|
+
|
38
|
+
if (position === 0) {
|
39
|
+
// remove first
|
40
|
+
setData((prev) => prev.filter((_, index) => index !== 0));
|
41
|
+
setNames((prev) => prev.filter((_, index) => index !== 0));
|
42
|
+
return;
|
43
|
+
}
|
44
|
+
|
45
|
+
// remove position index
|
46
|
+
setData((prev) => prev.filter((_, index) => index !== prev.length - 1));
|
47
|
+
setNames((prev) => prev.filter((_, index) => index !== prev.length - 1));
|
48
|
+
};
|
49
|
+
|
50
|
+
manager.addEventListener("change", handleOpenModal);
|
51
|
+
manager.addEventListener("close", handleClose);
|
52
|
+
return () => {
|
53
|
+
manager.removeEventListener("change", handleOpenModal);
|
54
|
+
manager.removeEventListener("close", handleClose);
|
55
|
+
};
|
56
|
+
}, []);
|
57
|
+
|
58
|
+
const activeModals = names.map((name) => {
|
59
|
+
const Component = modalList[name] || (() => <></>);
|
60
|
+
return Component;
|
61
|
+
});
|
62
|
+
|
63
|
+
const handleCloseModal = (index, e) => {
|
64
|
+
if (
|
65
|
+
modalRef.current[index] &&
|
66
|
+
!modalRef.current[index].contains(e.target)
|
67
|
+
) {
|
68
|
+
modal.close(index);
|
69
|
+
}
|
70
|
+
};
|
71
|
+
|
72
|
+
const refReducer = (index, value) => {
|
73
|
+
modalRef.current[index] = value;
|
74
|
+
};
|
75
|
+
|
76
|
+
return (
|
77
|
+
activeModals.length !== 0 &&
|
78
|
+
activeModals.map((Component, i) => {
|
79
|
+
const Modal = Component;
|
80
|
+
|
81
|
+
return (
|
82
|
+
<>
|
83
|
+
{CustomComponent ? (
|
84
|
+
<CustomComponent key={i} {...data[i]} />
|
85
|
+
) : (
|
86
|
+
<div
|
87
|
+
key={i}
|
88
|
+
className="backdrop_modal_manager"
|
89
|
+
onClick={(e) => {
|
90
|
+
handleCloseModal(i, e);
|
91
|
+
}}
|
92
|
+
>
|
93
|
+
<div
|
94
|
+
ref={(ref) => {
|
95
|
+
refReducer(i, ref);
|
96
|
+
}}
|
97
|
+
>
|
98
|
+
<Modal key={i} {...data[i]} />
|
99
|
+
</div>
|
100
|
+
</div>
|
101
|
+
)}
|
102
|
+
</>
|
103
|
+
);
|
104
|
+
})
|
105
|
+
);
|
106
|
+
};
|
107
|
+
|
108
|
+
export default ModalProvider;
|
package/src/index.ts
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
import Manager from "./utils/service/Manager";
|
2
|
+
import modal from "./utils/service/ModalManager";
|
3
|
+
import ModalProvider from "./components/modal-provider";
|
4
|
+
import { setModalList } from "./utils/config/modal-list";
|
5
|
+
import { setModalActions } from "./utils/config/modal-actions";
|
6
|
+
|
7
|
+
export { Manager, modal, ModalProvider, setModalList, setModalActions };
|
@@ -0,0 +1,30 @@
|
|
1
|
+
import { EventEmitter } from "events";
|
2
|
+
|
3
|
+
const Constants = {
|
4
|
+
CHANGE: "change",
|
5
|
+
CLOSE: "close",
|
6
|
+
};
|
7
|
+
|
8
|
+
type TData = {
|
9
|
+
[key: string]: any;
|
10
|
+
};
|
11
|
+
|
12
|
+
class Manager {
|
13
|
+
emitter: EventEmitter;
|
14
|
+
name: string;
|
15
|
+
data: { [key: string]: any };
|
16
|
+
|
17
|
+
constructor() {
|
18
|
+
this.emitter = new EventEmitter();
|
19
|
+
}
|
20
|
+
|
21
|
+
addEventListener(event: string, listener: (...args: any[]) => void) {
|
22
|
+
this.emitter.addListener(event, listener);
|
23
|
+
}
|
24
|
+
|
25
|
+
removeEventListener(event: string, listener: (...args: any[]) => void) {
|
26
|
+
this.emitter.removeListener(event, listener);
|
27
|
+
}
|
28
|
+
}
|
29
|
+
|
30
|
+
export default Manager;
|
@@ -0,0 +1,30 @@
|
|
1
|
+
import Manager from "./Manager";
|
2
|
+
import { v4 as uuidv4 } from "uuid";
|
3
|
+
|
4
|
+
const constants = {
|
5
|
+
CHANGE: "change",
|
6
|
+
CLOSE: "close",
|
7
|
+
};
|
8
|
+
|
9
|
+
class ModalManager extends Manager {
|
10
|
+
constructor() {
|
11
|
+
super();
|
12
|
+
}
|
13
|
+
|
14
|
+
create(name: string, data) {
|
15
|
+
this.name = name;
|
16
|
+
this.data = data;
|
17
|
+
this.emitter.emit(constants.CHANGE);
|
18
|
+
}
|
19
|
+
|
20
|
+
call(name: string, data: any = {}) {
|
21
|
+
this.create(name, { modalId: uuidv4(), data });
|
22
|
+
}
|
23
|
+
|
24
|
+
close(position?: number) {
|
25
|
+
this.emitter.emit(constants.CLOSE, position);
|
26
|
+
}
|
27
|
+
}
|
28
|
+
|
29
|
+
const modal = new ModalManager();
|
30
|
+
export default modal;
|