@4i/modal-manager 1.1.10 → 1.1.20

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.
@@ -12,5 +12,5 @@ interface ModalProviderProps {
12
12
  type TData = {
13
13
  [key: string]: any;
14
14
  };
15
- declare const ModalProvider: ({ modalList, isOverflow, className, backdropClassName, onModalStateChange, }: ModalProviderProps) => React.JSX.Element;
15
+ declare const ModalProvider: ({ modalList, isOverflow, className, backdropClassName, onModalStateChange, }: ModalProviderProps) => null;
16
16
  export default ModalProvider;
@@ -82,6 +82,7 @@ var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
82
82
  Object.defineProperty(exports, "__esModule", { value: true });
83
83
  var react_1 = __importStar(require("react"));
84
84
  var ModalManager_1 = __importStar(require("../utils/ModalManager"));
85
+ var react_dom_1 = require("react-dom");
85
86
  var ModalProvider = function (_a) {
86
87
  var modalList = _a.modalList, isOverflow = _a.isOverflow, className = _a.className, backdropClassName = _a.backdropClassName, onModalStateChange = _a.onModalStateChange;
87
88
  var _b = (0, react_1.useState)([]), data = _b[0], setData = _b[1];
@@ -118,7 +119,9 @@ var ModalProvider = function (_a) {
118
119
  var handleClose = function (position) { return __awaiter(void 0, void 0, void 0, function () {
119
120
  return __generator(this, function (_a) {
120
121
  switch (_a.label) {
121
- case 0: return [4 /*yield*/, applyCloseStyles(position)];
122
+ case 0:
123
+ console.log("position", position);
124
+ return [4 /*yield*/, applyCloseStyles(position)];
122
125
  case 1:
123
126
  _a.sent();
124
127
  if (isOverflow) {
@@ -176,7 +179,8 @@ var ModalProvider = function (_a) {
176
179
  var refReducer = function (index, value) {
177
180
  modalRef.current[index] = value;
178
181
  };
179
- return (react_1.default.createElement(react_1.default.Fragment, null, data.length !== 0 &&
182
+ var body = document.body;
183
+ (0, react_dom_1.createPortal)(react_1.default.createElement(react_1.default.Fragment, null, data.length !== 0 &&
180
184
  data.map(function (item, i) {
181
185
  var Modal = activeModals[i] || (function () { return react_1.default.createElement(react_1.default.Fragment, null); });
182
186
  return (react_1.default.createElement("div", { "data-index": i, key: item.modalId, className: "modal-manager backdrop_modal_manager ".concat(backdropClassName) },
@@ -189,6 +193,7 @@ var ModalProvider = function (_a) {
189
193
  refReducer(i, ref);
190
194
  } },
191
195
  react_1.default.createElement(Modal, __assign({}, item.data))))));
192
- })));
196
+ })), body);
197
+ return null;
193
198
  };
194
199
  exports.default = ModalProvider;
@@ -1,163 +1,169 @@
1
- "use client";
2
-
3
- import React, { useEffect, useRef, useState } from "react";
4
- import modal, { constants } from "../utils/ModalManager";
5
-
6
- export type ModalList = { [key: string]: React.ComponentType };
7
-
8
- interface ModalProviderProps {
9
- modalList: any;
10
- isOverflow?: boolean;
11
- className?: string;
12
- backdropClassName?: string;
13
- onModalStateChange?: (
14
- modalState: boolean,
15
- data: TData[],
16
- names: string[]
17
- ) => void;
18
- }
19
-
20
- type TData = { [key: string]: any };
21
-
22
- const ModalProvider = ({
23
- modalList,
24
- isOverflow,
25
- className,
26
- backdropClassName,
27
- onModalStateChange,
28
- }: ModalProviderProps) => {
29
- const [data, setData] = useState<TData[]>([]);
30
- const [names, setNames] = useState<string[]>([]);
31
- const modalRef = useRef<any[]>([]);
32
-
33
- const applyCloseStyles = (index: number) => {
34
- return new Promise((resolve) => {
35
- const modal = document.querySelector(
36
- `[data-index="${index}"]`
37
- ) as HTMLElement;
38
- if (!modal) return;
39
- modal.classList.add("closing");
40
- setTimeout(() => {
41
- resolve(true);
42
- }, 150);
43
- });
44
- };
45
-
46
- useEffect(() => {
47
- if (!onModalStateChange) return;
48
- const modalState = data.length !== 0;
49
- onModalStateChange(modalState, data, names);
50
- // eslint-disable-next-line react-hooks/exhaustive-deps
51
- }, [data, names]);
52
-
53
- useEffect(() => {
54
- const handleOpenModal = (name: string, data: TData) => {
55
- setData((prev: TData[]) => [...prev, data]);
56
- setNames((prev: string[]) => [...prev, name]);
57
-
58
- if (isOverflow) {
59
- if (typeof document === "undefined") return;
60
- document.body.style.overflow = "hidden";
61
- }
62
- };
63
-
64
- const handleClose = async (position: number | string) => {
65
- await applyCloseStyles(position as number);
66
- if (isOverflow) {
67
- if (typeof document !== "undefined") {
68
- document.body.style.overflow = "";
69
- }
70
- }
71
-
72
- if (position === "all") {
73
- setData([]);
74
- setNames([]);
75
- return;
76
- }
77
-
78
- if (position === -1) {
79
- // remove last
80
- setData((prev: TData[]) =>
81
- prev.filter((_, index) => index !== prev.length - 1)
82
- );
83
- setNames((prev: string[]) =>
84
- prev.filter((_, index) => index !== prev.length - 1)
85
- );
86
- return;
87
- }
88
-
89
- if (position === 0) {
90
- // remove first
91
- setData((prev: TData[]) => prev.filter((_, index) => index !== 0));
92
- setNames((prev: string[]) => prev.filter((_, index) => index !== 0));
93
- return;
94
- }
95
-
96
- // remove position index
97
- setData((prev: TData[]) =>
98
- prev.filter((_, index) => index !== prev.length - 1)
99
- );
100
- setNames((prev: string[]) =>
101
- prev.filter((_, index) => index !== prev.length - 1)
102
- );
103
- };
104
-
105
- modal.addEventListener(constants.CHANGE, handleOpenModal);
106
- modal.addEventListener(constants.CLOSE, handleClose);
107
- return () => {
108
- modal.removeEventListener(constants.CHANGE, handleOpenModal);
109
- modal.removeEventListener(constants.CLOSE, handleClose);
110
- };
111
- // eslint-disable-next-line react-hooks/exhaustive-deps
112
- }, []);
113
-
114
- const activeModals = names.map((name: string) => {
115
- const Component = modalList[name] || (() => <></>);
116
- return Component;
117
- });
118
-
119
- const handleCloseModal = (index: number) => {
120
- modal.close(index);
121
- };
122
-
123
- const refReducer = (index: number, value: any) => {
124
- modalRef.current[index] = value;
125
- };
126
-
127
- return (
128
- <>
129
- {data.length !== 0 &&
130
- data.map((item, i) => {
131
- const Modal = activeModals[i] || (() => <></>);
132
-
133
- return (
134
- <div
135
- data-index={i}
136
- key={item.modalId}
137
- className={`modal-manager backdrop_modal_manager ${backdropClassName}`}
138
- >
139
- <div
140
- onClick={(e) => {
141
- e.stopPropagation();
142
- handleCloseModal(i);
143
- }}
144
- className="backdrop"
145
- />
146
- {/* // h-full modal not close */}
147
- <div className={`${className} modal_paper`}>
148
- <div
149
- ref={(ref) => {
150
- refReducer(i, ref);
151
- }}
152
- >
153
- <Modal {...item.data} />
154
- </div>
155
- </div>
156
- </div>
157
- );
158
- })}
159
- </>
160
- );
161
- };
162
-
163
- export default ModalProvider;
1
+ "use client";
2
+
3
+ import React, { useEffect, useRef, useState } from "react";
4
+ import modal, { constants } from "../utils/ModalManager";
5
+ import { createPortal } from "react-dom";
6
+
7
+ export type ModalList = { [key: string]: React.ComponentType };
8
+
9
+ interface ModalProviderProps {
10
+ modalList: any;
11
+ isOverflow?: boolean;
12
+ className?: string;
13
+ backdropClassName?: string;
14
+ onModalStateChange?: (
15
+ modalState: boolean,
16
+ data: TData[],
17
+ names: string[]
18
+ ) => void;
19
+ }
20
+
21
+ type TData = { [key: string]: any };
22
+
23
+ const ModalProvider = ({
24
+ modalList,
25
+ isOverflow,
26
+ className,
27
+ backdropClassName,
28
+ onModalStateChange,
29
+ }: ModalProviderProps) => {
30
+ const [data, setData] = useState<TData[]>([]);
31
+ const [names, setNames] = useState<string[]>([]);
32
+ const modalRef = useRef<any[]>([]);
33
+
34
+ const applyCloseStyles = (index: number) => {
35
+ return new Promise((resolve) => {
36
+ const modal = document.querySelector(
37
+ `[data-index="${index}"]`
38
+ ) as HTMLElement;
39
+ if (!modal) return;
40
+ modal.classList.add("closing");
41
+ setTimeout(() => {
42
+ resolve(true);
43
+ }, 150);
44
+ });
45
+ };
46
+
47
+ useEffect(() => {
48
+ if (!onModalStateChange) return;
49
+ const modalState = data.length !== 0;
50
+ onModalStateChange(modalState, data, names);
51
+ // eslint-disable-next-line react-hooks/exhaustive-deps
52
+ }, [data, names]);
53
+
54
+ useEffect(() => {
55
+ const handleOpenModal = (name: string, data: TData) => {
56
+ setData((prev: TData[]) => [...prev, data]);
57
+ setNames((prev: string[]) => [...prev, name]);
58
+
59
+ if (isOverflow) {
60
+ if (typeof document === "undefined") return;
61
+ document.body.style.overflow = "hidden";
62
+ }
63
+ };
64
+
65
+ const handleClose = async (position: number | string) => {
66
+ console.log("position", position);
67
+ await applyCloseStyles(position as number);
68
+ if (isOverflow) {
69
+ if (typeof document !== "undefined") {
70
+ document.body.style.overflow = "";
71
+ }
72
+ }
73
+
74
+ if (position === "all") {
75
+ setData([]);
76
+ setNames([]);
77
+ return;
78
+ }
79
+
80
+ if (position === -1) {
81
+ // remove last
82
+ setData((prev: TData[]) =>
83
+ prev.filter((_, index) => index !== prev.length - 1)
84
+ );
85
+ setNames((prev: string[]) =>
86
+ prev.filter((_, index) => index !== prev.length - 1)
87
+ );
88
+ return;
89
+ }
90
+
91
+ if (position === 0) {
92
+ // remove first
93
+ setData((prev: TData[]) => prev.filter((_, index) => index !== 0));
94
+ setNames((prev: string[]) => prev.filter((_, index) => index !== 0));
95
+ return;
96
+ }
97
+
98
+ // remove position index
99
+ setData((prev: TData[]) =>
100
+ prev.filter((_, index) => index !== prev.length - 1)
101
+ );
102
+ setNames((prev: string[]) =>
103
+ prev.filter((_, index) => index !== prev.length - 1)
104
+ );
105
+ };
106
+
107
+ modal.addEventListener(constants.CHANGE, handleOpenModal);
108
+ modal.addEventListener(constants.CLOSE, handleClose);
109
+ return () => {
110
+ modal.removeEventListener(constants.CHANGE, handleOpenModal);
111
+ modal.removeEventListener(constants.CLOSE, handleClose);
112
+ };
113
+ // eslint-disable-next-line react-hooks/exhaustive-deps
114
+ }, []);
115
+
116
+ const activeModals = names.map((name: string) => {
117
+ const Component = modalList[name] || (() => <></>);
118
+ return Component;
119
+ });
120
+
121
+ const handleCloseModal = (index: number) => {
122
+ modal.close(index);
123
+ };
124
+
125
+ const refReducer = (index: number, value: any) => {
126
+ modalRef.current[index] = value;
127
+ };
128
+
129
+ const body = document.body;
130
+ createPortal(
131
+ <>
132
+ {data.length !== 0 &&
133
+ data.map((item, i) => {
134
+ const Modal = activeModals[i] || (() => <></>);
135
+
136
+ return (
137
+ <div
138
+ data-index={i}
139
+ key={item.modalId}
140
+ className={`modal-manager backdrop_modal_manager ${backdropClassName}`}
141
+ >
142
+ <div
143
+ onClick={(e) => {
144
+ e.stopPropagation();
145
+ handleCloseModal(i);
146
+ }}
147
+ className="backdrop"
148
+ />
149
+ {/* // h-full modal not close */}
150
+ <div className={`${className} modal_paper`}>
151
+ <div
152
+ ref={(ref) => {
153
+ refReducer(i, ref);
154
+ }}
155
+ >
156
+ <Modal {...item.data} />
157
+ </div>
158
+ </div>
159
+ </div>
160
+ );
161
+ })}
162
+ </>,
163
+ body
164
+ );
165
+
166
+ return null;
167
+ };
168
+
169
+ export default ModalProvider;
package/src/index.ts CHANGED
@@ -1,5 +1,5 @@
1
- import Manager from "./utils/Manager";
2
- import modal from "./utils/ModalManager";
3
- import ModalProvider from "./components/modal-provider";
4
-
5
- export { Manager, modal, ModalProvider };
1
+ import Manager from "./utils/Manager";
2
+ import modal from "./utils/ModalManager";
3
+ import ModalProvider from "./components/modal-provider";
4
+
5
+ export { Manager, modal, ModalProvider };
package/src/styles.css CHANGED
@@ -1,77 +1,77 @@
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
- @keyframes bg_opacity_out {
20
- from {
21
- opacity: 1;
22
- }
23
- to {
24
- opacity: 0;
25
- }
26
- }
27
-
28
- @keyframes bg_scale_out {
29
- from {
30
- opacity: 1;
31
- transform: scale(1);
32
- }
33
- to {
34
- opacity: 0;
35
- transform: scale(0.9);
36
- }
37
- }
38
-
39
- .modal-manager.backdrop_modal_manager {
40
- display: flex;
41
- justify-content: center;
42
- align-items: center;
43
- top: 0;
44
- left: 0;
45
- right: 0;
46
- bottom: 0;
47
- width: 100%;
48
- height: 100%;
49
- position: fixed;
50
- z-index: 1000;
51
- }
52
-
53
- .modal-manager .backdrop {
54
- background-color: rgba(0, 0, 0, 0.5);
55
- opacity: 0;
56
- position: fixed;
57
- top: 0;
58
- left: 0;
59
- right: 0;
60
- bottom: 0;
61
- animation: bg_opacity 150ms ease-in-out forwards;
62
- }
63
-
64
- .modal-manager .modal_paper {
65
- position: relative;
66
- z-index: 1001;
67
- animation: bg_opacity_scale 150ms ease-in-out forwards;
68
- width: 100%;
69
- }
70
-
71
- .modal-manager.closing .backdrop {
72
- animation: bg_opacity_out 150ms ease-in-out forwards;
73
- }
74
-
75
- .modal-manager.closing .modal_paper {
76
- animation: bg_scale_out 150ms ease-in-out forwards;
77
- }
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
+ @keyframes bg_opacity_out {
20
+ from {
21
+ opacity: 1;
22
+ }
23
+ to {
24
+ opacity: 0;
25
+ }
26
+ }
27
+
28
+ @keyframes bg_scale_out {
29
+ from {
30
+ opacity: 1;
31
+ transform: scale(1);
32
+ }
33
+ to {
34
+ opacity: 0;
35
+ transform: scale(0.9);
36
+ }
37
+ }
38
+
39
+ .modal-manager.backdrop_modal_manager {
40
+ display: flex;
41
+ justify-content: center;
42
+ align-items: center;
43
+ top: 0;
44
+ left: 0;
45
+ right: 0;
46
+ bottom: 0;
47
+ width: 100%;
48
+ height: 100%;
49
+ position: fixed;
50
+ z-index: 20000;
51
+ }
52
+
53
+ .modal-manager .backdrop {
54
+ background-color: rgba(0, 0, 0, 0.5);
55
+ opacity: 0;
56
+ position: fixed;
57
+ top: 0;
58
+ left: 0;
59
+ right: 0;
60
+ bottom: 0;
61
+ animation: bg_opacity 150ms ease-in-out forwards;
62
+ }
63
+
64
+ .modal-manager .modal_paper {
65
+ position: relative;
66
+ z-index: 1001;
67
+ animation: bg_opacity_scale 150ms ease-in-out forwards;
68
+ width: 100%;
69
+ }
70
+
71
+ .modal-manager.closing .backdrop {
72
+ animation: bg_opacity_out 150ms ease-in-out forwards;
73
+ }
74
+
75
+ .modal-manager.closing .modal_paper {
76
+ animation: bg_scale_out 150ms ease-in-out forwards;
77
+ }
@@ -1,27 +1,27 @@
1
- import { EventEmitter } from "events";
2
-
3
- type TData = {
4
- [key: string]: any;
5
- };
6
-
7
- class Manager {
8
- emitter: EventEmitter;
9
- name: string | null;
10
- data: { [key: string]: any };
11
-
12
- constructor() {
13
- this.name = "";
14
- this.data = {};
15
- this.emitter = new EventEmitter();
16
- }
17
-
18
- addEventListener(event: string, listener: (...args: any[]) => void) {
19
- this.emitter.addListener(event, listener);
20
- }
21
-
22
- removeEventListener(event: string, listener: (...args: any[]) => void) {
23
- this.emitter.removeListener(event, listener);
24
- }
25
- }
26
-
27
- export default Manager;
1
+ import { EventEmitter } from "events";
2
+
3
+ type TData = {
4
+ [key: string]: any;
5
+ };
6
+
7
+ class Manager {
8
+ emitter: EventEmitter;
9
+ name: string | null;
10
+ data: { [key: string]: any };
11
+
12
+ constructor() {
13
+ this.name = "";
14
+ this.data = {};
15
+ this.emitter = new EventEmitter();
16
+ }
17
+
18
+ addEventListener(event: string, listener: (...args: any[]) => void) {
19
+ this.emitter.addListener(event, listener);
20
+ }
21
+
22
+ removeEventListener(event: string, listener: (...args: any[]) => void) {
23
+ this.emitter.removeListener(event, listener);
24
+ }
25
+ }
26
+
27
+ export default Manager;