@lerx/promise-modal 0.8.3 → 0.8.5
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/README.md +53 -0
- package/dist/app/ModalManager.d.ts +5 -2
- package/dist/components/Anchor/style.d.ts +1 -0
- package/dist/core/handle/alert.d.ts +16 -148
- package/dist/core/handle/confirm.d.ts +18 -151
- package/dist/core/handle/index.d.ts +5 -3
- package/dist/core/handle/prompt.d.ts +23 -212
- package/dist/core/handle/static.d.ts +105 -0
- package/dist/core/handle/type.d.ts +99 -0
- package/dist/core/node/ModalNode/AbstractNode.d.ts +7 -5
- package/dist/core/node/ModalNode/AlertNode.d.ts +2 -2
- package/dist/core/node/ModalNode/ConfirmNode.d.ts +2 -2
- package/dist/core/node/ModalNode/PromptNode.d.ts +2 -2
- package/dist/helpers/closeModal.d.ts +2 -0
- package/dist/helpers/subscribeAbortSignal.d.ts +2 -0
- package/dist/hooks/useModal.d.ts +6 -0
- package/dist/index.cjs +238 -171
- package/dist/index.d.ts +1 -0
- package/dist/index.mjs +239 -173
- package/dist/providers/ConfigurationContext/ConfigurationContext.d.ts +4 -2
- package/dist/providers/ConfigurationContext/useConfigurationContext.d.ts +3 -1
- package/dist/providers/ModalManagerContext/ModalManagerContext.d.ts +0 -1
- package/dist/providers/ModalManagerContext/index.d.ts +1 -1
- package/dist/providers/ModalManagerContext/useModalManagerContext.d.ts +1 -1
- package/dist/providers/index.d.ts +1 -1
- package/dist/types/base.d.ts +2 -1
- package/dist/types/option.d.ts +2 -2
- package/package.json +2 -2
- package/dist/tsconfig.tsbuildinfo +0 -1
package/dist/index.cjs
CHANGED
|
@@ -8,16 +8,18 @@ const hash = require('@winglet/common-utils/hash');
|
|
|
8
8
|
const lib = require('@winglet/common-utils/lib');
|
|
9
9
|
const styleManager = require('@winglet/style-utils/style-manager');
|
|
10
10
|
const util = require('@winglet/style-utils/util');
|
|
11
|
+
const filter = require('@winglet/common-utils/filter');
|
|
11
12
|
const reactDom = require('react-dom');
|
|
12
13
|
const array = require('@winglet/common-utils/array');
|
|
13
14
|
const hoc = require('@winglet/react-utils/hoc');
|
|
14
|
-
const filter = require('@winglet/common-utils/filter');
|
|
15
15
|
const render = require('@winglet/react-utils/render');
|
|
16
16
|
|
|
17
17
|
class ModalManager {
|
|
18
18
|
static #anchor = null;
|
|
19
19
|
static #scope = `promise-modal-${lib.getRandomString(36)}`;
|
|
20
20
|
static #hash = hash.polynomialHash(ModalManager.#scope);
|
|
21
|
+
static #styleManager = styleManager.styleManagerFactory(ModalManager.#scope);
|
|
22
|
+
static #styleSheetDefinition = new Map();
|
|
21
23
|
static anchor(options) {
|
|
22
24
|
if (ModalManager.#anchor !== null)
|
|
23
25
|
return ModalManager.#anchor;
|
|
@@ -36,13 +38,20 @@ class ModalManager {
|
|
|
36
38
|
static get prerender() {
|
|
37
39
|
return ModalManager.#prerenderList;
|
|
38
40
|
}
|
|
39
|
-
static #openHandler = (modal) =>
|
|
41
|
+
static #openHandler = ((modal) => {
|
|
42
|
+
ModalManager.#prerenderList.push(modal);
|
|
43
|
+
});
|
|
40
44
|
static set openHandler(handler) {
|
|
41
45
|
ModalManager.#openHandler = handler;
|
|
42
46
|
ModalManager.#prerenderList = [];
|
|
43
47
|
}
|
|
44
|
-
static #
|
|
45
|
-
static
|
|
48
|
+
static #refreshHandler;
|
|
49
|
+
static set refreshHandler(handler) {
|
|
50
|
+
ModalManager.#refreshHandler = handler;
|
|
51
|
+
}
|
|
52
|
+
static refresh() {
|
|
53
|
+
ModalManager.#refreshHandler?.();
|
|
54
|
+
}
|
|
46
55
|
static defineStyleSheet(styleId, css) {
|
|
47
56
|
ModalManager.#styleSheetDefinition.set(styleId, util.compressCss(css));
|
|
48
57
|
}
|
|
@@ -56,95 +65,113 @@ class ModalManager {
|
|
|
56
65
|
static reset() {
|
|
57
66
|
ModalManager.#anchor = null;
|
|
58
67
|
ModalManager.#prerenderList = [];
|
|
59
|
-
ModalManager.#openHandler = (modal) =>
|
|
68
|
+
ModalManager.#openHandler = ((modal) => {
|
|
69
|
+
ModalManager.#prerenderList.push(modal);
|
|
70
|
+
});
|
|
71
|
+
ModalManager.#refreshHandler = undefined;
|
|
60
72
|
styleManager.destroyScope(ModalManager.#scope);
|
|
61
73
|
}
|
|
62
74
|
static open(modal) {
|
|
63
|
-
ModalManager.#openHandler(modal);
|
|
75
|
+
return ModalManager.#openHandler(modal);
|
|
64
76
|
}
|
|
65
77
|
}
|
|
66
78
|
|
|
67
|
-
const
|
|
68
|
-
|
|
79
|
+
const closeModal = (modalNode, refresh = true) => {
|
|
80
|
+
if (modalNode.visible === false)
|
|
81
|
+
return;
|
|
82
|
+
modalNode.onClose();
|
|
83
|
+
modalNode.onHide();
|
|
84
|
+
if (refresh)
|
|
85
|
+
ModalManager.refresh();
|
|
86
|
+
if (modalNode.manualDestroy || modalNode.alive === false)
|
|
87
|
+
return;
|
|
88
|
+
return setTimeout(() => modalNode.onDestroy(), modalNode.duration);
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
const subscribeAbortSignal = (modalNode, signal) => {
|
|
92
|
+
if (signal === undefined)
|
|
93
|
+
return null;
|
|
94
|
+
const handleAbort = () => closeModal(modalNode);
|
|
95
|
+
signal.addEventListener('abort', handleAbort, { once: true });
|
|
96
|
+
return () => signal.removeEventListener('abort', handleAbort);
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
const alertHandler = (args) => {
|
|
100
|
+
const modalNode = ModalManager.open({
|
|
101
|
+
...args,
|
|
102
|
+
type: 'alert',
|
|
103
|
+
});
|
|
104
|
+
const unsubscribe = subscribeAbortSignal(modalNode, args.signal);
|
|
105
|
+
const promiseHandler = new Promise((resolve, reject) => {
|
|
69
106
|
try {
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
subtitle,
|
|
77
|
-
content,
|
|
78
|
-
background,
|
|
79
|
-
footer,
|
|
80
|
-
dimmed,
|
|
81
|
-
manualDestroy,
|
|
82
|
-
closeOnBackdropClick,
|
|
83
|
-
ForegroundComponent,
|
|
84
|
-
BackgroundComponent,
|
|
85
|
-
});
|
|
107
|
+
modalNode.handleResolve = () => {
|
|
108
|
+
unsubscribe?.();
|
|
109
|
+
resolve();
|
|
110
|
+
};
|
|
111
|
+
if (args.signal?.aborted)
|
|
112
|
+
closeModal(modalNode);
|
|
86
113
|
}
|
|
87
114
|
catch (error) {
|
|
115
|
+
closeModal(modalNode);
|
|
116
|
+
unsubscribe?.();
|
|
88
117
|
reject(error);
|
|
89
118
|
}
|
|
90
119
|
});
|
|
120
|
+
return { modalNode, promiseHandler };
|
|
91
121
|
};
|
|
92
122
|
|
|
93
|
-
const
|
|
94
|
-
|
|
123
|
+
const confirmHandler = (args) => {
|
|
124
|
+
const modalNode = ModalManager.open({
|
|
125
|
+
...args,
|
|
126
|
+
type: 'confirm',
|
|
127
|
+
});
|
|
128
|
+
const unsubscribe = subscribeAbortSignal(modalNode, args.signal);
|
|
129
|
+
const promiseHandler = new Promise((resolve, reject) => {
|
|
95
130
|
try {
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
subtitle,
|
|
103
|
-
content,
|
|
104
|
-
background,
|
|
105
|
-
footer,
|
|
106
|
-
dimmed,
|
|
107
|
-
manualDestroy,
|
|
108
|
-
closeOnBackdropClick,
|
|
109
|
-
ForegroundComponent,
|
|
110
|
-
BackgroundComponent,
|
|
111
|
-
});
|
|
131
|
+
modalNode.handleResolve = (result) => {
|
|
132
|
+
unsubscribe?.();
|
|
133
|
+
resolve(result ?? false);
|
|
134
|
+
};
|
|
135
|
+
if (args.signal?.aborted)
|
|
136
|
+
closeModal(modalNode);
|
|
112
137
|
}
|
|
113
138
|
catch (error) {
|
|
139
|
+
closeModal(modalNode);
|
|
140
|
+
unsubscribe?.();
|
|
114
141
|
reject(error);
|
|
115
142
|
}
|
|
116
143
|
});
|
|
144
|
+
return { modalNode, promiseHandler };
|
|
117
145
|
};
|
|
118
146
|
|
|
119
|
-
const
|
|
120
|
-
|
|
147
|
+
const promptHandler = (args) => {
|
|
148
|
+
const modalNode = ModalManager.open({
|
|
149
|
+
...args,
|
|
150
|
+
type: 'prompt',
|
|
151
|
+
});
|
|
152
|
+
const unsubscribe = subscribeAbortSignal(modalNode, args.signal);
|
|
153
|
+
const promiseHandler = new Promise((resolve, reject) => {
|
|
121
154
|
try {
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
content,
|
|
129
|
-
Input,
|
|
130
|
-
defaultValue,
|
|
131
|
-
disabled,
|
|
132
|
-
returnOnCancel,
|
|
133
|
-
background,
|
|
134
|
-
footer,
|
|
135
|
-
dimmed,
|
|
136
|
-
manualDestroy,
|
|
137
|
-
closeOnBackdropClick,
|
|
138
|
-
ForegroundComponent,
|
|
139
|
-
BackgroundComponent,
|
|
140
|
-
});
|
|
155
|
+
modalNode.handleResolve = (result) => {
|
|
156
|
+
unsubscribe?.();
|
|
157
|
+
resolve(result);
|
|
158
|
+
};
|
|
159
|
+
if (args.signal?.aborted)
|
|
160
|
+
closeModal(modalNode);
|
|
141
161
|
}
|
|
142
162
|
catch (error) {
|
|
163
|
+
closeModal(modalNode);
|
|
164
|
+
unsubscribe?.();
|
|
143
165
|
reject(error);
|
|
144
166
|
}
|
|
145
167
|
});
|
|
168
|
+
return { modalNode, promiseHandler };
|
|
146
169
|
};
|
|
147
170
|
|
|
171
|
+
const alert = (args) => alertHandler(args).promiseHandler;
|
|
172
|
+
const confirm = (args) => confirmHandler(args).promiseHandler;
|
|
173
|
+
const prompt = (args) => promptHandler(args).promiseHandler;
|
|
174
|
+
|
|
148
175
|
class AbstractNode {
|
|
149
176
|
id;
|
|
150
177
|
group;
|
|
@@ -152,9 +179,10 @@ class AbstractNode {
|
|
|
152
179
|
title;
|
|
153
180
|
subtitle;
|
|
154
181
|
background;
|
|
182
|
+
dimmed;
|
|
183
|
+
duration;
|
|
155
184
|
manualDestroy;
|
|
156
185
|
closeOnBackdropClick;
|
|
157
|
-
dimmed;
|
|
158
186
|
ForegroundComponent;
|
|
159
187
|
BackgroundComponent;
|
|
160
188
|
#alive;
|
|
@@ -165,9 +193,12 @@ class AbstractNode {
|
|
|
165
193
|
get visible() {
|
|
166
194
|
return this.#visible;
|
|
167
195
|
}
|
|
168
|
-
#
|
|
196
|
+
#handleResolve;
|
|
197
|
+
set handleResolve(handleResolve) {
|
|
198
|
+
this.#handleResolve = handleResolve;
|
|
199
|
+
}
|
|
169
200
|
#listeners = new Set();
|
|
170
|
-
constructor({ id, initiator, group, title, subtitle, background, dimmed = true, manualDestroy = false, closeOnBackdropClick = true,
|
|
201
|
+
constructor({ id, initiator, group, title, subtitle, background, dimmed = true, duration = 0, manualDestroy = false, closeOnBackdropClick = true, handleResolve, ForegroundComponent, BackgroundComponent, }) {
|
|
171
202
|
this.id = id;
|
|
172
203
|
this.group = group;
|
|
173
204
|
this.initiator = initiator;
|
|
@@ -175,13 +206,17 @@ class AbstractNode {
|
|
|
175
206
|
this.subtitle = subtitle;
|
|
176
207
|
this.background = background;
|
|
177
208
|
this.dimmed = dimmed;
|
|
209
|
+
this.duration = duration;
|
|
178
210
|
this.manualDestroy = manualDestroy;
|
|
179
211
|
this.closeOnBackdropClick = closeOnBackdropClick;
|
|
180
212
|
this.ForegroundComponent = ForegroundComponent;
|
|
181
213
|
this.BackgroundComponent = BackgroundComponent;
|
|
182
214
|
this.#alive = true;
|
|
183
215
|
this.#visible = true;
|
|
184
|
-
this.#
|
|
216
|
+
this.#handleResolve = handleResolve;
|
|
217
|
+
}
|
|
218
|
+
onResolve(result) {
|
|
219
|
+
this.#handleResolve?.(result);
|
|
185
220
|
}
|
|
186
221
|
subscribe(listener) {
|
|
187
222
|
this.#listeners.add(listener);
|
|
@@ -193,9 +228,6 @@ class AbstractNode {
|
|
|
193
228
|
for (const listener of this.#listeners)
|
|
194
229
|
listener();
|
|
195
230
|
}
|
|
196
|
-
resolve(result) {
|
|
197
|
-
this.#resolve(result);
|
|
198
|
-
}
|
|
199
231
|
onDestroy() {
|
|
200
232
|
const needPublish = this.#alive === true;
|
|
201
233
|
this.#alive = false;
|
|
@@ -221,7 +253,7 @@ class AlertNode extends AbstractNode {
|
|
|
221
253
|
subtype;
|
|
222
254
|
content;
|
|
223
255
|
footer;
|
|
224
|
-
constructor({ id, group, initiator, type, subtype, title, subtitle, content, footer, background, dimmed, manualDestroy, closeOnBackdropClick,
|
|
256
|
+
constructor({ id, group, initiator, type, subtype, title, subtitle, content, footer, background, dimmed, duration, manualDestroy, closeOnBackdropClick, handleResolve, ForegroundComponent, BackgroundComponent, }) {
|
|
225
257
|
super({
|
|
226
258
|
id,
|
|
227
259
|
group,
|
|
@@ -230,9 +262,10 @@ class AlertNode extends AbstractNode {
|
|
|
230
262
|
subtitle,
|
|
231
263
|
background,
|
|
232
264
|
dimmed,
|
|
265
|
+
duration,
|
|
233
266
|
manualDestroy,
|
|
234
267
|
closeOnBackdropClick,
|
|
235
|
-
|
|
268
|
+
handleResolve,
|
|
236
269
|
ForegroundComponent,
|
|
237
270
|
BackgroundComponent,
|
|
238
271
|
});
|
|
@@ -242,10 +275,10 @@ class AlertNode extends AbstractNode {
|
|
|
242
275
|
this.footer = footer;
|
|
243
276
|
}
|
|
244
277
|
onClose() {
|
|
245
|
-
this.
|
|
278
|
+
this.onResolve(null);
|
|
246
279
|
}
|
|
247
280
|
onConfirm() {
|
|
248
|
-
this.
|
|
281
|
+
this.onResolve(null);
|
|
249
282
|
}
|
|
250
283
|
}
|
|
251
284
|
|
|
@@ -254,7 +287,7 @@ class ConfirmNode extends AbstractNode {
|
|
|
254
287
|
subtype;
|
|
255
288
|
content;
|
|
256
289
|
footer;
|
|
257
|
-
constructor({ id, group, initiator, type, subtype, title, subtitle, content, footer, background, dimmed, manualDestroy, closeOnBackdropClick,
|
|
290
|
+
constructor({ id, group, initiator, type, subtype, title, subtitle, content, footer, background, dimmed, duration, manualDestroy, closeOnBackdropClick, handleResolve, ForegroundComponent, BackgroundComponent, }) {
|
|
258
291
|
super({
|
|
259
292
|
id,
|
|
260
293
|
group,
|
|
@@ -263,9 +296,10 @@ class ConfirmNode extends AbstractNode {
|
|
|
263
296
|
subtitle,
|
|
264
297
|
background,
|
|
265
298
|
dimmed,
|
|
299
|
+
duration,
|
|
266
300
|
manualDestroy,
|
|
267
301
|
closeOnBackdropClick,
|
|
268
|
-
|
|
302
|
+
handleResolve,
|
|
269
303
|
ForegroundComponent,
|
|
270
304
|
BackgroundComponent,
|
|
271
305
|
});
|
|
@@ -275,10 +309,10 @@ class ConfirmNode extends AbstractNode {
|
|
|
275
309
|
this.footer = footer;
|
|
276
310
|
}
|
|
277
311
|
onClose() {
|
|
278
|
-
this.
|
|
312
|
+
this.onResolve(false);
|
|
279
313
|
}
|
|
280
314
|
onConfirm() {
|
|
281
|
-
this.
|
|
315
|
+
this.onResolve(true);
|
|
282
316
|
}
|
|
283
317
|
}
|
|
284
318
|
|
|
@@ -291,7 +325,7 @@ class PromptNode extends AbstractNode {
|
|
|
291
325
|
returnOnCancel;
|
|
292
326
|
footer;
|
|
293
327
|
#value;
|
|
294
|
-
constructor({ id, group, initiator, type, title, subtitle, content, defaultValue, Input, disabled, returnOnCancel, footer, background, dimmed, manualDestroy, closeOnBackdropClick,
|
|
328
|
+
constructor({ id, group, initiator, type, title, subtitle, content, defaultValue, Input, disabled, returnOnCancel, footer, background, dimmed, duration, manualDestroy, closeOnBackdropClick, handleResolve, ForegroundComponent, BackgroundComponent, }) {
|
|
295
329
|
super({
|
|
296
330
|
id,
|
|
297
331
|
group,
|
|
@@ -300,9 +334,10 @@ class PromptNode extends AbstractNode {
|
|
|
300
334
|
subtitle,
|
|
301
335
|
background,
|
|
302
336
|
dimmed,
|
|
337
|
+
duration,
|
|
303
338
|
manualDestroy,
|
|
304
339
|
closeOnBackdropClick,
|
|
305
|
-
|
|
340
|
+
handleResolve,
|
|
306
341
|
ForegroundComponent,
|
|
307
342
|
BackgroundComponent,
|
|
308
343
|
});
|
|
@@ -319,13 +354,13 @@ class PromptNode extends AbstractNode {
|
|
|
319
354
|
this.#value = value;
|
|
320
355
|
}
|
|
321
356
|
onConfirm() {
|
|
322
|
-
this.
|
|
357
|
+
this.onResolve(this.#value ?? null);
|
|
323
358
|
}
|
|
324
359
|
onClose() {
|
|
325
360
|
if (this.returnOnCancel)
|
|
326
|
-
this.
|
|
361
|
+
this.onResolve(this.#value ?? null);
|
|
327
362
|
else
|
|
328
|
-
this.
|
|
363
|
+
this.onResolve(null);
|
|
329
364
|
}
|
|
330
365
|
}
|
|
331
366
|
|
|
@@ -364,8 +399,8 @@ const FallbackFooter = ({ confirmLabel, hideConfirm = false, cancelLabel, hideCa
|
|
|
364
399
|
const ModalManagerContext = react.createContext({});
|
|
365
400
|
|
|
366
401
|
const useModalManagerContext = () => react.useContext(ModalManagerContext);
|
|
367
|
-
const
|
|
368
|
-
const { getModal } =
|
|
402
|
+
const useModalManager = (id) => {
|
|
403
|
+
const { getModal } = react.useContext(ModalManagerContext);
|
|
369
404
|
return react.useMemo(() => getModal(id), [id, getModal]);
|
|
370
405
|
};
|
|
371
406
|
|
|
@@ -429,20 +464,28 @@ const ConfigurationContextProvider = react.memo(({ ForegroundComponent, Backgrou
|
|
|
429
464
|
FooterComponent: react.memo(FooterComponent || FallbackFooter),
|
|
430
465
|
});
|
|
431
466
|
const options = hook.useSnapshot(inputOptions);
|
|
432
|
-
const value = react.useMemo(() =>
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
467
|
+
const value = react.useMemo(() => {
|
|
468
|
+
const { backdrop: defaultBackdrop, ...defaultOptions } = DEFAULT_OPTIONS;
|
|
469
|
+
const backdrop = getBackdropStyle(options?.backdrop, defaultBackdrop);
|
|
470
|
+
return {
|
|
471
|
+
ForegroundComponent: constant.ForegroundComponent,
|
|
472
|
+
BackgroundComponent: constant.BackgroundComponent,
|
|
473
|
+
TitleComponent: constant.TitleComponent,
|
|
474
|
+
SubtitleComponent: constant.SubtitleComponent,
|
|
475
|
+
ContentComponent: constant.ContentComponent,
|
|
476
|
+
FooterComponent: constant.FooterComponent,
|
|
477
|
+
options: { ...defaultOptions, ...options, backdrop },
|
|
478
|
+
};
|
|
479
|
+
}, [constant, options]);
|
|
444
480
|
return (jsxRuntime.jsx(ConfigurationContext.Provider, { value: value, children: children }));
|
|
445
481
|
});
|
|
482
|
+
const getBackdropStyle = (backdrop, defaultBackdrop) => {
|
|
483
|
+
if (filter.isPlainObject(backdrop))
|
|
484
|
+
return backdrop;
|
|
485
|
+
if (filter.isString(backdrop))
|
|
486
|
+
return { backgroundColor: backdrop };
|
|
487
|
+
return defaultBackdrop;
|
|
488
|
+
};
|
|
446
489
|
|
|
447
490
|
const useConfigurationContext = () => react.useContext(ConfigurationContext);
|
|
448
491
|
const useConfigurationOptions = () => {
|
|
@@ -474,32 +517,26 @@ const ModalManagerContextProvider = react.memo(({ usePathname, children, }) => {
|
|
|
474
517
|
const { manualDestroy, closeOnBackdropClick } = options;
|
|
475
518
|
for (const data of ModalManager.prerender) {
|
|
476
519
|
const modal = nodeFactory({
|
|
520
|
+
duration,
|
|
521
|
+
manualDestroy,
|
|
522
|
+
closeOnBackdropClick,
|
|
477
523
|
...data,
|
|
478
524
|
id: modalIdSequence.current++,
|
|
479
525
|
initiator: initiator.current,
|
|
480
|
-
manualDestroy: data.manualDestroy !== undefined
|
|
481
|
-
? data.manualDestroy
|
|
482
|
-
: manualDestroy,
|
|
483
|
-
closeOnBackdropClick: data.closeOnBackdropClick !== undefined
|
|
484
|
-
? data.closeOnBackdropClick
|
|
485
|
-
: closeOnBackdropClick,
|
|
486
526
|
});
|
|
487
527
|
modalDictionary.current.set(modal.id, modal);
|
|
488
528
|
setModalIds((ids) => [...ids, modal.id]);
|
|
489
529
|
}
|
|
490
530
|
ModalManager.openHandler = (data) => {
|
|
491
|
-
const
|
|
531
|
+
const modalNode = nodeFactory({
|
|
532
|
+
duration,
|
|
533
|
+
manualDestroy,
|
|
534
|
+
closeOnBackdropClick,
|
|
492
535
|
...data,
|
|
493
536
|
id: modalIdSequence.current++,
|
|
494
537
|
initiator: initiator.current,
|
|
495
|
-
manualDestroy: data.manualDestroy !== undefined
|
|
496
|
-
? data.manualDestroy
|
|
497
|
-
: manualDestroy,
|
|
498
|
-
closeOnBackdropClick: data.closeOnBackdropClick !== undefined
|
|
499
|
-
? data.closeOnBackdropClick
|
|
500
|
-
: closeOnBackdropClick,
|
|
501
538
|
});
|
|
502
|
-
modalDictionary.current.set(
|
|
539
|
+
modalDictionary.current.set(modalNode.id, modalNode);
|
|
503
540
|
setModalIds((ids) => {
|
|
504
541
|
const aliveIds = [];
|
|
505
542
|
for (let i = 0, l = ids.length; i < l; i++) {
|
|
@@ -510,8 +547,9 @@ const ModalManagerContextProvider = react.memo(({ usePathname, children, }) => {
|
|
|
510
547
|
else
|
|
511
548
|
aliveIds.push(id);
|
|
512
549
|
}
|
|
513
|
-
return [...aliveIds,
|
|
550
|
+
return [...aliveIds, modalNode.id];
|
|
514
551
|
});
|
|
552
|
+
return modalNode;
|
|
515
553
|
};
|
|
516
554
|
});
|
|
517
555
|
react.useLayoutEffect(() => {
|
|
@@ -526,78 +564,62 @@ const ModalManagerContextProvider = react.memo(({ usePathname, children, }) => {
|
|
|
526
564
|
}
|
|
527
565
|
initiator.current = pathname;
|
|
528
566
|
}, [pathname]);
|
|
529
|
-
const
|
|
530
|
-
|
|
531
|
-
}, []);
|
|
532
|
-
const onDestroy = react.useCallback((modalId) => {
|
|
567
|
+
const getModalNodeRef = react.useRef((modalId) => modalDictionary.current.get(modalId));
|
|
568
|
+
const onDestroyRef = react.useRef((modalId) => {
|
|
533
569
|
const modal = modalDictionary.current.get(modalId);
|
|
534
570
|
if (!modal)
|
|
535
571
|
return;
|
|
536
572
|
modal.onDestroy();
|
|
537
|
-
|
|
538
|
-
}
|
|
539
|
-
const
|
|
540
|
-
const hideModal = react.useCallback((modalId) => {
|
|
573
|
+
ModalManager.refresh();
|
|
574
|
+
});
|
|
575
|
+
const hideModalRef = react.useRef((modalId) => {
|
|
541
576
|
const modal = modalDictionary.current.get(modalId);
|
|
542
577
|
if (!modal)
|
|
543
578
|
return;
|
|
544
579
|
modal.onHide();
|
|
545
|
-
|
|
546
|
-
if (
|
|
547
|
-
setTimeout(() =>
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
}, [duration]);
|
|
551
|
-
const onChange = react.useCallback((modalId, value) => {
|
|
580
|
+
ModalManager.refresh();
|
|
581
|
+
if (modal.manualDestroy === false)
|
|
582
|
+
setTimeout(() => modal.onDestroy(), modal.duration);
|
|
583
|
+
});
|
|
584
|
+
const onChangeRef = react.useRef((modalId, value) => {
|
|
552
585
|
const modal = modalDictionary.current.get(modalId);
|
|
553
586
|
if (!modal)
|
|
554
587
|
return;
|
|
555
588
|
if (modal.type === 'prompt')
|
|
556
589
|
modal.onChange(value);
|
|
557
|
-
}
|
|
558
|
-
const
|
|
590
|
+
});
|
|
591
|
+
const onConfirmRef = react.useRef((modalId) => {
|
|
559
592
|
const modal = modalDictionary.current.get(modalId);
|
|
560
593
|
if (!modal)
|
|
561
594
|
return;
|
|
562
595
|
modal.onConfirm();
|
|
563
|
-
|
|
564
|
-
}
|
|
565
|
-
const
|
|
596
|
+
hideModalRef.current(modalId);
|
|
597
|
+
});
|
|
598
|
+
const onCloseRef = react.useRef((modalId) => {
|
|
566
599
|
const modal = modalDictionary.current.get(modalId);
|
|
567
600
|
if (!modal)
|
|
568
601
|
return;
|
|
569
602
|
modal.onClose();
|
|
570
|
-
|
|
571
|
-
}
|
|
572
|
-
const
|
|
573
|
-
modal:
|
|
574
|
-
onConfirm: () =>
|
|
575
|
-
onClose: () =>
|
|
576
|
-
onChange: (value) =>
|
|
577
|
-
onDestroy: () =>
|
|
578
|
-
})
|
|
603
|
+
hideModalRef.current(modalId);
|
|
604
|
+
});
|
|
605
|
+
const getModalRef = react.useRef((modalId) => ({
|
|
606
|
+
modal: getModalNodeRef.current(modalId),
|
|
607
|
+
onConfirm: () => onConfirmRef.current(modalId),
|
|
608
|
+
onClose: () => onCloseRef.current(modalId),
|
|
609
|
+
onChange: (value) => onChangeRef.current(modalId, value),
|
|
610
|
+
onDestroy: () => onDestroyRef.current(modalId),
|
|
611
|
+
}));
|
|
579
612
|
const value = react.useMemo(() => {
|
|
580
613
|
return {
|
|
581
614
|
modalIds,
|
|
582
|
-
getModalNode,
|
|
583
|
-
onChange,
|
|
584
|
-
onConfirm,
|
|
585
|
-
onClose,
|
|
586
|
-
onDestroy,
|
|
587
|
-
getModal,
|
|
588
|
-
setUpdater: (updater) => {
|
|
589
|
-
updaterRef.current = updater;
|
|
590
|
-
},
|
|
615
|
+
getModalNode: getModalNodeRef.current,
|
|
616
|
+
onChange: onChangeRef.current,
|
|
617
|
+
onConfirm: onConfirmRef.current,
|
|
618
|
+
onClose: onCloseRef.current,
|
|
619
|
+
onDestroy: onDestroyRef.current,
|
|
620
|
+
getModal: getModalRef.current,
|
|
591
621
|
};
|
|
592
|
-
}, [
|
|
593
|
-
modalIds,
|
|
594
|
-
getModal,
|
|
595
|
-
getModalNode,
|
|
596
|
-
onChange,
|
|
597
|
-
onConfirm,
|
|
598
|
-
onClose,
|
|
599
|
-
onDestroy,
|
|
600
|
-
]);
|
|
622
|
+
}, [modalIds]);
|
|
601
623
|
return (jsxRuntime.jsx(ModalManagerContext.Provider, { value: value, children: children }));
|
|
602
624
|
});
|
|
603
625
|
|
|
@@ -666,7 +688,7 @@ ModalManager.defineStyleSheet('background', style$3);
|
|
|
666
688
|
const BackgroundFrame = ({ modalId, onChangeOrder, }) => {
|
|
667
689
|
const { BackgroundComponent } = useConfigurationContext();
|
|
668
690
|
const { context: userDefinedContext } = useUserDefinedContext();
|
|
669
|
-
const { modal, onClose, onChange, onConfirm, onDestroy } =
|
|
691
|
+
const { modal, onClose, onChange, onConfirm, onDestroy } = useModalManager(modalId);
|
|
670
692
|
const handleClose = react.useCallback((event) => {
|
|
671
693
|
if (modal && modal.closeOnBackdropClick && modal.visible)
|
|
672
694
|
onClose();
|
|
@@ -782,7 +804,7 @@ ModalManager.defineStyleSheet('foreground', style$2);
|
|
|
782
804
|
const ForegroundFrame = ({ modalId, onChangeOrder, }) => {
|
|
783
805
|
const { ForegroundComponent } = useConfigurationContext();
|
|
784
806
|
const { context: userDefinedContext } = useUserDefinedContext();
|
|
785
|
-
const { modal, onChange, onConfirm, onClose, onDestroy } =
|
|
807
|
+
const { modal, onChange, onConfirm, onClose, onDestroy } = useModalManager(modalId);
|
|
786
808
|
const Foreground = react.useMemo(() => modal?.ForegroundComponent || ForegroundComponent, [ForegroundComponent, modal]);
|
|
787
809
|
if (!modal)
|
|
788
810
|
return null;
|
|
@@ -814,7 +836,7 @@ ModalManager.defineStyleSheet('presenter', style$1);
|
|
|
814
836
|
const Presenter = react.memo(({ modalId, getValue, increment }) => {
|
|
815
837
|
const ref = react.useRef(null);
|
|
816
838
|
const options = useConfigurationOptions();
|
|
817
|
-
const { modal } =
|
|
839
|
+
const { modal } = useModalManager(modalId);
|
|
818
840
|
useSubscribeModal(modal);
|
|
819
841
|
hook.useOnMountLayout(() => {
|
|
820
842
|
if (ref.current === null)
|
|
@@ -842,27 +864,41 @@ const style = `
|
|
|
842
864
|
inset: 0;
|
|
843
865
|
pointer-events: none;
|
|
844
866
|
z-index: var(--z-index);
|
|
845
|
-
|
|
867
|
+
}`;
|
|
868
|
+
const backdrop = ModalManager.getHashedClassNames('backdrop');
|
|
869
|
+
const backdropStyle = `
|
|
870
|
+
.${backdrop} {
|
|
871
|
+
position: fixed;
|
|
872
|
+
inset: 0;
|
|
873
|
+
opacity: 0;
|
|
874
|
+
transition-property: opacity;
|
|
875
|
+
transition-duration: var(--transition-duration);
|
|
876
|
+
transition-timing-function: ease-in-out;
|
|
877
|
+
pointer-events: none;
|
|
846
878
|
}`;
|
|
847
879
|
ModalManager.defineStyleSheet('anchor', style);
|
|
880
|
+
ModalManager.defineStyleSheet('backdrop', backdropStyle);
|
|
848
881
|
|
|
849
882
|
const { getValue, increment, reset } = lib.counterFactory(0);
|
|
850
883
|
const AnchorInner = () => {
|
|
851
884
|
const [version, update] = hook.useVersion();
|
|
852
|
-
const { modalIds
|
|
885
|
+
const { modalIds } = useModalManagerContext();
|
|
853
886
|
react.useEffect(() => {
|
|
854
|
-
|
|
855
|
-
}, [
|
|
887
|
+
ModalManager.refreshHandler = update;
|
|
888
|
+
}, [update]);
|
|
856
889
|
const options = useConfigurationOptions();
|
|
857
890
|
const dimmed = useActiveModalCount(validateDimmable, version);
|
|
858
891
|
if (!dimmed)
|
|
859
892
|
reset();
|
|
860
|
-
const
|
|
861
|
-
...(dimmed ? options.backdrop : {}),
|
|
893
|
+
const anchorStyle = react.useMemo(() => ({
|
|
862
894
|
'--z-index': options.zIndex,
|
|
863
|
-
|
|
895
|
+
'--transition-duration': options.duration,
|
|
896
|
+
}), [options]);
|
|
897
|
+
const backdropStyle = react.useMemo(() => ({
|
|
898
|
+
...options.backdrop,
|
|
899
|
+
opacity: dimmed ? 1 : 0,
|
|
864
900
|
}), [dimmed, options]);
|
|
865
|
-
return (jsxRuntime.
|
|
901
|
+
return (jsxRuntime.jsxs("div", { className: anchor, style: anchorStyle, children: [jsxRuntime.jsx("div", { className: backdrop, style: backdropStyle }), array.map(modalIds, (id) => (jsxRuntime.jsx(Presenter, { modalId: id, getValue: getValue, increment: increment, reset: reset }, id)))] }));
|
|
866
902
|
};
|
|
867
903
|
const validateDimmable = (modal) => modal?.visible && modal.dimmed;
|
|
868
904
|
const Anchor = react.memo(hoc.withErrorBoundary(AnchorInner));
|
|
@@ -949,8 +985,38 @@ const useBootstrap = ({ usePathname: useExternalPathname, ForegroundComponent, B
|
|
|
949
985
|
return { portal, initialize };
|
|
950
986
|
};
|
|
951
987
|
|
|
988
|
+
const useModal = () => {
|
|
989
|
+
const modalNodesRef = react.useRef([]);
|
|
990
|
+
const alertRef = react.useRef((args) => {
|
|
991
|
+
const { modalNode, promiseHandler } = alertHandler(args);
|
|
992
|
+
modalNodesRef.current.push(modalNode);
|
|
993
|
+
return promiseHandler;
|
|
994
|
+
});
|
|
995
|
+
const confirmRef = react.useRef((args) => {
|
|
996
|
+
const { modalNode, promiseHandler } = confirmHandler(args);
|
|
997
|
+
modalNodesRef.current.push(modalNode);
|
|
998
|
+
return promiseHandler;
|
|
999
|
+
});
|
|
1000
|
+
const promptRef = react.useRef((args) => {
|
|
1001
|
+
const { modalNode, promiseHandler } = promptHandler(args);
|
|
1002
|
+
modalNodesRef.current.push(modalNode);
|
|
1003
|
+
return promiseHandler;
|
|
1004
|
+
});
|
|
1005
|
+
hook.useOnUnmount(() => {
|
|
1006
|
+
for (const node of modalNodesRef.current)
|
|
1007
|
+
closeModal(node, false);
|
|
1008
|
+
ModalManager.refresh();
|
|
1009
|
+
modalNodesRef.current = [];
|
|
1010
|
+
});
|
|
1011
|
+
return {
|
|
1012
|
+
alert: alertRef.current,
|
|
1013
|
+
confirm: confirmRef.current,
|
|
1014
|
+
prompt: promptRef.current,
|
|
1015
|
+
};
|
|
1016
|
+
};
|
|
1017
|
+
|
|
952
1018
|
const useDestroyAfter = (modalId, duration) => {
|
|
953
|
-
const { modal, onDestroy } =
|
|
1019
|
+
const { modal, onDestroy } = useModalManager(modalId);
|
|
954
1020
|
const tick = useSubscribeModal(modal);
|
|
955
1021
|
const reference = react.useRef({
|
|
956
1022
|
modal,
|
|
@@ -998,6 +1064,7 @@ exports.prompt = prompt;
|
|
|
998
1064
|
exports.useActiveModalCount = useActiveModalCount;
|
|
999
1065
|
exports.useDestroyAfter = useDestroyAfter;
|
|
1000
1066
|
exports.useInitializeModal = useBootstrap;
|
|
1067
|
+
exports.useModal = useModal;
|
|
1001
1068
|
exports.useModalAnimation = useModalAnimation;
|
|
1002
1069
|
exports.useModalBackdrop = useConfigurationBackdrop;
|
|
1003
1070
|
exports.useModalDuration = useConfigurationDuration;
|