@lerx/promise-modal 0.8.4 → 0.8.6
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/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 +54 -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 +7 -0
- package/dist/hooks/useModalDuration.d.ts +8 -0
- package/dist/index.cjs +211 -154
- package/dist/index.d.ts +3 -1
- package/dist/index.mjs +211 -155
- 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/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
2
2
|
import { createContext, useContext, useMemo, forwardRef, memo, useRef, useState, useLayoutEffect, useCallback, Fragment, useEffect, useImperativeHandle } from 'react';
|
|
3
3
|
import { convertMsFromDuration } from '@winglet/common-utils/convert';
|
|
4
|
-
import { useConstant, useSnapshot, useReference, useOnMountLayout, useHandle, useVersion, useOnMount } from '@winglet/react-utils/hook';
|
|
4
|
+
import { useConstant, useSnapshot, useReference, useOnMountLayout, useHandle, useVersion, useOnMount, useOnUnmount } from '@winglet/react-utils/hook';
|
|
5
5
|
import { polynomialHash } from '@winglet/common-utils/hash';
|
|
6
6
|
import { getRandomString, counterFactory } from '@winglet/common-utils/lib';
|
|
7
7
|
import { styleManagerFactory, destroyScope } from '@winglet/style-utils/style-manager';
|
|
@@ -16,6 +16,8 @@ class ModalManager {
|
|
|
16
16
|
static #anchor = null;
|
|
17
17
|
static #scope = `promise-modal-${getRandomString(36)}`;
|
|
18
18
|
static #hash = polynomialHash(ModalManager.#scope);
|
|
19
|
+
static #styleManager = styleManagerFactory(ModalManager.#scope);
|
|
20
|
+
static #styleSheetDefinition = new Map();
|
|
19
21
|
static anchor(options) {
|
|
20
22
|
if (ModalManager.#anchor !== null)
|
|
21
23
|
return ModalManager.#anchor;
|
|
@@ -34,13 +36,20 @@ class ModalManager {
|
|
|
34
36
|
static get prerender() {
|
|
35
37
|
return ModalManager.#prerenderList;
|
|
36
38
|
}
|
|
37
|
-
static #openHandler = (modal) =>
|
|
39
|
+
static #openHandler = ((modal) => {
|
|
40
|
+
ModalManager.#prerenderList.push(modal);
|
|
41
|
+
});
|
|
38
42
|
static set openHandler(handler) {
|
|
39
43
|
ModalManager.#openHandler = handler;
|
|
40
44
|
ModalManager.#prerenderList = [];
|
|
41
45
|
}
|
|
42
|
-
static #
|
|
43
|
-
static
|
|
46
|
+
static #refreshHandler;
|
|
47
|
+
static set refreshHandler(handler) {
|
|
48
|
+
ModalManager.#refreshHandler = handler;
|
|
49
|
+
}
|
|
50
|
+
static refresh() {
|
|
51
|
+
ModalManager.#refreshHandler?.();
|
|
52
|
+
}
|
|
44
53
|
static defineStyleSheet(styleId, css) {
|
|
45
54
|
ModalManager.#styleSheetDefinition.set(styleId, compressCss(css));
|
|
46
55
|
}
|
|
@@ -54,95 +63,113 @@ class ModalManager {
|
|
|
54
63
|
static reset() {
|
|
55
64
|
ModalManager.#anchor = null;
|
|
56
65
|
ModalManager.#prerenderList = [];
|
|
57
|
-
ModalManager.#openHandler = (modal) =>
|
|
66
|
+
ModalManager.#openHandler = ((modal) => {
|
|
67
|
+
ModalManager.#prerenderList.push(modal);
|
|
68
|
+
});
|
|
69
|
+
ModalManager.#refreshHandler = undefined;
|
|
58
70
|
destroyScope(ModalManager.#scope);
|
|
59
71
|
}
|
|
60
72
|
static open(modal) {
|
|
61
|
-
ModalManager.#openHandler(modal);
|
|
73
|
+
return ModalManager.#openHandler(modal);
|
|
62
74
|
}
|
|
63
75
|
}
|
|
64
76
|
|
|
65
|
-
const
|
|
66
|
-
|
|
77
|
+
const closeModal = (modalNode, refresh = true) => {
|
|
78
|
+
if (modalNode.visible === false)
|
|
79
|
+
return;
|
|
80
|
+
modalNode.onClose();
|
|
81
|
+
modalNode.onHide();
|
|
82
|
+
if (refresh)
|
|
83
|
+
ModalManager.refresh();
|
|
84
|
+
if (modalNode.manualDestroy || modalNode.alive === false)
|
|
85
|
+
return;
|
|
86
|
+
return setTimeout(() => modalNode.onDestroy(), modalNode.duration);
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
const subscribeAbortSignal = (modalNode, signal) => {
|
|
90
|
+
if (signal === undefined)
|
|
91
|
+
return null;
|
|
92
|
+
const handleAbort = () => closeModal(modalNode);
|
|
93
|
+
signal.addEventListener('abort', handleAbort, { once: true });
|
|
94
|
+
return () => signal.removeEventListener('abort', handleAbort);
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
const alertHandler = (args) => {
|
|
98
|
+
const modalNode = ModalManager.open({
|
|
99
|
+
...args,
|
|
100
|
+
type: 'alert',
|
|
101
|
+
});
|
|
102
|
+
const unsubscribe = subscribeAbortSignal(modalNode, args.signal);
|
|
103
|
+
const promiseHandler = new Promise((resolve, reject) => {
|
|
67
104
|
try {
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
subtitle,
|
|
75
|
-
content,
|
|
76
|
-
background,
|
|
77
|
-
footer,
|
|
78
|
-
dimmed,
|
|
79
|
-
manualDestroy,
|
|
80
|
-
closeOnBackdropClick,
|
|
81
|
-
ForegroundComponent,
|
|
82
|
-
BackgroundComponent,
|
|
83
|
-
});
|
|
105
|
+
modalNode.handleResolve = () => {
|
|
106
|
+
unsubscribe?.();
|
|
107
|
+
resolve();
|
|
108
|
+
};
|
|
109
|
+
if (args.signal?.aborted)
|
|
110
|
+
closeModal(modalNode);
|
|
84
111
|
}
|
|
85
112
|
catch (error) {
|
|
113
|
+
closeModal(modalNode);
|
|
114
|
+
unsubscribe?.();
|
|
86
115
|
reject(error);
|
|
87
116
|
}
|
|
88
117
|
});
|
|
118
|
+
return { modalNode, promiseHandler };
|
|
89
119
|
};
|
|
90
120
|
|
|
91
|
-
const
|
|
92
|
-
|
|
121
|
+
const confirmHandler = (args) => {
|
|
122
|
+
const modalNode = ModalManager.open({
|
|
123
|
+
...args,
|
|
124
|
+
type: 'confirm',
|
|
125
|
+
});
|
|
126
|
+
const unsubscribe = subscribeAbortSignal(modalNode, args.signal);
|
|
127
|
+
const promiseHandler = new Promise((resolve, reject) => {
|
|
93
128
|
try {
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
subtitle,
|
|
101
|
-
content,
|
|
102
|
-
background,
|
|
103
|
-
footer,
|
|
104
|
-
dimmed,
|
|
105
|
-
manualDestroy,
|
|
106
|
-
closeOnBackdropClick,
|
|
107
|
-
ForegroundComponent,
|
|
108
|
-
BackgroundComponent,
|
|
109
|
-
});
|
|
129
|
+
modalNode.handleResolve = (result) => {
|
|
130
|
+
unsubscribe?.();
|
|
131
|
+
resolve(result ?? false);
|
|
132
|
+
};
|
|
133
|
+
if (args.signal?.aborted)
|
|
134
|
+
closeModal(modalNode);
|
|
110
135
|
}
|
|
111
136
|
catch (error) {
|
|
137
|
+
closeModal(modalNode);
|
|
138
|
+
unsubscribe?.();
|
|
112
139
|
reject(error);
|
|
113
140
|
}
|
|
114
141
|
});
|
|
142
|
+
return { modalNode, promiseHandler };
|
|
115
143
|
};
|
|
116
144
|
|
|
117
|
-
const
|
|
118
|
-
|
|
145
|
+
const promptHandler = (args) => {
|
|
146
|
+
const modalNode = ModalManager.open({
|
|
147
|
+
...args,
|
|
148
|
+
type: 'prompt',
|
|
149
|
+
});
|
|
150
|
+
const unsubscribe = subscribeAbortSignal(modalNode, args.signal);
|
|
151
|
+
const promiseHandler = new Promise((resolve, reject) => {
|
|
119
152
|
try {
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
content,
|
|
127
|
-
Input,
|
|
128
|
-
defaultValue,
|
|
129
|
-
disabled,
|
|
130
|
-
returnOnCancel,
|
|
131
|
-
background,
|
|
132
|
-
footer,
|
|
133
|
-
dimmed,
|
|
134
|
-
manualDestroy,
|
|
135
|
-
closeOnBackdropClick,
|
|
136
|
-
ForegroundComponent,
|
|
137
|
-
BackgroundComponent,
|
|
138
|
-
});
|
|
153
|
+
modalNode.handleResolve = (result) => {
|
|
154
|
+
unsubscribe?.();
|
|
155
|
+
resolve(result);
|
|
156
|
+
};
|
|
157
|
+
if (args.signal?.aborted)
|
|
158
|
+
closeModal(modalNode);
|
|
139
159
|
}
|
|
140
160
|
catch (error) {
|
|
161
|
+
closeModal(modalNode);
|
|
162
|
+
unsubscribe?.();
|
|
141
163
|
reject(error);
|
|
142
164
|
}
|
|
143
165
|
});
|
|
166
|
+
return { modalNode, promiseHandler };
|
|
144
167
|
};
|
|
145
168
|
|
|
169
|
+
const alert = (args) => alertHandler(args).promiseHandler;
|
|
170
|
+
const confirm = (args) => confirmHandler(args).promiseHandler;
|
|
171
|
+
const prompt = (args) => promptHandler(args).promiseHandler;
|
|
172
|
+
|
|
146
173
|
class AbstractNode {
|
|
147
174
|
id;
|
|
148
175
|
group;
|
|
@@ -150,9 +177,10 @@ class AbstractNode {
|
|
|
150
177
|
title;
|
|
151
178
|
subtitle;
|
|
152
179
|
background;
|
|
180
|
+
dimmed;
|
|
181
|
+
duration;
|
|
153
182
|
manualDestroy;
|
|
154
183
|
closeOnBackdropClick;
|
|
155
|
-
dimmed;
|
|
156
184
|
ForegroundComponent;
|
|
157
185
|
BackgroundComponent;
|
|
158
186
|
#alive;
|
|
@@ -163,9 +191,12 @@ class AbstractNode {
|
|
|
163
191
|
get visible() {
|
|
164
192
|
return this.#visible;
|
|
165
193
|
}
|
|
166
|
-
#
|
|
194
|
+
#handleResolve;
|
|
195
|
+
set handleResolve(handleResolve) {
|
|
196
|
+
this.#handleResolve = handleResolve;
|
|
197
|
+
}
|
|
167
198
|
#listeners = new Set();
|
|
168
|
-
constructor({ id, initiator, group, title, subtitle, background, dimmed = true, manualDestroy = false, closeOnBackdropClick = true,
|
|
199
|
+
constructor({ id, initiator, group, title, subtitle, background, dimmed = true, duration = 0, manualDestroy = false, closeOnBackdropClick = true, handleResolve, ForegroundComponent, BackgroundComponent, }) {
|
|
169
200
|
this.id = id;
|
|
170
201
|
this.group = group;
|
|
171
202
|
this.initiator = initiator;
|
|
@@ -173,13 +204,17 @@ class AbstractNode {
|
|
|
173
204
|
this.subtitle = subtitle;
|
|
174
205
|
this.background = background;
|
|
175
206
|
this.dimmed = dimmed;
|
|
207
|
+
this.duration = duration;
|
|
176
208
|
this.manualDestroy = manualDestroy;
|
|
177
209
|
this.closeOnBackdropClick = closeOnBackdropClick;
|
|
178
210
|
this.ForegroundComponent = ForegroundComponent;
|
|
179
211
|
this.BackgroundComponent = BackgroundComponent;
|
|
180
212
|
this.#alive = true;
|
|
181
213
|
this.#visible = true;
|
|
182
|
-
this.#
|
|
214
|
+
this.#handleResolve = handleResolve;
|
|
215
|
+
}
|
|
216
|
+
onResolve(result) {
|
|
217
|
+
this.#handleResolve?.(result);
|
|
183
218
|
}
|
|
184
219
|
subscribe(listener) {
|
|
185
220
|
this.#listeners.add(listener);
|
|
@@ -191,9 +226,6 @@ class AbstractNode {
|
|
|
191
226
|
for (const listener of this.#listeners)
|
|
192
227
|
listener();
|
|
193
228
|
}
|
|
194
|
-
resolve(result) {
|
|
195
|
-
this.#resolve(result);
|
|
196
|
-
}
|
|
197
229
|
onDestroy() {
|
|
198
230
|
const needPublish = this.#alive === true;
|
|
199
231
|
this.#alive = false;
|
|
@@ -219,7 +251,7 @@ class AlertNode extends AbstractNode {
|
|
|
219
251
|
subtype;
|
|
220
252
|
content;
|
|
221
253
|
footer;
|
|
222
|
-
constructor({ id, group, initiator, type, subtype, title, subtitle, content, footer, background, dimmed, manualDestroy, closeOnBackdropClick,
|
|
254
|
+
constructor({ id, group, initiator, type, subtype, title, subtitle, content, footer, background, dimmed, duration, manualDestroy, closeOnBackdropClick, handleResolve, ForegroundComponent, BackgroundComponent, }) {
|
|
223
255
|
super({
|
|
224
256
|
id,
|
|
225
257
|
group,
|
|
@@ -228,9 +260,10 @@ class AlertNode extends AbstractNode {
|
|
|
228
260
|
subtitle,
|
|
229
261
|
background,
|
|
230
262
|
dimmed,
|
|
263
|
+
duration,
|
|
231
264
|
manualDestroy,
|
|
232
265
|
closeOnBackdropClick,
|
|
233
|
-
|
|
266
|
+
handleResolve,
|
|
234
267
|
ForegroundComponent,
|
|
235
268
|
BackgroundComponent,
|
|
236
269
|
});
|
|
@@ -240,10 +273,10 @@ class AlertNode extends AbstractNode {
|
|
|
240
273
|
this.footer = footer;
|
|
241
274
|
}
|
|
242
275
|
onClose() {
|
|
243
|
-
this.
|
|
276
|
+
this.onResolve(null);
|
|
244
277
|
}
|
|
245
278
|
onConfirm() {
|
|
246
|
-
this.
|
|
279
|
+
this.onResolve(null);
|
|
247
280
|
}
|
|
248
281
|
}
|
|
249
282
|
|
|
@@ -252,7 +285,7 @@ class ConfirmNode extends AbstractNode {
|
|
|
252
285
|
subtype;
|
|
253
286
|
content;
|
|
254
287
|
footer;
|
|
255
|
-
constructor({ id, group, initiator, type, subtype, title, subtitle, content, footer, background, dimmed, manualDestroy, closeOnBackdropClick,
|
|
288
|
+
constructor({ id, group, initiator, type, subtype, title, subtitle, content, footer, background, dimmed, duration, manualDestroy, closeOnBackdropClick, handleResolve, ForegroundComponent, BackgroundComponent, }) {
|
|
256
289
|
super({
|
|
257
290
|
id,
|
|
258
291
|
group,
|
|
@@ -261,9 +294,10 @@ class ConfirmNode extends AbstractNode {
|
|
|
261
294
|
subtitle,
|
|
262
295
|
background,
|
|
263
296
|
dimmed,
|
|
297
|
+
duration,
|
|
264
298
|
manualDestroy,
|
|
265
299
|
closeOnBackdropClick,
|
|
266
|
-
|
|
300
|
+
handleResolve,
|
|
267
301
|
ForegroundComponent,
|
|
268
302
|
BackgroundComponent,
|
|
269
303
|
});
|
|
@@ -273,10 +307,10 @@ class ConfirmNode extends AbstractNode {
|
|
|
273
307
|
this.footer = footer;
|
|
274
308
|
}
|
|
275
309
|
onClose() {
|
|
276
|
-
this.
|
|
310
|
+
this.onResolve(false);
|
|
277
311
|
}
|
|
278
312
|
onConfirm() {
|
|
279
|
-
this.
|
|
313
|
+
this.onResolve(true);
|
|
280
314
|
}
|
|
281
315
|
}
|
|
282
316
|
|
|
@@ -289,7 +323,7 @@ class PromptNode extends AbstractNode {
|
|
|
289
323
|
returnOnCancel;
|
|
290
324
|
footer;
|
|
291
325
|
#value;
|
|
292
|
-
constructor({ id, group, initiator, type, title, subtitle, content, defaultValue, Input, disabled, returnOnCancel, footer, background, dimmed, manualDestroy, closeOnBackdropClick,
|
|
326
|
+
constructor({ id, group, initiator, type, title, subtitle, content, defaultValue, Input, disabled, returnOnCancel, footer, background, dimmed, duration, manualDestroy, closeOnBackdropClick, handleResolve, ForegroundComponent, BackgroundComponent, }) {
|
|
293
327
|
super({
|
|
294
328
|
id,
|
|
295
329
|
group,
|
|
@@ -298,9 +332,10 @@ class PromptNode extends AbstractNode {
|
|
|
298
332
|
subtitle,
|
|
299
333
|
background,
|
|
300
334
|
dimmed,
|
|
335
|
+
duration,
|
|
301
336
|
manualDestroy,
|
|
302
337
|
closeOnBackdropClick,
|
|
303
|
-
|
|
338
|
+
handleResolve,
|
|
304
339
|
ForegroundComponent,
|
|
305
340
|
BackgroundComponent,
|
|
306
341
|
});
|
|
@@ -317,13 +352,13 @@ class PromptNode extends AbstractNode {
|
|
|
317
352
|
this.#value = value;
|
|
318
353
|
}
|
|
319
354
|
onConfirm() {
|
|
320
|
-
this.
|
|
355
|
+
this.onResolve(this.#value ?? null);
|
|
321
356
|
}
|
|
322
357
|
onClose() {
|
|
323
358
|
if (this.returnOnCancel)
|
|
324
|
-
this.
|
|
359
|
+
this.onResolve(this.#value ?? null);
|
|
325
360
|
else
|
|
326
|
-
this.
|
|
361
|
+
this.onResolve(null);
|
|
327
362
|
}
|
|
328
363
|
}
|
|
329
364
|
|
|
@@ -362,8 +397,8 @@ const FallbackFooter = ({ confirmLabel, hideConfirm = false, cancelLabel, hideCa
|
|
|
362
397
|
const ModalManagerContext = createContext({});
|
|
363
398
|
|
|
364
399
|
const useModalManagerContext = () => useContext(ModalManagerContext);
|
|
365
|
-
const
|
|
366
|
-
const { getModal } =
|
|
400
|
+
const useModalManager = (id) => {
|
|
401
|
+
const { getModal } = useContext(ModalManagerContext);
|
|
367
402
|
return useMemo(() => getModal(id), [id, getModal]);
|
|
368
403
|
};
|
|
369
404
|
|
|
@@ -480,32 +515,26 @@ const ModalManagerContextProvider = memo(({ usePathname, children, }) => {
|
|
|
480
515
|
const { manualDestroy, closeOnBackdropClick } = options;
|
|
481
516
|
for (const data of ModalManager.prerender) {
|
|
482
517
|
const modal = nodeFactory({
|
|
518
|
+
duration,
|
|
519
|
+
manualDestroy,
|
|
520
|
+
closeOnBackdropClick,
|
|
483
521
|
...data,
|
|
484
522
|
id: modalIdSequence.current++,
|
|
485
523
|
initiator: initiator.current,
|
|
486
|
-
manualDestroy: data.manualDestroy !== undefined
|
|
487
|
-
? data.manualDestroy
|
|
488
|
-
: manualDestroy,
|
|
489
|
-
closeOnBackdropClick: data.closeOnBackdropClick !== undefined
|
|
490
|
-
? data.closeOnBackdropClick
|
|
491
|
-
: closeOnBackdropClick,
|
|
492
524
|
});
|
|
493
525
|
modalDictionary.current.set(modal.id, modal);
|
|
494
526
|
setModalIds((ids) => [...ids, modal.id]);
|
|
495
527
|
}
|
|
496
528
|
ModalManager.openHandler = (data) => {
|
|
497
|
-
const
|
|
529
|
+
const modalNode = nodeFactory({
|
|
530
|
+
duration,
|
|
531
|
+
manualDestroy,
|
|
532
|
+
closeOnBackdropClick,
|
|
498
533
|
...data,
|
|
499
534
|
id: modalIdSequence.current++,
|
|
500
535
|
initiator: initiator.current,
|
|
501
|
-
manualDestroy: data.manualDestroy !== undefined
|
|
502
|
-
? data.manualDestroy
|
|
503
|
-
: manualDestroy,
|
|
504
|
-
closeOnBackdropClick: data.closeOnBackdropClick !== undefined
|
|
505
|
-
? data.closeOnBackdropClick
|
|
506
|
-
: closeOnBackdropClick,
|
|
507
536
|
});
|
|
508
|
-
modalDictionary.current.set(
|
|
537
|
+
modalDictionary.current.set(modalNode.id, modalNode);
|
|
509
538
|
setModalIds((ids) => {
|
|
510
539
|
const aliveIds = [];
|
|
511
540
|
for (let i = 0, l = ids.length; i < l; i++) {
|
|
@@ -516,8 +545,9 @@ const ModalManagerContextProvider = memo(({ usePathname, children, }) => {
|
|
|
516
545
|
else
|
|
517
546
|
aliveIds.push(id);
|
|
518
547
|
}
|
|
519
|
-
return [...aliveIds,
|
|
548
|
+
return [...aliveIds, modalNode.id];
|
|
520
549
|
});
|
|
550
|
+
return modalNode;
|
|
521
551
|
};
|
|
522
552
|
});
|
|
523
553
|
useLayoutEffect(() => {
|
|
@@ -532,78 +562,62 @@ const ModalManagerContextProvider = memo(({ usePathname, children, }) => {
|
|
|
532
562
|
}
|
|
533
563
|
initiator.current = pathname;
|
|
534
564
|
}, [pathname]);
|
|
535
|
-
const
|
|
536
|
-
|
|
537
|
-
}, []);
|
|
538
|
-
const onDestroy = useCallback((modalId) => {
|
|
565
|
+
const getModalNodeRef = useRef((modalId) => modalDictionary.current.get(modalId));
|
|
566
|
+
const onDestroyRef = useRef((modalId) => {
|
|
539
567
|
const modal = modalDictionary.current.get(modalId);
|
|
540
568
|
if (!modal)
|
|
541
569
|
return;
|
|
542
570
|
modal.onDestroy();
|
|
543
|
-
|
|
544
|
-
}
|
|
545
|
-
const
|
|
546
|
-
const hideModal = useCallback((modalId) => {
|
|
571
|
+
ModalManager.refresh();
|
|
572
|
+
});
|
|
573
|
+
const hideModalRef = useRef((modalId) => {
|
|
547
574
|
const modal = modalDictionary.current.get(modalId);
|
|
548
575
|
if (!modal)
|
|
549
576
|
return;
|
|
550
577
|
modal.onHide();
|
|
551
|
-
|
|
552
|
-
if (
|
|
553
|
-
setTimeout(() =>
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
}, [duration]);
|
|
557
|
-
const onChange = useCallback((modalId, value) => {
|
|
578
|
+
ModalManager.refresh();
|
|
579
|
+
if (modal.manualDestroy === false)
|
|
580
|
+
setTimeout(() => modal.onDestroy(), modal.duration);
|
|
581
|
+
});
|
|
582
|
+
const onChangeRef = useRef((modalId, value) => {
|
|
558
583
|
const modal = modalDictionary.current.get(modalId);
|
|
559
584
|
if (!modal)
|
|
560
585
|
return;
|
|
561
586
|
if (modal.type === 'prompt')
|
|
562
587
|
modal.onChange(value);
|
|
563
|
-
}
|
|
564
|
-
const
|
|
588
|
+
});
|
|
589
|
+
const onConfirmRef = useRef((modalId) => {
|
|
565
590
|
const modal = modalDictionary.current.get(modalId);
|
|
566
591
|
if (!modal)
|
|
567
592
|
return;
|
|
568
593
|
modal.onConfirm();
|
|
569
|
-
|
|
570
|
-
}
|
|
571
|
-
const
|
|
594
|
+
hideModalRef.current(modalId);
|
|
595
|
+
});
|
|
596
|
+
const onCloseRef = useRef((modalId) => {
|
|
572
597
|
const modal = modalDictionary.current.get(modalId);
|
|
573
598
|
if (!modal)
|
|
574
599
|
return;
|
|
575
600
|
modal.onClose();
|
|
576
|
-
|
|
577
|
-
}
|
|
578
|
-
const
|
|
579
|
-
modal:
|
|
580
|
-
onConfirm: () =>
|
|
581
|
-
onClose: () =>
|
|
582
|
-
onChange: (value) =>
|
|
583
|
-
onDestroy: () =>
|
|
584
|
-
})
|
|
601
|
+
hideModalRef.current(modalId);
|
|
602
|
+
});
|
|
603
|
+
const getModalRef = useRef((modalId) => ({
|
|
604
|
+
modal: getModalNodeRef.current(modalId),
|
|
605
|
+
onConfirm: () => onConfirmRef.current(modalId),
|
|
606
|
+
onClose: () => onCloseRef.current(modalId),
|
|
607
|
+
onChange: (value) => onChangeRef.current(modalId, value),
|
|
608
|
+
onDestroy: () => onDestroyRef.current(modalId),
|
|
609
|
+
}));
|
|
585
610
|
const value = useMemo(() => {
|
|
586
611
|
return {
|
|
587
612
|
modalIds,
|
|
588
|
-
getModalNode,
|
|
589
|
-
onChange,
|
|
590
|
-
onConfirm,
|
|
591
|
-
onClose,
|
|
592
|
-
onDestroy,
|
|
593
|
-
getModal,
|
|
594
|
-
setUpdater: (updater) => {
|
|
595
|
-
updaterRef.current = updater;
|
|
596
|
-
},
|
|
613
|
+
getModalNode: getModalNodeRef.current,
|
|
614
|
+
onChange: onChangeRef.current,
|
|
615
|
+
onConfirm: onConfirmRef.current,
|
|
616
|
+
onClose: onCloseRef.current,
|
|
617
|
+
onDestroy: onDestroyRef.current,
|
|
618
|
+
getModal: getModalRef.current,
|
|
597
619
|
};
|
|
598
|
-
}, [
|
|
599
|
-
modalIds,
|
|
600
|
-
getModal,
|
|
601
|
-
getModalNode,
|
|
602
|
-
onChange,
|
|
603
|
-
onConfirm,
|
|
604
|
-
onClose,
|
|
605
|
-
onDestroy,
|
|
606
|
-
]);
|
|
620
|
+
}, [modalIds]);
|
|
607
621
|
return (jsx(ModalManagerContext.Provider, { value: value, children: children }));
|
|
608
622
|
});
|
|
609
623
|
|
|
@@ -672,7 +686,7 @@ ModalManager.defineStyleSheet('background', style$3);
|
|
|
672
686
|
const BackgroundFrame = ({ modalId, onChangeOrder, }) => {
|
|
673
687
|
const { BackgroundComponent } = useConfigurationContext();
|
|
674
688
|
const { context: userDefinedContext } = useUserDefinedContext();
|
|
675
|
-
const { modal, onClose, onChange, onConfirm, onDestroy } =
|
|
689
|
+
const { modal, onClose, onChange, onConfirm, onDestroy } = useModalManager(modalId);
|
|
676
690
|
const handleClose = useCallback((event) => {
|
|
677
691
|
if (modal && modal.closeOnBackdropClick && modal.visible)
|
|
678
692
|
onClose();
|
|
@@ -788,7 +802,7 @@ ModalManager.defineStyleSheet('foreground', style$2);
|
|
|
788
802
|
const ForegroundFrame = ({ modalId, onChangeOrder, }) => {
|
|
789
803
|
const { ForegroundComponent } = useConfigurationContext();
|
|
790
804
|
const { context: userDefinedContext } = useUserDefinedContext();
|
|
791
|
-
const { modal, onChange, onConfirm, onClose, onDestroy } =
|
|
805
|
+
const { modal, onChange, onConfirm, onClose, onDestroy } = useModalManager(modalId);
|
|
792
806
|
const Foreground = useMemo(() => modal?.ForegroundComponent || ForegroundComponent, [ForegroundComponent, modal]);
|
|
793
807
|
if (!modal)
|
|
794
808
|
return null;
|
|
@@ -820,7 +834,7 @@ ModalManager.defineStyleSheet('presenter', style$1);
|
|
|
820
834
|
const Presenter = memo(({ modalId, getValue, increment }) => {
|
|
821
835
|
const ref = useRef(null);
|
|
822
836
|
const options = useConfigurationOptions();
|
|
823
|
-
const { modal } =
|
|
837
|
+
const { modal } = useModalManager(modalId);
|
|
824
838
|
useSubscribeModal(modal);
|
|
825
839
|
useOnMountLayout(() => {
|
|
826
840
|
if (ref.current === null)
|
|
@@ -866,10 +880,10 @@ ModalManager.defineStyleSheet('backdrop', backdropStyle);
|
|
|
866
880
|
const { getValue, increment, reset } = counterFactory(0);
|
|
867
881
|
const AnchorInner = () => {
|
|
868
882
|
const [version, update] = useVersion();
|
|
869
|
-
const { modalIds
|
|
883
|
+
const { modalIds } = useModalManagerContext();
|
|
870
884
|
useEffect(() => {
|
|
871
|
-
|
|
872
|
-
}, [
|
|
885
|
+
ModalManager.refreshHandler = update;
|
|
886
|
+
}, [update]);
|
|
873
887
|
const options = useConfigurationOptions();
|
|
874
888
|
const dimmed = useActiveModalCount(validateDimmable, version);
|
|
875
889
|
if (!dimmed)
|
|
@@ -969,8 +983,39 @@ const useBootstrap = ({ usePathname: useExternalPathname, ForegroundComponent, B
|
|
|
969
983
|
return { portal, initialize };
|
|
970
984
|
};
|
|
971
985
|
|
|
986
|
+
const useModal = (configuration) => {
|
|
987
|
+
const modalNodesRef = useRef([]);
|
|
988
|
+
const baseArgsRef = useRef(configuration);
|
|
989
|
+
const alertRef = useRef((args) => {
|
|
990
|
+
const { modalNode, promiseHandler } = alertHandler(baseArgsRef.current ? { ...baseArgsRef.current, ...args } : args);
|
|
991
|
+
modalNodesRef.current.push(modalNode);
|
|
992
|
+
return promiseHandler;
|
|
993
|
+
});
|
|
994
|
+
const confirmRef = useRef((args) => {
|
|
995
|
+
const { modalNode, promiseHandler } = confirmHandler(baseArgsRef.current ? { ...baseArgsRef.current, ...args } : args);
|
|
996
|
+
modalNodesRef.current.push(modalNode);
|
|
997
|
+
return promiseHandler;
|
|
998
|
+
});
|
|
999
|
+
const promptRef = useRef((args) => {
|
|
1000
|
+
const { modalNode, promiseHandler } = promptHandler(baseArgsRef.current ? { ...baseArgsRef.current, ...args } : args);
|
|
1001
|
+
modalNodesRef.current.push(modalNode);
|
|
1002
|
+
return promiseHandler;
|
|
1003
|
+
});
|
|
1004
|
+
useOnUnmount(() => {
|
|
1005
|
+
for (const node of modalNodesRef.current)
|
|
1006
|
+
closeModal(node, false);
|
|
1007
|
+
ModalManager.refresh();
|
|
1008
|
+
modalNodesRef.current = [];
|
|
1009
|
+
});
|
|
1010
|
+
return {
|
|
1011
|
+
alert: alertRef.current,
|
|
1012
|
+
confirm: confirmRef.current,
|
|
1013
|
+
prompt: promptRef.current,
|
|
1014
|
+
};
|
|
1015
|
+
};
|
|
1016
|
+
|
|
972
1017
|
const useDestroyAfter = (modalId, duration) => {
|
|
973
|
-
const { modal, onDestroy } =
|
|
1018
|
+
const { modal, onDestroy } = useModalManager(modalId);
|
|
974
1019
|
const tick = useSubscribeModal(modal);
|
|
975
1020
|
const reference = useRef({
|
|
976
1021
|
modal,
|
|
@@ -1011,4 +1056,15 @@ const useModalAnimation = (visible, handler) => {
|
|
|
1011
1056
|
}, [visible]);
|
|
1012
1057
|
};
|
|
1013
1058
|
|
|
1014
|
-
|
|
1059
|
+
const useModalDuration = (id) => {
|
|
1060
|
+
const globalDuration = useConfigurationDuration();
|
|
1061
|
+
if (id === undefined)
|
|
1062
|
+
return globalDuration;
|
|
1063
|
+
const { modal } = useModalManager(id);
|
|
1064
|
+
if (modal === undefined)
|
|
1065
|
+
return globalDuration;
|
|
1066
|
+
const duration = modal.duration;
|
|
1067
|
+
return { duration, milliseconds: duration + 'ms' };
|
|
1068
|
+
};
|
|
1069
|
+
|
|
1070
|
+
export { BootstrapProvider as ModalProvider, alert, confirm, prompt, useActiveModalCount, useDestroyAfter, useBootstrap as useInitializeModal, useModal, useModalAnimation, useConfigurationBackdrop as useModalBackdrop, useModalDuration, useConfigurationOptions as useModalOptions, useSubscribeModal };
|
|
@@ -5,6 +5,5 @@ export interface ModalManagerContextProps extends ModalHandlersWithId {
|
|
|
5
5
|
modalIds: ModalNode['id'][];
|
|
6
6
|
getModal: Fn<[id: ModalNode['id']], ModalActions>;
|
|
7
7
|
getModalNode: Fn<[id: ModalNode['id']], ModalNode | undefined>;
|
|
8
|
-
setUpdater: Fn<[updater: Fn]>;
|
|
9
8
|
}
|
|
10
9
|
export declare const ModalManagerContext: import("react").Context<ModalManagerContextProps>;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
export { ModalManagerContextProvider } from './ModalManagerContextProvider';
|
|
2
|
-
export { useModalManagerContext,
|
|
2
|
+
export { useModalManagerContext, useModalManager, } from './useModalManagerContext';
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import type { ManagedModal } from '../../types';
|
|
2
2
|
export declare const useModalManagerContext: () => import("./ModalManagerContext").ModalManagerContextProps;
|
|
3
|
-
export declare const
|
|
3
|
+
export declare const useModalManager: (id: ManagedModal["id"]) => import("../../types").ModalActions;
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export { useModalManagerContext,
|
|
1
|
+
export { useModalManagerContext, useModalManager } from './ModalManagerContext';
|
|
2
2
|
export { useConfigurationContext, useConfigurationOptions, useConfigurationDuration, useConfigurationBackdrop, } from './ConfigurationContext';
|
|
3
3
|
export { useUserDefinedContext } from './UserDefinedContext';
|
package/dist/types/base.d.ts
CHANGED
|
@@ -8,9 +8,10 @@ export interface BaseModal<T, B> {
|
|
|
8
8
|
subtitle?: ReactNode;
|
|
9
9
|
background?: ModalBackground<B>;
|
|
10
10
|
dimmed?: boolean;
|
|
11
|
+
duration?: number;
|
|
11
12
|
manualDestroy?: boolean;
|
|
12
13
|
closeOnBackdropClick?: boolean;
|
|
13
|
-
|
|
14
|
+
handleResolve?: Fn<[result: T | null]>;
|
|
14
15
|
ForegroundComponent?: ForegroundComponent;
|
|
15
16
|
BackgroundComponent?: BackgroundComponent;
|
|
16
17
|
}
|