@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.
Files changed (149) hide show
  1. package/dist/app/ModalManager.d.ts +0 -1
  2. package/dist/app/constant.d.ts +0 -1
  3. package/dist/bootstrap/BootstrapProvider/BootstrapProvider.d.ts +0 -1
  4. package/dist/bootstrap/BootstrapProvider/helpers/bootstrap.d.ts +0 -1
  5. package/dist/bootstrap/BootstrapProvider/hooks/useInitialize.d.ts +0 -1
  6. package/dist/bootstrap/BootstrapProvider/index.d.ts +0 -1
  7. package/dist/bootstrap/BootstrapProvider/type.d.ts +0 -1
  8. package/dist/bootstrap/BootstrapProvider/useBootstrap.d.ts +0 -1
  9. package/dist/bootstrap/index.d.ts +0 -1
  10. package/dist/components/Anchor/Anchor.d.ts +0 -1
  11. package/dist/components/Anchor/classNames.emotion.d.ts +0 -1
  12. package/dist/components/Anchor/index.d.ts +0 -1
  13. package/dist/components/Background/Background.d.ts +0 -1
  14. package/dist/components/Background/classNames.emotion.d.ts +0 -1
  15. package/dist/components/Background/index.d.ts +0 -1
  16. package/dist/components/FallbackComponents/FallbackContent.d.ts +0 -1
  17. package/dist/components/FallbackComponents/FallbackFooter.d.ts +0 -1
  18. package/dist/components/FallbackComponents/FallbackForegroundFrame.d.ts +0 -1
  19. package/dist/components/FallbackComponents/FallbackSubtitle.d.ts +0 -1
  20. package/dist/components/FallbackComponents/FallbackTitle.d.ts +0 -1
  21. package/dist/components/FallbackComponents/classNames.emotion.d.ts +0 -1
  22. package/dist/components/FallbackComponents/index.d.ts +0 -1
  23. package/dist/components/Foreground/Foreground.d.ts +0 -1
  24. package/dist/components/Foreground/classNames.emotion.d.ts +0 -1
  25. package/dist/components/Foreground/components/AlertInner.d.ts +0 -1
  26. package/dist/components/Foreground/components/ConfirmInner.d.ts +0 -1
  27. package/dist/components/Foreground/components/PromptInner.d.ts +0 -1
  28. package/dist/components/Foreground/components/index.d.ts +0 -1
  29. package/dist/components/Foreground/index.d.ts +0 -1
  30. package/dist/components/Presenter/Presenter.d.ts +0 -1
  31. package/dist/components/Presenter/classNames.emotion.d.ts +0 -1
  32. package/dist/components/Presenter/index.d.ts +0 -1
  33. package/dist/core/handle/alert.d.ts +0 -1
  34. package/dist/core/handle/confirm.d.ts +0 -1
  35. package/dist/core/handle/index.d.ts +0 -1
  36. package/dist/core/handle/prompt.d.ts +0 -1
  37. package/dist/core/index.d.ts +0 -1
  38. package/dist/core/node/ModalNode/AbstractNode.d.ts +0 -1
  39. package/dist/core/node/ModalNode/AlertNode.d.ts +0 -1
  40. package/dist/core/node/ModalNode/ConfirmNode.d.ts +0 -1
  41. package/dist/core/node/ModalNode/PromptNode.d.ts +0 -1
  42. package/dist/core/node/ModalNode/index.d.ts +0 -1
  43. package/dist/core/node/index.d.ts +0 -1
  44. package/dist/core/node/nodeFactory.d.ts +0 -1
  45. package/dist/core/node/type.d.ts +0 -1
  46. package/dist/hooks/useActiveModalCount.d.ts +0 -1
  47. package/dist/hooks/useDefaultPathname.d.ts +0 -1
  48. package/dist/hooks/useDestroyAfter.d.ts +0 -1
  49. package/dist/hooks/useModalAnimation.d.ts +0 -1
  50. package/dist/hooks/useSubscribeModal.d.ts +0 -1
  51. package/dist/index.cjs +966 -0
  52. package/dist/index.d.ts +0 -1
  53. package/dist/index.mjs +953 -0
  54. package/dist/providers/ConfigurationContext/ConfigurationContext.d.ts +0 -1
  55. package/dist/providers/ConfigurationContext/ConfigurationContextProvider.d.ts +4 -1
  56. package/dist/providers/ConfigurationContext/index.d.ts +0 -1
  57. package/dist/providers/ConfigurationContext/useConfigurationContext.d.ts +0 -1
  58. package/dist/providers/ModalManagerContext/ModalManagerContext.d.ts +0 -1
  59. package/dist/providers/ModalManagerContext/ModalManagerContextProvider.d.ts +0 -1
  60. package/dist/providers/ModalManagerContext/index.d.ts +0 -1
  61. package/dist/providers/ModalManagerContext/useModalManagerContext.d.ts +0 -1
  62. package/dist/providers/UserDefinedContext/UserDefinedContext.d.ts +0 -1
  63. package/dist/providers/UserDefinedContext/UserDefinedContextProvider.d.ts +2 -2
  64. package/dist/providers/UserDefinedContext/index.d.ts +0 -1
  65. package/dist/providers/UserDefinedContext/useUserDefinedContext.d.ts +0 -1
  66. package/dist/providers/index.d.ts +0 -1
  67. package/dist/types/alert.d.ts +0 -1
  68. package/dist/types/background.d.ts +0 -1
  69. package/dist/types/base.d.ts +0 -1
  70. package/dist/types/confirm.d.ts +0 -1
  71. package/dist/types/index.d.ts +0 -1
  72. package/dist/types/modal.d.ts +0 -1
  73. package/dist/types/prompt.d.ts +0 -1
  74. package/package.json +19 -31
  75. package/dist/app/ModalManager.d.ts.map +0 -1
  76. package/dist/app/constant.d.ts.map +0 -1
  77. package/dist/bootstrap/BootstrapProvider/BootstrapProvider.d.ts.map +0 -1
  78. package/dist/bootstrap/BootstrapProvider/helpers/bootstrap.d.ts.map +0 -1
  79. package/dist/bootstrap/BootstrapProvider/hooks/useInitialize.d.ts.map +0 -1
  80. package/dist/bootstrap/BootstrapProvider/index.d.ts.map +0 -1
  81. package/dist/bootstrap/BootstrapProvider/type.d.ts.map +0 -1
  82. package/dist/bootstrap/BootstrapProvider/useBootstrap.d.ts.map +0 -1
  83. package/dist/bootstrap/index.d.ts.map +0 -1
  84. package/dist/components/Anchor/Anchor.d.ts.map +0 -1
  85. package/dist/components/Anchor/classNames.emotion.d.ts.map +0 -1
  86. package/dist/components/Anchor/index.d.ts.map +0 -1
  87. package/dist/components/Background/Background.d.ts.map +0 -1
  88. package/dist/components/Background/classNames.emotion.d.ts.map +0 -1
  89. package/dist/components/Background/index.d.ts.map +0 -1
  90. package/dist/components/FallbackComponents/FallbackContent.d.ts.map +0 -1
  91. package/dist/components/FallbackComponents/FallbackFooter.d.ts.map +0 -1
  92. package/dist/components/FallbackComponents/FallbackForegroundFrame.d.ts.map +0 -1
  93. package/dist/components/FallbackComponents/FallbackSubtitle.d.ts.map +0 -1
  94. package/dist/components/FallbackComponents/FallbackTitle.d.ts.map +0 -1
  95. package/dist/components/FallbackComponents/classNames.emotion.d.ts.map +0 -1
  96. package/dist/components/FallbackComponents/index.d.ts.map +0 -1
  97. package/dist/components/Foreground/Foreground.d.ts.map +0 -1
  98. package/dist/components/Foreground/classNames.emotion.d.ts.map +0 -1
  99. package/dist/components/Foreground/components/AlertInner.d.ts.map +0 -1
  100. package/dist/components/Foreground/components/ConfirmInner.d.ts.map +0 -1
  101. package/dist/components/Foreground/components/PromptInner.d.ts.map +0 -1
  102. package/dist/components/Foreground/components/index.d.ts.map +0 -1
  103. package/dist/components/Foreground/index.d.ts.map +0 -1
  104. package/dist/components/Presenter/Presenter.d.ts.map +0 -1
  105. package/dist/components/Presenter/classNames.emotion.d.ts.map +0 -1
  106. package/dist/components/Presenter/index.d.ts.map +0 -1
  107. package/dist/core/handle/alert.d.ts.map +0 -1
  108. package/dist/core/handle/confirm.d.ts.map +0 -1
  109. package/dist/core/handle/index.d.ts.map +0 -1
  110. package/dist/core/handle/prompt.d.ts.map +0 -1
  111. package/dist/core/index.d.ts.map +0 -1
  112. package/dist/core/node/ModalNode/AbstractNode.d.ts.map +0 -1
  113. package/dist/core/node/ModalNode/AlertNode.d.ts.map +0 -1
  114. package/dist/core/node/ModalNode/ConfirmNode.d.ts.map +0 -1
  115. package/dist/core/node/ModalNode/PromptNode.d.ts.map +0 -1
  116. package/dist/core/node/ModalNode/index.d.ts.map +0 -1
  117. package/dist/core/node/index.d.ts.map +0 -1
  118. package/dist/core/node/nodeFactory.d.ts.map +0 -1
  119. package/dist/core/node/type.d.ts.map +0 -1
  120. package/dist/hooks/useActiveModalCount.d.ts.map +0 -1
  121. package/dist/hooks/useDefaultPathname.d.ts.map +0 -1
  122. package/dist/hooks/useDestroyAfter.d.ts.map +0 -1
  123. package/dist/hooks/useModalAnimation.d.ts.map +0 -1
  124. package/dist/hooks/useSubscribeModal.d.ts.map +0 -1
  125. package/dist/index.cjs.js +0 -2
  126. package/dist/index.cjs.js.map +0 -1
  127. package/dist/index.d.ts.map +0 -1
  128. package/dist/index.esm.js +0 -2
  129. package/dist/index.esm.js.map +0 -1
  130. package/dist/providers/ConfigurationContext/ConfigurationContext.d.ts.map +0 -1
  131. package/dist/providers/ConfigurationContext/ConfigurationContextProvider.d.ts.map +0 -1
  132. package/dist/providers/ConfigurationContext/index.d.ts.map +0 -1
  133. package/dist/providers/ConfigurationContext/useConfigurationContext.d.ts.map +0 -1
  134. package/dist/providers/ModalManagerContext/ModalManagerContext.d.ts.map +0 -1
  135. package/dist/providers/ModalManagerContext/ModalManagerContextProvider.d.ts.map +0 -1
  136. package/dist/providers/ModalManagerContext/index.d.ts.map +0 -1
  137. package/dist/providers/ModalManagerContext/useModalManagerContext.d.ts.map +0 -1
  138. package/dist/providers/UserDefinedContext/UserDefinedContext.d.ts.map +0 -1
  139. package/dist/providers/UserDefinedContext/UserDefinedContextProvider.d.ts.map +0 -1
  140. package/dist/providers/UserDefinedContext/index.d.ts.map +0 -1
  141. package/dist/providers/UserDefinedContext/useUserDefinedContext.d.ts.map +0 -1
  142. package/dist/providers/index.d.ts.map +0 -1
  143. package/dist/types/alert.d.ts.map +0 -1
  144. package/dist/types/background.d.ts.map +0 -1
  145. package/dist/types/base.d.ts.map +0 -1
  146. package/dist/types/confirm.d.ts.map +0 -1
  147. package/dist/types/index.d.ts.map +0 -1
  148. package/dist/types/modal.d.ts.map +0 -1
  149. 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;