@lerx/promise-modal 0.1.0 → 0.2.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/dist/app/ModalManager.d.ts +0 -1
- package/dist/app/constant.d.ts +0 -1
- package/dist/bootstrap/BootstrapProvider/BootstrapProvider.d.ts +0 -1
- package/dist/bootstrap/BootstrapProvider/helpers/bootstrap.d.ts +0 -1
- package/dist/bootstrap/BootstrapProvider/hooks/useInitialize.d.ts +0 -1
- package/dist/bootstrap/BootstrapProvider/index.d.ts +0 -1
- package/dist/bootstrap/BootstrapProvider/type.d.ts +0 -1
- package/dist/bootstrap/BootstrapProvider/useBootstrap.d.ts +0 -1
- package/dist/bootstrap/index.d.ts +0 -1
- package/dist/components/Anchor/Anchor.d.ts +0 -1
- package/dist/components/Anchor/classNames.emotion.d.ts +0 -1
- package/dist/components/Anchor/index.d.ts +0 -1
- package/dist/components/Background/Background.d.ts +0 -1
- package/dist/components/Background/classNames.emotion.d.ts +0 -1
- package/dist/components/Background/index.d.ts +0 -1
- package/dist/components/FallbackComponents/FallbackContent.d.ts +0 -1
- package/dist/components/FallbackComponents/FallbackFooter.d.ts +0 -1
- package/dist/components/FallbackComponents/FallbackForegroundFrame.d.ts +0 -1
- package/dist/components/FallbackComponents/FallbackSubtitle.d.ts +0 -1
- package/dist/components/FallbackComponents/FallbackTitle.d.ts +0 -1
- package/dist/components/FallbackComponents/classNames.emotion.d.ts +0 -1
- package/dist/components/FallbackComponents/index.d.ts +0 -1
- package/dist/components/Foreground/Foreground.d.ts +0 -1
- package/dist/components/Foreground/classNames.emotion.d.ts +0 -1
- package/dist/components/Foreground/components/AlertInner.d.ts +0 -1
- package/dist/components/Foreground/components/ConfirmInner.d.ts +0 -1
- package/dist/components/Foreground/components/PromptInner.d.ts +0 -1
- package/dist/components/Foreground/components/index.d.ts +0 -1
- package/dist/components/Foreground/index.d.ts +0 -1
- package/dist/components/Presenter/Presenter.d.ts +0 -1
- package/dist/components/Presenter/classNames.emotion.d.ts +0 -1
- package/dist/components/Presenter/index.d.ts +0 -1
- package/dist/core/handle/alert.d.ts +0 -1
- package/dist/core/handle/confirm.d.ts +0 -1
- package/dist/core/handle/index.d.ts +0 -1
- package/dist/core/handle/prompt.d.ts +0 -1
- package/dist/core/index.d.ts +0 -1
- package/dist/core/node/ModalNode/AbstractNode.d.ts +0 -1
- package/dist/core/node/ModalNode/AlertNode.d.ts +0 -1
- package/dist/core/node/ModalNode/ConfirmNode.d.ts +0 -1
- package/dist/core/node/ModalNode/PromptNode.d.ts +0 -1
- package/dist/core/node/ModalNode/index.d.ts +0 -1
- package/dist/core/node/index.d.ts +0 -1
- package/dist/core/node/nodeFactory.d.ts +0 -1
- package/dist/core/node/type.d.ts +0 -1
- package/dist/hooks/useActiveModalCount.d.ts +0 -1
- package/dist/hooks/useDefaultPathname.d.ts +0 -1
- package/dist/hooks/useDestroyAfter.d.ts +0 -1
- package/dist/hooks/useModalAnimation.d.ts +0 -1
- package/dist/hooks/useSubscribeModal.d.ts +0 -1
- package/dist/index.cjs +966 -0
- package/dist/index.d.ts +0 -1
- package/dist/index.mjs +953 -0
- package/dist/providers/ConfigurationContext/ConfigurationContext.d.ts +0 -1
- package/dist/providers/ConfigurationContext/ConfigurationContextProvider.d.ts +4 -1
- package/dist/providers/ConfigurationContext/index.d.ts +0 -1
- package/dist/providers/ConfigurationContext/useConfigurationContext.d.ts +0 -1
- package/dist/providers/ModalManagerContext/ModalManagerContext.d.ts +0 -1
- package/dist/providers/ModalManagerContext/ModalManagerContextProvider.d.ts +0 -1
- package/dist/providers/ModalManagerContext/index.d.ts +0 -1
- package/dist/providers/ModalManagerContext/useModalManagerContext.d.ts +0 -1
- package/dist/providers/UserDefinedContext/UserDefinedContext.d.ts +0 -1
- package/dist/providers/UserDefinedContext/UserDefinedContextProvider.d.ts +2 -2
- package/dist/providers/UserDefinedContext/index.d.ts +0 -1
- package/dist/providers/UserDefinedContext/useUserDefinedContext.d.ts +0 -1
- package/dist/providers/index.d.ts +0 -1
- package/dist/types/alert.d.ts +0 -1
- package/dist/types/background.d.ts +0 -1
- package/dist/types/base.d.ts +0 -1
- package/dist/types/confirm.d.ts +0 -1
- package/dist/types/index.d.ts +0 -1
- package/dist/types/modal.d.ts +0 -1
- package/dist/types/prompt.d.ts +0 -1
- package/package.json +19 -31
- package/dist/app/ModalManager.d.ts.map +0 -1
- package/dist/app/constant.d.ts.map +0 -1
- package/dist/bootstrap/BootstrapProvider/BootstrapProvider.d.ts.map +0 -1
- package/dist/bootstrap/BootstrapProvider/helpers/bootstrap.d.ts.map +0 -1
- package/dist/bootstrap/BootstrapProvider/hooks/useInitialize.d.ts.map +0 -1
- package/dist/bootstrap/BootstrapProvider/index.d.ts.map +0 -1
- package/dist/bootstrap/BootstrapProvider/type.d.ts.map +0 -1
- package/dist/bootstrap/BootstrapProvider/useBootstrap.d.ts.map +0 -1
- package/dist/bootstrap/index.d.ts.map +0 -1
- package/dist/components/Anchor/Anchor.d.ts.map +0 -1
- package/dist/components/Anchor/classNames.emotion.d.ts.map +0 -1
- package/dist/components/Anchor/index.d.ts.map +0 -1
- package/dist/components/Background/Background.d.ts.map +0 -1
- package/dist/components/Background/classNames.emotion.d.ts.map +0 -1
- package/dist/components/Background/index.d.ts.map +0 -1
- package/dist/components/FallbackComponents/FallbackContent.d.ts.map +0 -1
- package/dist/components/FallbackComponents/FallbackFooter.d.ts.map +0 -1
- package/dist/components/FallbackComponents/FallbackForegroundFrame.d.ts.map +0 -1
- package/dist/components/FallbackComponents/FallbackSubtitle.d.ts.map +0 -1
- package/dist/components/FallbackComponents/FallbackTitle.d.ts.map +0 -1
- package/dist/components/FallbackComponents/classNames.emotion.d.ts.map +0 -1
- package/dist/components/FallbackComponents/index.d.ts.map +0 -1
- package/dist/components/Foreground/Foreground.d.ts.map +0 -1
- package/dist/components/Foreground/classNames.emotion.d.ts.map +0 -1
- package/dist/components/Foreground/components/AlertInner.d.ts.map +0 -1
- package/dist/components/Foreground/components/ConfirmInner.d.ts.map +0 -1
- package/dist/components/Foreground/components/PromptInner.d.ts.map +0 -1
- package/dist/components/Foreground/components/index.d.ts.map +0 -1
- package/dist/components/Foreground/index.d.ts.map +0 -1
- package/dist/components/Presenter/Presenter.d.ts.map +0 -1
- package/dist/components/Presenter/classNames.emotion.d.ts.map +0 -1
- package/dist/components/Presenter/index.d.ts.map +0 -1
- package/dist/core/handle/alert.d.ts.map +0 -1
- package/dist/core/handle/confirm.d.ts.map +0 -1
- package/dist/core/handle/index.d.ts.map +0 -1
- package/dist/core/handle/prompt.d.ts.map +0 -1
- package/dist/core/index.d.ts.map +0 -1
- package/dist/core/node/ModalNode/AbstractNode.d.ts.map +0 -1
- package/dist/core/node/ModalNode/AlertNode.d.ts.map +0 -1
- package/dist/core/node/ModalNode/ConfirmNode.d.ts.map +0 -1
- package/dist/core/node/ModalNode/PromptNode.d.ts.map +0 -1
- package/dist/core/node/ModalNode/index.d.ts.map +0 -1
- package/dist/core/node/index.d.ts.map +0 -1
- package/dist/core/node/nodeFactory.d.ts.map +0 -1
- package/dist/core/node/type.d.ts.map +0 -1
- package/dist/hooks/useActiveModalCount.d.ts.map +0 -1
- package/dist/hooks/useDefaultPathname.d.ts.map +0 -1
- package/dist/hooks/useDestroyAfter.d.ts.map +0 -1
- package/dist/hooks/useModalAnimation.d.ts.map +0 -1
- package/dist/hooks/useSubscribeModal.d.ts.map +0 -1
- package/dist/index.cjs.js +0 -2
- package/dist/index.cjs.js.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/index.esm.js +0 -2
- package/dist/index.esm.js.map +0 -1
- package/dist/providers/ConfigurationContext/ConfigurationContext.d.ts.map +0 -1
- package/dist/providers/ConfigurationContext/ConfigurationContextProvider.d.ts.map +0 -1
- package/dist/providers/ConfigurationContext/index.d.ts.map +0 -1
- package/dist/providers/ConfigurationContext/useConfigurationContext.d.ts.map +0 -1
- package/dist/providers/ModalManagerContext/ModalManagerContext.d.ts.map +0 -1
- package/dist/providers/ModalManagerContext/ModalManagerContextProvider.d.ts.map +0 -1
- package/dist/providers/ModalManagerContext/index.d.ts.map +0 -1
- package/dist/providers/ModalManagerContext/useModalManagerContext.d.ts.map +0 -1
- package/dist/providers/UserDefinedContext/UserDefinedContext.d.ts.map +0 -1
- package/dist/providers/UserDefinedContext/UserDefinedContextProvider.d.ts.map +0 -1
- package/dist/providers/UserDefinedContext/index.d.ts.map +0 -1
- package/dist/providers/UserDefinedContext/useUserDefinedContext.d.ts.map +0 -1
- package/dist/providers/index.d.ts.map +0 -1
- package/dist/types/alert.d.ts.map +0 -1
- package/dist/types/background.d.ts.map +0 -1
- package/dist/types/base.d.ts.map +0 -1
- package/dist/types/confirm.d.ts.map +0 -1
- package/dist/types/index.d.ts.map +0 -1
- package/dist/types/modal.d.ts.map +0 -1
- package/dist/types/prompt.d.ts.map +0 -1
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,966 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const jsxRuntime = require('react/jsx-runtime');
|
|
4
|
+
const react = require('react');
|
|
5
|
+
const convert = require('@winglet/common-utils/convert');
|
|
6
|
+
const hook = require('@winglet/react-utils/hook');
|
|
7
|
+
const lib = require('@winglet/common-utils/lib');
|
|
8
|
+
const css = require('@emotion/css');
|
|
9
|
+
const reactDom = require('react-dom');
|
|
10
|
+
const array = require('@winglet/common-utils/array');
|
|
11
|
+
const hoc = require('@winglet/react-utils/hoc');
|
|
12
|
+
const filter = require('@winglet/common-utils/filter');
|
|
13
|
+
const render = require('@winglet/react-utils/render');
|
|
14
|
+
const console = require('@winglet/common-utils/console');
|
|
15
|
+
|
|
16
|
+
class ModalManager {
|
|
17
|
+
static #active = false;
|
|
18
|
+
static activate() {
|
|
19
|
+
if (ModalManager.#active)
|
|
20
|
+
return false;
|
|
21
|
+
return (ModalManager.#active = true);
|
|
22
|
+
}
|
|
23
|
+
static #anchor = null;
|
|
24
|
+
static anchor(options) {
|
|
25
|
+
if (ModalManager.#anchor) {
|
|
26
|
+
const anchor = document.getElementById(ModalManager.#anchor.id);
|
|
27
|
+
if (anchor)
|
|
28
|
+
return anchor;
|
|
29
|
+
}
|
|
30
|
+
const { tag = 'div', prefix = 'promise-modal', root = document.body, } = options || {};
|
|
31
|
+
const node = document.createElement(tag);
|
|
32
|
+
node.setAttribute('id', `${prefix}-${lib.getRandomString(36)}`);
|
|
33
|
+
root.appendChild(node);
|
|
34
|
+
ModalManager.#anchor = node;
|
|
35
|
+
return node;
|
|
36
|
+
}
|
|
37
|
+
static #prerenderList = [];
|
|
38
|
+
static get prerender() {
|
|
39
|
+
return ModalManager.#prerenderList;
|
|
40
|
+
}
|
|
41
|
+
static #openHandler = (modal) => ModalManager.#prerenderList.push(modal);
|
|
42
|
+
static set openHandler(handler) {
|
|
43
|
+
ModalManager.#openHandler = handler;
|
|
44
|
+
ModalManager.#prerenderList = [];
|
|
45
|
+
}
|
|
46
|
+
static get unanchored() {
|
|
47
|
+
return !ModalManager.#anchor;
|
|
48
|
+
}
|
|
49
|
+
static reset() {
|
|
50
|
+
ModalManager.#active = false;
|
|
51
|
+
ModalManager.#anchor = null;
|
|
52
|
+
ModalManager.#prerenderList = [];
|
|
53
|
+
ModalManager.#openHandler = (modal) => ModalManager.#prerenderList.push(modal);
|
|
54
|
+
}
|
|
55
|
+
static open(modal) {
|
|
56
|
+
ModalManager.#openHandler(modal);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
const alert = ({ subtype, title, subtitle, content, background, footer, dimmed, manualDestroy, closeOnBackdropClick, ForegroundComponent, BackgroundComponent, }) => {
|
|
61
|
+
return new Promise((resolve, reject) => {
|
|
62
|
+
try {
|
|
63
|
+
ModalManager.open({
|
|
64
|
+
type: 'alert',
|
|
65
|
+
subtype,
|
|
66
|
+
resolve: () => resolve(),
|
|
67
|
+
title,
|
|
68
|
+
subtitle,
|
|
69
|
+
content,
|
|
70
|
+
background,
|
|
71
|
+
footer,
|
|
72
|
+
dimmed,
|
|
73
|
+
manualDestroy,
|
|
74
|
+
closeOnBackdropClick,
|
|
75
|
+
ForegroundComponent,
|
|
76
|
+
BackgroundComponent,
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
catch (error) {
|
|
80
|
+
reject(error);
|
|
81
|
+
}
|
|
82
|
+
});
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
const confirm = ({ subtype, title, subtitle, content, background, footer, dimmed, manualDestroy, closeOnBackdropClick, ForegroundComponent, BackgroundComponent, }) => {
|
|
86
|
+
return new Promise((resolve, reject) => {
|
|
87
|
+
try {
|
|
88
|
+
ModalManager.open({
|
|
89
|
+
type: 'confirm',
|
|
90
|
+
subtype,
|
|
91
|
+
resolve: (result) => resolve(result ?? false),
|
|
92
|
+
title,
|
|
93
|
+
subtitle,
|
|
94
|
+
content,
|
|
95
|
+
background,
|
|
96
|
+
footer,
|
|
97
|
+
dimmed,
|
|
98
|
+
manualDestroy,
|
|
99
|
+
closeOnBackdropClick,
|
|
100
|
+
ForegroundComponent,
|
|
101
|
+
BackgroundComponent,
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
catch (error) {
|
|
105
|
+
reject(error);
|
|
106
|
+
}
|
|
107
|
+
});
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
const prompt = ({ defaultValue, title, subtitle, content, Input, disabled, returnOnCancel, background, footer, dimmed, manualDestroy, closeOnBackdropClick, ForegroundComponent, BackgroundComponent, }) => {
|
|
111
|
+
return new Promise((resolve, reject) => {
|
|
112
|
+
try {
|
|
113
|
+
ModalManager.open({
|
|
114
|
+
type: 'prompt',
|
|
115
|
+
resolve: (result) => resolve(result),
|
|
116
|
+
title,
|
|
117
|
+
subtitle,
|
|
118
|
+
content,
|
|
119
|
+
Input,
|
|
120
|
+
defaultValue,
|
|
121
|
+
disabled,
|
|
122
|
+
returnOnCancel,
|
|
123
|
+
background,
|
|
124
|
+
footer,
|
|
125
|
+
dimmed,
|
|
126
|
+
manualDestroy,
|
|
127
|
+
closeOnBackdropClick,
|
|
128
|
+
ForegroundComponent,
|
|
129
|
+
BackgroundComponent,
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
catch (error) {
|
|
133
|
+
reject(error);
|
|
134
|
+
}
|
|
135
|
+
});
|
|
136
|
+
};
|
|
137
|
+
|
|
138
|
+
class AbstractNode {
|
|
139
|
+
id;
|
|
140
|
+
initiator;
|
|
141
|
+
title;
|
|
142
|
+
subtitle;
|
|
143
|
+
background;
|
|
144
|
+
manualDestroy;
|
|
145
|
+
closeOnBackdropClick;
|
|
146
|
+
dimmed;
|
|
147
|
+
ForegroundComponent;
|
|
148
|
+
BackgroundComponent;
|
|
149
|
+
#alive;
|
|
150
|
+
get alive() {
|
|
151
|
+
return this.#alive;
|
|
152
|
+
}
|
|
153
|
+
#visible;
|
|
154
|
+
get visible() {
|
|
155
|
+
return this.#visible;
|
|
156
|
+
}
|
|
157
|
+
#resolve;
|
|
158
|
+
#listeners = new Set();
|
|
159
|
+
constructor({ id, initiator, title, subtitle, background, dimmed = true, manualDestroy = false, closeOnBackdropClick = true, resolve, ForegroundComponent, BackgroundComponent, }) {
|
|
160
|
+
this.id = id;
|
|
161
|
+
this.initiator = initiator;
|
|
162
|
+
this.title = title;
|
|
163
|
+
this.subtitle = subtitle;
|
|
164
|
+
this.background = background;
|
|
165
|
+
this.dimmed = dimmed;
|
|
166
|
+
this.manualDestroy = manualDestroy;
|
|
167
|
+
this.closeOnBackdropClick = closeOnBackdropClick;
|
|
168
|
+
this.ForegroundComponent = ForegroundComponent;
|
|
169
|
+
this.BackgroundComponent = BackgroundComponent;
|
|
170
|
+
this.#alive = true;
|
|
171
|
+
this.#visible = true;
|
|
172
|
+
this.#resolve = resolve;
|
|
173
|
+
}
|
|
174
|
+
subscribe(listener) {
|
|
175
|
+
this.#listeners.add(listener);
|
|
176
|
+
return () => {
|
|
177
|
+
this.#listeners.delete(listener);
|
|
178
|
+
};
|
|
179
|
+
}
|
|
180
|
+
publish() {
|
|
181
|
+
for (const listener of this.#listeners)
|
|
182
|
+
listener();
|
|
183
|
+
}
|
|
184
|
+
resolve(result) {
|
|
185
|
+
this.#resolve(result);
|
|
186
|
+
}
|
|
187
|
+
onDestroy() {
|
|
188
|
+
const needPublish = this.#alive === true;
|
|
189
|
+
this.#alive = false;
|
|
190
|
+
if (this.manualDestroy && needPublish)
|
|
191
|
+
this.publish();
|
|
192
|
+
}
|
|
193
|
+
onShow() {
|
|
194
|
+
const needPublish = this.#visible === false;
|
|
195
|
+
this.#visible = true;
|
|
196
|
+
if (needPublish)
|
|
197
|
+
this.publish();
|
|
198
|
+
}
|
|
199
|
+
onHide() {
|
|
200
|
+
const needPublish = this.#visible === true;
|
|
201
|
+
this.#visible = false;
|
|
202
|
+
if (needPublish)
|
|
203
|
+
this.publish();
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
class AlertNode extends AbstractNode {
|
|
208
|
+
type;
|
|
209
|
+
subtype;
|
|
210
|
+
content;
|
|
211
|
+
footer;
|
|
212
|
+
constructor({ id, initiator, type, subtype, title, subtitle, content, footer, background, dimmed, manualDestroy, closeOnBackdropClick, resolve, ForegroundComponent, BackgroundComponent, }) {
|
|
213
|
+
super({
|
|
214
|
+
id,
|
|
215
|
+
initiator,
|
|
216
|
+
title,
|
|
217
|
+
subtitle,
|
|
218
|
+
background,
|
|
219
|
+
dimmed,
|
|
220
|
+
manualDestroy,
|
|
221
|
+
closeOnBackdropClick,
|
|
222
|
+
resolve,
|
|
223
|
+
ForegroundComponent,
|
|
224
|
+
BackgroundComponent,
|
|
225
|
+
});
|
|
226
|
+
this.type = type;
|
|
227
|
+
this.subtype = subtype;
|
|
228
|
+
this.content = content;
|
|
229
|
+
this.footer = footer;
|
|
230
|
+
}
|
|
231
|
+
onClose() {
|
|
232
|
+
this.resolve(null);
|
|
233
|
+
}
|
|
234
|
+
onConfirm() {
|
|
235
|
+
this.resolve(null);
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
class ConfirmNode extends AbstractNode {
|
|
240
|
+
type;
|
|
241
|
+
subtype;
|
|
242
|
+
content;
|
|
243
|
+
footer;
|
|
244
|
+
constructor({ id, initiator, type, subtype, title, subtitle, content, footer, background, dimmed, manualDestroy, closeOnBackdropClick, resolve, ForegroundComponent, BackgroundComponent, }) {
|
|
245
|
+
super({
|
|
246
|
+
id,
|
|
247
|
+
initiator,
|
|
248
|
+
title,
|
|
249
|
+
subtitle,
|
|
250
|
+
background,
|
|
251
|
+
dimmed,
|
|
252
|
+
manualDestroy,
|
|
253
|
+
closeOnBackdropClick,
|
|
254
|
+
resolve,
|
|
255
|
+
ForegroundComponent,
|
|
256
|
+
BackgroundComponent,
|
|
257
|
+
});
|
|
258
|
+
this.type = type;
|
|
259
|
+
this.subtype = subtype;
|
|
260
|
+
this.content = content;
|
|
261
|
+
this.footer = footer;
|
|
262
|
+
}
|
|
263
|
+
onClose() {
|
|
264
|
+
this.resolve(false);
|
|
265
|
+
}
|
|
266
|
+
onConfirm() {
|
|
267
|
+
this.resolve(true);
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
class PromptNode extends AbstractNode {
|
|
272
|
+
type;
|
|
273
|
+
content;
|
|
274
|
+
defaultValue;
|
|
275
|
+
Input;
|
|
276
|
+
disabled;
|
|
277
|
+
returnOnCancel;
|
|
278
|
+
footer;
|
|
279
|
+
#value;
|
|
280
|
+
constructor({ id, initiator, type, title, subtitle, content, defaultValue, Input, disabled, returnOnCancel, footer, background, dimmed, manualDestroy, closeOnBackdropClick, resolve, ForegroundComponent, BackgroundComponent, }) {
|
|
281
|
+
super({
|
|
282
|
+
id,
|
|
283
|
+
initiator,
|
|
284
|
+
title,
|
|
285
|
+
subtitle,
|
|
286
|
+
background,
|
|
287
|
+
dimmed,
|
|
288
|
+
manualDestroy,
|
|
289
|
+
closeOnBackdropClick,
|
|
290
|
+
resolve,
|
|
291
|
+
ForegroundComponent,
|
|
292
|
+
BackgroundComponent,
|
|
293
|
+
});
|
|
294
|
+
this.type = type;
|
|
295
|
+
this.content = content;
|
|
296
|
+
this.Input = Input;
|
|
297
|
+
this.defaultValue = defaultValue;
|
|
298
|
+
this.#value = defaultValue;
|
|
299
|
+
this.disabled = disabled;
|
|
300
|
+
this.returnOnCancel = returnOnCancel;
|
|
301
|
+
this.footer = footer;
|
|
302
|
+
}
|
|
303
|
+
onChange(value) {
|
|
304
|
+
this.#value = value;
|
|
305
|
+
}
|
|
306
|
+
onConfirm() {
|
|
307
|
+
this.resolve(this.#value ?? null);
|
|
308
|
+
}
|
|
309
|
+
onClose() {
|
|
310
|
+
if (this.returnOnCancel)
|
|
311
|
+
this.resolve(this.#value ?? null);
|
|
312
|
+
else
|
|
313
|
+
this.resolve(null);
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
const nodeFactory = (modal) => {
|
|
318
|
+
switch (modal.type) {
|
|
319
|
+
case 'alert':
|
|
320
|
+
return new AlertNode(modal);
|
|
321
|
+
case 'confirm':
|
|
322
|
+
return new ConfirmNode(modal);
|
|
323
|
+
case 'prompt':
|
|
324
|
+
return new PromptNode(modal);
|
|
325
|
+
}
|
|
326
|
+
throw new Error(`Unknown modal: ${modal.type}`, { modal });
|
|
327
|
+
};
|
|
328
|
+
|
|
329
|
+
const DEFAULT_ANIMATION_DURATION = '300ms';
|
|
330
|
+
const DEFAULT_BACKDROP_COLOR = 'rgba(0, 0, 0, 0.5)';
|
|
331
|
+
|
|
332
|
+
const fallback = css.css `
|
|
333
|
+
margin: unset;
|
|
334
|
+
`;
|
|
335
|
+
const frame = css.css `
|
|
336
|
+
display: flex;
|
|
337
|
+
flex-direction: column;
|
|
338
|
+
justify-content: center;
|
|
339
|
+
align-items: center;
|
|
340
|
+
background-color: white;
|
|
341
|
+
padding: 20px 80px;
|
|
342
|
+
gap: 10px;
|
|
343
|
+
border: 1px solid black;
|
|
344
|
+
`;
|
|
345
|
+
|
|
346
|
+
const FallbackTitle = ({ children }) => {
|
|
347
|
+
return jsxRuntime.jsx("h2", { className: fallback, children: children });
|
|
348
|
+
};
|
|
349
|
+
|
|
350
|
+
const FallbackSubtitle = ({ children }) => {
|
|
351
|
+
return jsxRuntime.jsx("h3", { className: fallback, children: children });
|
|
352
|
+
};
|
|
353
|
+
|
|
354
|
+
const FallbackContent = ({ children }) => {
|
|
355
|
+
return jsxRuntime.jsx("div", { className: fallback, children: children });
|
|
356
|
+
};
|
|
357
|
+
|
|
358
|
+
const FallbackFooter = ({ confirmLabel, hideConfirm = false, cancelLabel, hideCancel = false, disabled, onConfirm, onCancel, }) => {
|
|
359
|
+
return (jsxRuntime.jsxs("div", { children: [!hideConfirm && (jsxRuntime.jsx("button", { onClick: onConfirm, disabled: disabled, children: confirmLabel || 'Confirm' })), !hideCancel && typeof onCancel === 'function' && (jsxRuntime.jsx("button", { onClick: onCancel, children: cancelLabel || 'Cancel' }))] }));
|
|
360
|
+
};
|
|
361
|
+
|
|
362
|
+
const ModalManagerContext = react.createContext({});
|
|
363
|
+
|
|
364
|
+
const useModalManagerContext = () => react.useContext(ModalManagerContext);
|
|
365
|
+
const useModal = (id) => {
|
|
366
|
+
const { getModal } = useModalManagerContext();
|
|
367
|
+
return react.useMemo(() => getModal(id), [id, getModal]);
|
|
368
|
+
};
|
|
369
|
+
|
|
370
|
+
const defaultValidate = (modal) => modal?.visible;
|
|
371
|
+
const useActiveModalCount = (validate = defaultValidate, refreshKey = 0) => {
|
|
372
|
+
const { modalIds, getModalNode } = useModalManagerContext();
|
|
373
|
+
return react.useMemo(() => {
|
|
374
|
+
let count = 0;
|
|
375
|
+
for (const id of modalIds) {
|
|
376
|
+
if (validate(getModalNode(id)))
|
|
377
|
+
count++;
|
|
378
|
+
}
|
|
379
|
+
return count;
|
|
380
|
+
}, [getModalNode, modalIds, refreshKey]);
|
|
381
|
+
};
|
|
382
|
+
|
|
383
|
+
const MAX_MODAL_COUNT = 5;
|
|
384
|
+
const MAX_MODAL_LEVEL = 3;
|
|
385
|
+
const FallbackForegroundFrame = react.forwardRef(({ id, onChangeOrder, children }, ref) => {
|
|
386
|
+
const activeCount = useActiveModalCount();
|
|
387
|
+
const [level, offset] = react.useMemo(() => {
|
|
388
|
+
const stacked = activeCount > 1;
|
|
389
|
+
const level = stacked
|
|
390
|
+
? (Math.floor(id / MAX_MODAL_COUNT) % MAX_MODAL_LEVEL) * 100
|
|
391
|
+
: 0;
|
|
392
|
+
const offset = stacked ? (id % MAX_MODAL_COUNT) * 35 : 0;
|
|
393
|
+
return [level, offset];
|
|
394
|
+
}, [activeCount, id]);
|
|
395
|
+
return (jsxRuntime.jsx("div", { ref: ref, className: frame, onClick: onChangeOrder, style: {
|
|
396
|
+
marginBottom: `calc(25vh + ${level}px)`,
|
|
397
|
+
marginLeft: `${level}px`,
|
|
398
|
+
transform: `translate(${offset}px, ${offset}px)`,
|
|
399
|
+
}, children: children }));
|
|
400
|
+
});
|
|
401
|
+
|
|
402
|
+
const ConfigurationContext = react.createContext({});
|
|
403
|
+
|
|
404
|
+
const ConfigurationContextProvider = react.memo(({ ForegroundComponent, BackgroundComponent, TitleComponent, SubtitleComponent, ContentComponent, FooterComponent, options, children, }) => {
|
|
405
|
+
const value = react.useMemo(() => ({
|
|
406
|
+
BackgroundComponent,
|
|
407
|
+
ForegroundComponent: ForegroundComponent || FallbackForegroundFrame,
|
|
408
|
+
TitleComponent: TitleComponent || FallbackTitle,
|
|
409
|
+
SubtitleComponent: SubtitleComponent || FallbackSubtitle,
|
|
410
|
+
ContentComponent: react.memo(ContentComponent || FallbackContent),
|
|
411
|
+
FooterComponent: react.memo(FooterComponent || FallbackFooter),
|
|
412
|
+
options: {
|
|
413
|
+
duration: DEFAULT_ANIMATION_DURATION,
|
|
414
|
+
backdrop: DEFAULT_BACKDROP_COLOR,
|
|
415
|
+
closeOnBackdropClick: true,
|
|
416
|
+
manualDestroy: false,
|
|
417
|
+
...options,
|
|
418
|
+
},
|
|
419
|
+
}), [
|
|
420
|
+
ForegroundComponent,
|
|
421
|
+
BackgroundComponent,
|
|
422
|
+
ContentComponent,
|
|
423
|
+
FooterComponent,
|
|
424
|
+
SubtitleComponent,
|
|
425
|
+
TitleComponent,
|
|
426
|
+
options,
|
|
427
|
+
]);
|
|
428
|
+
return (jsxRuntime.jsx(ConfigurationContext.Provider, { value: value, children: children }));
|
|
429
|
+
});
|
|
430
|
+
|
|
431
|
+
const useConfigurationContext = () => react.useContext(ConfigurationContext);
|
|
432
|
+
const useConfigurationOptions = () => {
|
|
433
|
+
const context = react.useContext(ConfigurationContext);
|
|
434
|
+
return context.options;
|
|
435
|
+
};
|
|
436
|
+
const useConfigurationDuration = () => {
|
|
437
|
+
const context = useConfigurationOptions();
|
|
438
|
+
return {
|
|
439
|
+
duration: context.duration,
|
|
440
|
+
milliseconds: convert.convertMsFromDuration(context.duration),
|
|
441
|
+
};
|
|
442
|
+
};
|
|
443
|
+
const useConfigurationBackdrop = () => {
|
|
444
|
+
const context = useConfigurationOptions();
|
|
445
|
+
return context.backdrop;
|
|
446
|
+
};
|
|
447
|
+
|
|
448
|
+
const ModalManagerContextProvider = react.memo(({ usePathname, children, }) => {
|
|
449
|
+
const modalDictionary = react.useRef(new Map());
|
|
450
|
+
const [modalIds, setModalIds] = react.useState([]);
|
|
451
|
+
const modalIdsRef = hook.useReference(modalIds);
|
|
452
|
+
const { pathname } = usePathname();
|
|
453
|
+
const initiator = react.useRef(pathname);
|
|
454
|
+
const modalIdSequence = react.useRef(0);
|
|
455
|
+
const options = useConfigurationOptions();
|
|
456
|
+
const duration = react.useMemo(() => convert.convertMsFromDuration(options.duration), [options]);
|
|
457
|
+
hook.useOnMountLayout(() => {
|
|
458
|
+
const { manualDestroy, closeOnBackdropClick } = options;
|
|
459
|
+
for (const data of ModalManager.prerender) {
|
|
460
|
+
const modal = nodeFactory({
|
|
461
|
+
...data,
|
|
462
|
+
id: modalIdSequence.current++,
|
|
463
|
+
initiator: initiator.current,
|
|
464
|
+
manualDestroy: data.manualDestroy !== undefined
|
|
465
|
+
? data.manualDestroy
|
|
466
|
+
: manualDestroy,
|
|
467
|
+
closeOnBackdropClick: data.closeOnBackdropClick !== undefined
|
|
468
|
+
? data.closeOnBackdropClick
|
|
469
|
+
: closeOnBackdropClick,
|
|
470
|
+
});
|
|
471
|
+
modalDictionary.current.set(modal.id, modal);
|
|
472
|
+
setModalIds((ids) => [...ids, modal.id]);
|
|
473
|
+
}
|
|
474
|
+
ModalManager.openHandler = (data) => {
|
|
475
|
+
const modal = nodeFactory({
|
|
476
|
+
...data,
|
|
477
|
+
id: modalIdSequence.current++,
|
|
478
|
+
initiator: initiator.current,
|
|
479
|
+
manualDestroy: data.manualDestroy !== undefined
|
|
480
|
+
? data.manualDestroy
|
|
481
|
+
: manualDestroy,
|
|
482
|
+
closeOnBackdropClick: data.closeOnBackdropClick !== undefined
|
|
483
|
+
? data.closeOnBackdropClick
|
|
484
|
+
: closeOnBackdropClick,
|
|
485
|
+
});
|
|
486
|
+
modalDictionary.current.set(modal.id, modal);
|
|
487
|
+
setModalIds((ids) => {
|
|
488
|
+
const aliveIds = [];
|
|
489
|
+
for (let index = 0; index < ids.length; index++) {
|
|
490
|
+
const id = ids[index];
|
|
491
|
+
const destroyed = !modalDictionary.current.get(id)?.alive;
|
|
492
|
+
if (destroyed)
|
|
493
|
+
modalDictionary.current.delete(id);
|
|
494
|
+
else
|
|
495
|
+
aliveIds.push(id);
|
|
496
|
+
}
|
|
497
|
+
return [...aliveIds, modal.id];
|
|
498
|
+
});
|
|
499
|
+
};
|
|
500
|
+
return () => {
|
|
501
|
+
ModalManager.reset();
|
|
502
|
+
};
|
|
503
|
+
});
|
|
504
|
+
react.useLayoutEffect(() => {
|
|
505
|
+
for (const id of modalIdsRef.current) {
|
|
506
|
+
const modal = modalDictionary.current.get(id);
|
|
507
|
+
if (!modal?.alive)
|
|
508
|
+
continue;
|
|
509
|
+
if (modal.initiator === pathname)
|
|
510
|
+
modal.onShow();
|
|
511
|
+
else
|
|
512
|
+
modal.onHide();
|
|
513
|
+
}
|
|
514
|
+
initiator.current = pathname;
|
|
515
|
+
}, [pathname]);
|
|
516
|
+
const getModalNode = react.useCallback((modalId) => {
|
|
517
|
+
return modalDictionary.current.get(modalId);
|
|
518
|
+
}, []);
|
|
519
|
+
const onDestroy = react.useCallback((modalId) => {
|
|
520
|
+
const modal = modalDictionary.current.get(modalId);
|
|
521
|
+
if (!modal)
|
|
522
|
+
return;
|
|
523
|
+
modal.onDestroy();
|
|
524
|
+
updaterRef.current?.();
|
|
525
|
+
}, []);
|
|
526
|
+
const updaterRef = react.useRef(undefined);
|
|
527
|
+
const hideModal = react.useCallback((modalId) => {
|
|
528
|
+
const modal = modalDictionary.current.get(modalId);
|
|
529
|
+
if (!modal)
|
|
530
|
+
return;
|
|
531
|
+
modal.onHide();
|
|
532
|
+
updaterRef.current?.();
|
|
533
|
+
if (!modal.manualDestroy)
|
|
534
|
+
setTimeout(() => {
|
|
535
|
+
modal.onDestroy();
|
|
536
|
+
}, duration);
|
|
537
|
+
}, [duration]);
|
|
538
|
+
const onChange = react.useCallback((modalId, value) => {
|
|
539
|
+
const modal = modalDictionary.current.get(modalId);
|
|
540
|
+
if (!modal)
|
|
541
|
+
return;
|
|
542
|
+
if (modal.type === 'prompt')
|
|
543
|
+
modal.onChange(value);
|
|
544
|
+
}, []);
|
|
545
|
+
const onConfirm = react.useCallback((modalId) => {
|
|
546
|
+
const modal = modalDictionary.current.get(modalId);
|
|
547
|
+
if (!modal)
|
|
548
|
+
return;
|
|
549
|
+
modal.onConfirm();
|
|
550
|
+
hideModal(modalId);
|
|
551
|
+
}, [hideModal]);
|
|
552
|
+
const onClose = react.useCallback((modalId) => {
|
|
553
|
+
const modal = modalDictionary.current.get(modalId);
|
|
554
|
+
if (!modal)
|
|
555
|
+
return;
|
|
556
|
+
modal.onClose();
|
|
557
|
+
hideModal(modalId);
|
|
558
|
+
}, [hideModal]);
|
|
559
|
+
const getModal = react.useCallback((modalId) => ({
|
|
560
|
+
modal: getModalNode(modalId),
|
|
561
|
+
onConfirm: () => onConfirm(modalId),
|
|
562
|
+
onClose: () => onClose(modalId),
|
|
563
|
+
onChange: (value) => onChange(modalId, value),
|
|
564
|
+
onDestroy: () => onDestroy(modalId),
|
|
565
|
+
}), [getModalNode, onConfirm, onClose, onChange, onDestroy]);
|
|
566
|
+
const value = react.useMemo(() => {
|
|
567
|
+
return {
|
|
568
|
+
modalIds,
|
|
569
|
+
getModalNode,
|
|
570
|
+
onChange,
|
|
571
|
+
onConfirm,
|
|
572
|
+
onClose,
|
|
573
|
+
onDestroy,
|
|
574
|
+
getModal,
|
|
575
|
+
setUpdater: (updater) => {
|
|
576
|
+
updaterRef.current = updater;
|
|
577
|
+
},
|
|
578
|
+
};
|
|
579
|
+
}, [
|
|
580
|
+
modalIds,
|
|
581
|
+
getModal,
|
|
582
|
+
getModalNode,
|
|
583
|
+
onChange,
|
|
584
|
+
onConfirm,
|
|
585
|
+
onClose,
|
|
586
|
+
onDestroy,
|
|
587
|
+
]);
|
|
588
|
+
return (jsxRuntime.jsx(ModalManagerContext.Provider, { value: value, children: children }));
|
|
589
|
+
});
|
|
590
|
+
|
|
591
|
+
const UserDefinedContext = react.createContext({});
|
|
592
|
+
|
|
593
|
+
const UserDefinedContextProvider = ({ context, children, }) => {
|
|
594
|
+
const contextValue = react.useMemo(() => ({ context: context || {} }), [context]);
|
|
595
|
+
return (jsxRuntime.jsx(UserDefinedContext.Provider, { value: contextValue, children: children }));
|
|
596
|
+
};
|
|
597
|
+
|
|
598
|
+
const useUserDefinedContext = () => {
|
|
599
|
+
return react.useContext(UserDefinedContext);
|
|
600
|
+
};
|
|
601
|
+
|
|
602
|
+
const usePathname = () => {
|
|
603
|
+
const [pathname, setPathname] = react.useState(window.location.pathname);
|
|
604
|
+
react.useLayoutEffect(() => {
|
|
605
|
+
let requestId;
|
|
606
|
+
const checkPathname = () => {
|
|
607
|
+
if (requestId)
|
|
608
|
+
cancelAnimationFrame(requestId);
|
|
609
|
+
if (pathname !== window.location.pathname) {
|
|
610
|
+
setPathname(window.location.pathname);
|
|
611
|
+
}
|
|
612
|
+
else {
|
|
613
|
+
requestId = requestAnimationFrame(checkPathname);
|
|
614
|
+
}
|
|
615
|
+
};
|
|
616
|
+
requestId = requestAnimationFrame(checkPathname);
|
|
617
|
+
return () => {
|
|
618
|
+
if (requestId)
|
|
619
|
+
cancelAnimationFrame(requestId);
|
|
620
|
+
};
|
|
621
|
+
}, [pathname]);
|
|
622
|
+
return { pathname };
|
|
623
|
+
};
|
|
624
|
+
|
|
625
|
+
const background = css.css `
|
|
626
|
+
display: none;
|
|
627
|
+
position: fixed;
|
|
628
|
+
inset: 0;
|
|
629
|
+
z-index: -999;
|
|
630
|
+
pointer-events: none;
|
|
631
|
+
> * {
|
|
632
|
+
pointer-events: none;
|
|
633
|
+
}
|
|
634
|
+
`;
|
|
635
|
+
const active$1 = css.css `
|
|
636
|
+
pointer-events: all;
|
|
637
|
+
`;
|
|
638
|
+
const visible$1 = css.css `
|
|
639
|
+
display: flex;
|
|
640
|
+
align-items: center;
|
|
641
|
+
justify-content: center;
|
|
642
|
+
`;
|
|
643
|
+
|
|
644
|
+
const BackgroundFrame = ({ modalId, onChangeOrder, }) => {
|
|
645
|
+
const { BackgroundComponent } = useConfigurationContext();
|
|
646
|
+
const { context: userDefinedContext } = useUserDefinedContext();
|
|
647
|
+
const { modal, onClose, onChange, onConfirm, onDestroy } = useModal(modalId);
|
|
648
|
+
const handleClose = react.useCallback((event) => {
|
|
649
|
+
if (modal && modal.closeOnBackdropClick && modal.visible)
|
|
650
|
+
onClose();
|
|
651
|
+
event.stopPropagation();
|
|
652
|
+
}, [modal, onClose]);
|
|
653
|
+
const Background = react.useMemo(() => modal?.BackgroundComponent || BackgroundComponent, [BackgroundComponent, modal]);
|
|
654
|
+
if (!modal)
|
|
655
|
+
return null;
|
|
656
|
+
return (jsxRuntime.jsx("div", { className: css.cx(background, {
|
|
657
|
+
[visible$1]: modal.manualDestroy ? modal.alive : modal.visible,
|
|
658
|
+
[active$1]: modal.closeOnBackdropClick && modal.visible,
|
|
659
|
+
}), onClick: handleClose, children: Background && (jsxRuntime.jsx(Background, { id: modal.id, type: modal.type, alive: modal.alive, visible: modal.visible, initiator: modal.initiator, manualDestroy: modal.manualDestroy, closeOnBackdropClick: modal.closeOnBackdropClick, background: modal.background, onChange: onChange, onConfirm: onConfirm, onClose: onClose, onDestroy: onDestroy, onChangeOrder: onChangeOrder, context: userDefinedContext })) }));
|
|
660
|
+
};
|
|
661
|
+
|
|
662
|
+
const foreground = css.css `
|
|
663
|
+
pointer-events: none;
|
|
664
|
+
display: none;
|
|
665
|
+
position: fixed;
|
|
666
|
+
inset: 0;
|
|
667
|
+
z-index: 1;
|
|
668
|
+
`;
|
|
669
|
+
const active = css.css `
|
|
670
|
+
> * {
|
|
671
|
+
pointer-events: all;
|
|
672
|
+
}
|
|
673
|
+
`;
|
|
674
|
+
const visible = css.css `
|
|
675
|
+
display: flex !important;
|
|
676
|
+
justify-content: center;
|
|
677
|
+
align-items: center;
|
|
678
|
+
`;
|
|
679
|
+
|
|
680
|
+
const AlertInner = react.memo(({ modal, handlers }) => {
|
|
681
|
+
const { title, subtitle, content, footer } = react.useMemo(() => modal, [modal]);
|
|
682
|
+
const { context: userDefinedContext } = useUserDefinedContext();
|
|
683
|
+
const { onConfirm } = react.useMemo(() => handlers, [handlers]);
|
|
684
|
+
const handleConfirm = hook.useHandle(onConfirm);
|
|
685
|
+
const { TitleComponent, SubtitleComponent, ContentComponent, FooterComponent, } = useConfigurationContext();
|
|
686
|
+
return (jsxRuntime.jsxs(react.Fragment, { children: [title &&
|
|
687
|
+
(filter.isString(title) ? (jsxRuntime.jsx(TitleComponent, { context: userDefinedContext, children: title })) : (title)), subtitle &&
|
|
688
|
+
(filter.isString(subtitle) ? (jsxRuntime.jsx(SubtitleComponent, { context: userDefinedContext, children: subtitle })) : (subtitle)), content &&
|
|
689
|
+
(filter.isString(content) ? (jsxRuntime.jsx(ContentComponent, { context: userDefinedContext, children: content })) : (render.renderComponent(content, {
|
|
690
|
+
onConfirm: handleConfirm,
|
|
691
|
+
}))), footer !== false &&
|
|
692
|
+
(typeof footer === 'function' ? (footer({
|
|
693
|
+
onConfirm: handleConfirm,
|
|
694
|
+
context: userDefinedContext,
|
|
695
|
+
})) : (jsxRuntime.jsx(FooterComponent, { onConfirm: handleConfirm, confirmLabel: footer?.confirm, hideConfirm: footer?.hideConfirm, context: userDefinedContext })))] }));
|
|
696
|
+
});
|
|
697
|
+
|
|
698
|
+
const ConfirmInner = react.memo(({ modal, handlers }) => {
|
|
699
|
+
const { title, subtitle, content, footer } = react.useMemo(() => modal, [modal]);
|
|
700
|
+
const { context: userDefinedContext } = useUserDefinedContext();
|
|
701
|
+
const { onConfirm, onClose } = react.useMemo(() => handlers, [handlers]);
|
|
702
|
+
const handleConfirm = hook.useHandle(onConfirm);
|
|
703
|
+
const handleClose = hook.useHandle(onClose);
|
|
704
|
+
const { TitleComponent, SubtitleComponent, ContentComponent, FooterComponent, } = useConfigurationContext();
|
|
705
|
+
return (jsxRuntime.jsxs(react.Fragment, { children: [title &&
|
|
706
|
+
(filter.isString(title) ? (jsxRuntime.jsx(TitleComponent, { context: userDefinedContext, children: title })) : (title)), subtitle &&
|
|
707
|
+
(filter.isString(subtitle) ? (jsxRuntime.jsx(SubtitleComponent, { context: userDefinedContext, children: subtitle })) : (subtitle)), content &&
|
|
708
|
+
(filter.isString(content) ? (jsxRuntime.jsx(ContentComponent, { context: userDefinedContext, children: content })) : (render.renderComponent(content, {
|
|
709
|
+
onConfirm: handleConfirm,
|
|
710
|
+
onCancel: handleClose,
|
|
711
|
+
context: userDefinedContext,
|
|
712
|
+
}))), footer !== false &&
|
|
713
|
+
(typeof footer === 'function' ? (footer({
|
|
714
|
+
onConfirm: handleConfirm,
|
|
715
|
+
onCancel: handleClose,
|
|
716
|
+
context: userDefinedContext,
|
|
717
|
+
})) : (jsxRuntime.jsx(FooterComponent, { onConfirm: handleConfirm, onCancel: handleClose, confirmLabel: footer?.confirm, cancelLabel: footer?.cancel, hideConfirm: footer?.hideConfirm, hideCancel: footer?.hideCancel, context: userDefinedContext })))] }));
|
|
718
|
+
});
|
|
719
|
+
|
|
720
|
+
const PromptInner = react.memo(({ modal, handlers }) => {
|
|
721
|
+
const { Input, defaultValue, disabled: checkDisabled, title, subtitle, content, footer, } = react.useMemo(() => ({
|
|
722
|
+
...modal,
|
|
723
|
+
Input: react.memo(hoc.withErrorBoundary(modal.Input)),
|
|
724
|
+
}), [modal]);
|
|
725
|
+
const { context: userDefinedContext } = useUserDefinedContext();
|
|
726
|
+
const [value, setValue] = react.useState(defaultValue);
|
|
727
|
+
const { onChange, onClose, onConfirm } = react.useMemo(() => handlers, [handlers]);
|
|
728
|
+
const handleClose = hook.useHandle(onClose);
|
|
729
|
+
const handleChange = hook.useHandle((inputValue) => {
|
|
730
|
+
const input = filter.isFunction(inputValue) ? inputValue(value) : inputValue;
|
|
731
|
+
setValue(input);
|
|
732
|
+
onChange(input);
|
|
733
|
+
});
|
|
734
|
+
const handleConfirm = react.useCallback(() => {
|
|
735
|
+
requestAnimationFrame(onConfirm);
|
|
736
|
+
}, [onConfirm]);
|
|
737
|
+
const disabled = react.useMemo(() => (value ? !!checkDisabled?.(value) : false), [checkDisabled, value]);
|
|
738
|
+
const { TitleComponent, SubtitleComponent, ContentComponent, FooterComponent, } = useConfigurationContext();
|
|
739
|
+
return (jsxRuntime.jsxs(react.Fragment, { children: [title &&
|
|
740
|
+
(filter.isString(title) ? (jsxRuntime.jsx(TitleComponent, { context: userDefinedContext, children: title })) : (title)), subtitle &&
|
|
741
|
+
(filter.isString(subtitle) ? (jsxRuntime.jsx(SubtitleComponent, { context: userDefinedContext, children: subtitle })) : (subtitle)), content &&
|
|
742
|
+
(filter.isString(content) ? (jsxRuntime.jsx(ContentComponent, { context: userDefinedContext, children: content })) : (render.renderComponent(content, {
|
|
743
|
+
onConfirm: handleConfirm,
|
|
744
|
+
onCancel: handleClose,
|
|
745
|
+
context: userDefinedContext,
|
|
746
|
+
}))), Input && (jsxRuntime.jsx(Input, { defaultValue: defaultValue, value: value, onChange: handleChange, onConfirm: handleConfirm, onCancel: handleClose, context: userDefinedContext })), footer !== false &&
|
|
747
|
+
(typeof footer === 'function' ? (footer({
|
|
748
|
+
value,
|
|
749
|
+
disabled,
|
|
750
|
+
onChange: handleChange,
|
|
751
|
+
onConfirm: handleConfirm,
|
|
752
|
+
onCancel: handleClose,
|
|
753
|
+
context: userDefinedContext,
|
|
754
|
+
})) : (jsxRuntime.jsx(FooterComponent, { disabled: disabled, onConfirm: handleConfirm, onCancel: handleClose, confirmLabel: footer?.confirm, cancelLabel: footer?.cancel, hideConfirm: footer?.hideConfirm, hideCancel: footer?.hideCancel, context: userDefinedContext })))] }));
|
|
755
|
+
});
|
|
756
|
+
|
|
757
|
+
const ForegroundFrame = ({ modalId, onChangeOrder, }) => {
|
|
758
|
+
const { ForegroundComponent } = useConfigurationContext();
|
|
759
|
+
const { context: userDefinedContext } = useUserDefinedContext();
|
|
760
|
+
const { modal, onChange, onConfirm, onClose, onDestroy } = useModal(modalId);
|
|
761
|
+
const Foreground = react.useMemo(() => modal?.ForegroundComponent || ForegroundComponent, [ForegroundComponent, modal]);
|
|
762
|
+
if (!modal)
|
|
763
|
+
return null;
|
|
764
|
+
return (jsxRuntime.jsx("div", { className: css.cx(foreground, {
|
|
765
|
+
[visible]: modal.manualDestroy ? modal.alive : modal.visible,
|
|
766
|
+
[active]: modal.visible,
|
|
767
|
+
}), children: jsxRuntime.jsxs(Foreground, { id: modal.id, type: modal.type, alive: modal.alive, visible: modal.visible, initiator: modal.initiator, manualDestroy: modal.manualDestroy, closeOnBackdropClick: modal.closeOnBackdropClick, background: modal.background, onChange: onChange, onConfirm: onConfirm, onClose: onClose, onDestroy: onDestroy, onChangeOrder: onChangeOrder, context: userDefinedContext, children: [modal.type === 'alert' && (jsxRuntime.jsx(AlertInner, { modal: modal, handlers: { onConfirm } })), modal.type === 'confirm' && (jsxRuntime.jsx(ConfirmInner, { modal: modal, handlers: { onConfirm, onClose } })), modal.type === 'prompt' && (jsxRuntime.jsx(PromptInner, { modal: modal, handlers: { onChange, onConfirm, onClose } }))] }) }));
|
|
768
|
+
};
|
|
769
|
+
|
|
770
|
+
const useSubscribeModal = (modal) => {
|
|
771
|
+
const [version, update] = hook.useVersion();
|
|
772
|
+
react.useEffect(() => {
|
|
773
|
+
if (!modal)
|
|
774
|
+
return;
|
|
775
|
+
const unsubscribe = modal.subscribe(update);
|
|
776
|
+
return unsubscribe;
|
|
777
|
+
}, [modal, update]);
|
|
778
|
+
return version;
|
|
779
|
+
};
|
|
780
|
+
|
|
781
|
+
const presenter = css.css `
|
|
782
|
+
position: fixed;
|
|
783
|
+
inset: 0;
|
|
784
|
+
pointer-events: none;
|
|
785
|
+
overflow: hidden;
|
|
786
|
+
`;
|
|
787
|
+
|
|
788
|
+
const { increment } = lib.counterFactory(1);
|
|
789
|
+
const Presenter = react.memo(({ modalId }) => {
|
|
790
|
+
const ref = react.useRef(null);
|
|
791
|
+
const { modal } = useModal(modalId);
|
|
792
|
+
useSubscribeModal(modal);
|
|
793
|
+
const handleChangeOrder = hook.useHandle(() => {
|
|
794
|
+
if (ref.current) {
|
|
795
|
+
ref.current.style.zIndex = `${increment()}`;
|
|
796
|
+
}
|
|
797
|
+
});
|
|
798
|
+
return (jsxRuntime.jsxs("div", { ref: ref, className: presenter, children: [jsxRuntime.jsx(BackgroundFrame, { modalId: modalId, onChangeOrder: handleChangeOrder }), jsxRuntime.jsx(ForegroundFrame, { modalId: modalId, onChangeOrder: handleChangeOrder })] }));
|
|
799
|
+
});
|
|
800
|
+
|
|
801
|
+
const anchor = css.css `
|
|
802
|
+
display: flex;
|
|
803
|
+
align-items: center;
|
|
804
|
+
justify-content: center;
|
|
805
|
+
position: fixed;
|
|
806
|
+
inset: 0;
|
|
807
|
+
pointer-events: none;
|
|
808
|
+
z-index: 1000;
|
|
809
|
+
transition: background-color ease-in-out;
|
|
810
|
+
`;
|
|
811
|
+
|
|
812
|
+
const AnchorInner = () => {
|
|
813
|
+
const [version, update] = hook.useVersion();
|
|
814
|
+
const { modalIds, setUpdater } = useModalManagerContext();
|
|
815
|
+
react.useEffect(() => {
|
|
816
|
+
setUpdater(update);
|
|
817
|
+
}, [setUpdater, update]);
|
|
818
|
+
const options = useConfigurationOptions();
|
|
819
|
+
const dimmed = useActiveModalCount(validateDimmable, version);
|
|
820
|
+
return (jsxRuntime.jsx("div", { className: anchor, style: {
|
|
821
|
+
transitionDuration: options.duration,
|
|
822
|
+
backgroundColor: dimmed ? options.backdrop : 'transparent',
|
|
823
|
+
}, children: array.map(modalIds, (id) => (jsxRuntime.jsx(Presenter, { modalId: id }, id))) }));
|
|
824
|
+
};
|
|
825
|
+
const validateDimmable = (modal) => modal?.visible && modal.dimmed;
|
|
826
|
+
const Anchor = react.memo(hoc.withErrorBoundary(AnchorInner));
|
|
827
|
+
|
|
828
|
+
const bootstrap = ({ ForegroundComponent, BackgroundComponent, TitleComponent, SubtitleComponent, ContentComponent, FooterComponent, usePathname, options, context, anchor, }) => reactDom.createPortal(jsxRuntime.jsx(UserDefinedContextProvider, { context: context, children: jsxRuntime.jsx(ConfigurationContextProvider, { ForegroundComponent: ForegroundComponent, BackgroundComponent: BackgroundComponent, TitleComponent: TitleComponent, SubtitleComponent: SubtitleComponent, ContentComponent: ContentComponent, FooterComponent: FooterComponent, options: options, children: jsxRuntime.jsx(ModalManagerContextProvider, { usePathname: usePathname, children: jsxRuntime.jsx(Anchor, {}) }) }) }), anchor);
|
|
829
|
+
|
|
830
|
+
const useInitialize = () => {
|
|
831
|
+
const permitted = react.useRef(ModalManager.activate());
|
|
832
|
+
const anchorRef = react.useRef(null);
|
|
833
|
+
const [, update] = hook.useVersion();
|
|
834
|
+
const handleInitialize = react.useCallback((root) => {
|
|
835
|
+
if (permitted.current) {
|
|
836
|
+
anchorRef.current = ModalManager.anchor({ root });
|
|
837
|
+
update();
|
|
838
|
+
}
|
|
839
|
+
else
|
|
840
|
+
console.printError('ModalProvider is already initialized', [
|
|
841
|
+
'ModalProvider can only be initialized once.',
|
|
842
|
+
'Nesting ModalProvider will be ignored...',
|
|
843
|
+
], {
|
|
844
|
+
info: 'Something is wrong with the ModalProvider initialization...',
|
|
845
|
+
});
|
|
846
|
+
}, [update]);
|
|
847
|
+
return {
|
|
848
|
+
anchorRef,
|
|
849
|
+
handleInitialize,
|
|
850
|
+
};
|
|
851
|
+
};
|
|
852
|
+
|
|
853
|
+
const BootstrapProvider = react.forwardRef(({ usePathname: useExternalPathname, ForegroundComponent, BackgroundComponent, TitleComponent, SubtitleComponent, ContentComponent, FooterComponent, options, context, children, }, handleRef) => {
|
|
854
|
+
const usePathname$1 = react.useMemo(() => useExternalPathname || usePathname, [useExternalPathname]);
|
|
855
|
+
const { anchorRef, handleInitialize } = useInitialize();
|
|
856
|
+
react.useImperativeHandle(handleRef, () => ({
|
|
857
|
+
initialize: handleInitialize,
|
|
858
|
+
}), [handleInitialize]);
|
|
859
|
+
hook.useOnMount(() => {
|
|
860
|
+
if (handleRef === null)
|
|
861
|
+
handleInitialize();
|
|
862
|
+
return () => {
|
|
863
|
+
if (anchorRef.current)
|
|
864
|
+
anchorRef.current.remove();
|
|
865
|
+
};
|
|
866
|
+
});
|
|
867
|
+
return (jsxRuntime.jsxs(react.Fragment, { children: [children, anchorRef.current &&
|
|
868
|
+
bootstrap({
|
|
869
|
+
ForegroundComponent,
|
|
870
|
+
BackgroundComponent,
|
|
871
|
+
TitleComponent,
|
|
872
|
+
SubtitleComponent,
|
|
873
|
+
ContentComponent,
|
|
874
|
+
FooterComponent,
|
|
875
|
+
usePathname: usePathname$1,
|
|
876
|
+
options,
|
|
877
|
+
context,
|
|
878
|
+
anchor: anchorRef.current,
|
|
879
|
+
})] }));
|
|
880
|
+
});
|
|
881
|
+
|
|
882
|
+
const useBootstrap = ({ usePathname: useExternalPathname, ForegroundComponent, BackgroundComponent, TitleComponent, SubtitleComponent, ContentComponent, FooterComponent, options, context, mode = 'auto', } = {}) => {
|
|
883
|
+
const usePathname$1 = react.useMemo(() => useExternalPathname || usePathname, [useExternalPathname]);
|
|
884
|
+
const { anchorRef, handleInitialize } = useInitialize();
|
|
885
|
+
hook.useOnMount(() => {
|
|
886
|
+
if (mode === 'auto')
|
|
887
|
+
handleInitialize();
|
|
888
|
+
return () => {
|
|
889
|
+
if (anchorRef.current)
|
|
890
|
+
anchorRef.current.remove();
|
|
891
|
+
};
|
|
892
|
+
});
|
|
893
|
+
const initialize = react.useCallback((element) => {
|
|
894
|
+
if (mode === 'manual')
|
|
895
|
+
handleInitialize(element);
|
|
896
|
+
}, [mode, handleInitialize]);
|
|
897
|
+
const portal = anchorRef.current &&
|
|
898
|
+
bootstrap({
|
|
899
|
+
usePathname: usePathname$1,
|
|
900
|
+
ForegroundComponent,
|
|
901
|
+
BackgroundComponent,
|
|
902
|
+
TitleComponent,
|
|
903
|
+
SubtitleComponent,
|
|
904
|
+
ContentComponent,
|
|
905
|
+
FooterComponent,
|
|
906
|
+
options,
|
|
907
|
+
context,
|
|
908
|
+
anchor: anchorRef.current,
|
|
909
|
+
});
|
|
910
|
+
return { portal, initialize };
|
|
911
|
+
};
|
|
912
|
+
|
|
913
|
+
const useDestroyAfter = (modalId, duration) => {
|
|
914
|
+
const { modal, onDestroy } = useModal(modalId);
|
|
915
|
+
const tick = useSubscribeModal(modal);
|
|
916
|
+
const reference = react.useRef({
|
|
917
|
+
modal,
|
|
918
|
+
onDestroy,
|
|
919
|
+
milliseconds: filter.isString(duration)
|
|
920
|
+
? convert.convertMsFromDuration(duration)
|
|
921
|
+
: duration,
|
|
922
|
+
});
|
|
923
|
+
react.useEffect(() => {
|
|
924
|
+
const { modal, onDestroy, milliseconds } = reference.current;
|
|
925
|
+
if (!modal || modal.visible || !modal.alive)
|
|
926
|
+
return;
|
|
927
|
+
const timer = setTimeout(() => {
|
|
928
|
+
onDestroy();
|
|
929
|
+
}, milliseconds);
|
|
930
|
+
return () => {
|
|
931
|
+
if (timer)
|
|
932
|
+
clearTimeout(timer);
|
|
933
|
+
};
|
|
934
|
+
}, [tick]);
|
|
935
|
+
};
|
|
936
|
+
|
|
937
|
+
const useModalAnimation = (visible, handler) => {
|
|
938
|
+
const handlerRef = react.useRef(handler);
|
|
939
|
+
handlerRef.current = handler;
|
|
940
|
+
react.useLayoutEffect(() => {
|
|
941
|
+
if (!handlerRef.current)
|
|
942
|
+
return;
|
|
943
|
+
let frame;
|
|
944
|
+
if (visible)
|
|
945
|
+
frame = requestAnimationFrame(() => handlerRef.current.onVisible?.());
|
|
946
|
+
else
|
|
947
|
+
frame = requestAnimationFrame(() => handlerRef.current.onHidden?.());
|
|
948
|
+
return () => {
|
|
949
|
+
if (frame)
|
|
950
|
+
cancelAnimationFrame(frame);
|
|
951
|
+
};
|
|
952
|
+
}, [visible]);
|
|
953
|
+
};
|
|
954
|
+
|
|
955
|
+
exports.ModalProvider = BootstrapProvider;
|
|
956
|
+
exports.alert = alert;
|
|
957
|
+
exports.confirm = confirm;
|
|
958
|
+
exports.prompt = prompt;
|
|
959
|
+
exports.useActiveModalCount = useActiveModalCount;
|
|
960
|
+
exports.useDestroyAfter = useDestroyAfter;
|
|
961
|
+
exports.useInitializeModal = useBootstrap;
|
|
962
|
+
exports.useModalAnimation = useModalAnimation;
|
|
963
|
+
exports.useModalBackdrop = useConfigurationBackdrop;
|
|
964
|
+
exports.useModalDuration = useConfigurationDuration;
|
|
965
|
+
exports.useModalOptions = useConfigurationOptions;
|
|
966
|
+
exports.useSubscribeModal = useSubscribeModal;
|