@lerx/promise-modal 0.2.1 → 0.2.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/app/ModalManager.d.ts +3 -0
- package/dist/bootstrap/BootstrapProvider/hooks/useInitialize.d.ts +1 -0
- package/dist/core/handle/alert.d.ts +2 -1
- package/dist/core/handle/confirm.d.ts +2 -1
- package/dist/core/handle/prompt.d.ts +3 -2
- package/dist/core/node/ModalNode/AbstractNode.d.ts +2 -1
- package/dist/core/node/ModalNode/AlertNode.d.ts +1 -1
- package/dist/core/node/ModalNode/ConfirmNode.d.ts +1 -1
- package/dist/core/node/ModalNode/PromptNode.d.ts +1 -1
- package/dist/hooks/useActiveModalCount.d.ts +1 -1
- package/dist/index.cjs +121 -78
- package/dist/index.mjs +119 -76
- package/dist/types/base.d.ts +1 -0
- package/package.json +4 -4
- package/dist/components/FallbackComponents/classNames.emotion.d.ts +0 -2
- /package/dist/components/Anchor/{classNames.emotion.d.ts → style.d.ts} +0 -0
- /package/dist/components/Background/{classNames.emotion.d.ts → style.d.ts} +0 -0
- /package/dist/components/Foreground/{classNames.emotion.d.ts → style.d.ts} +0 -0
- /package/dist/components/Presenter/{classNames.emotion.d.ts → style.d.ts} +0 -0
|
@@ -11,6 +11,9 @@ export declare class ModalManager {
|
|
|
11
11
|
static get prerender(): Modal[];
|
|
12
12
|
static set openHandler(handler: Fn<[Modal], void>);
|
|
13
13
|
static get unanchored(): boolean;
|
|
14
|
+
static defineStyleSheet(styleId: string, css: string): void;
|
|
15
|
+
static applyStyleSheet(): void;
|
|
16
|
+
static getHashedClassNames(styleId: string): string;
|
|
14
17
|
static reset(): void;
|
|
15
18
|
static open(modal: Modal): void;
|
|
16
19
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { ComponentType, ReactNode } from 'react';
|
|
2
2
|
import type { AlertContentProps, AlertFooterRender, BackgroundComponent, FooterOptions, ForegroundComponent, ModalBackground } from '../../types';
|
|
3
3
|
interface AlertProps<B> {
|
|
4
|
+
group?: string;
|
|
4
5
|
subtype?: 'info' | 'success' | 'warning' | 'error';
|
|
5
6
|
title?: ReactNode;
|
|
6
7
|
subtitle?: ReactNode;
|
|
@@ -13,5 +14,5 @@ interface AlertProps<B> {
|
|
|
13
14
|
ForegroundComponent?: ForegroundComponent;
|
|
14
15
|
BackgroundComponent?: BackgroundComponent;
|
|
15
16
|
}
|
|
16
|
-
export declare const alert: <B = any>({ subtype, title, subtitle, content, background, footer, dimmed, manualDestroy, closeOnBackdropClick, ForegroundComponent, BackgroundComponent, }: AlertProps<B>) => Promise<void>;
|
|
17
|
+
export declare const alert: <B = any>({ group, subtype, title, subtitle, content, background, footer, dimmed, manualDestroy, closeOnBackdropClick, ForegroundComponent, BackgroundComponent, }: AlertProps<B>) => Promise<void>;
|
|
17
18
|
export {};
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { ComponentType, ReactNode } from 'react';
|
|
2
2
|
import type { BackgroundComponent, ConfirmContentProps, ConfirmFooterRender, FooterOptions, ForegroundComponent, ModalBackground } from '../../types';
|
|
3
3
|
interface ConfirmProps<B> {
|
|
4
|
+
group?: string;
|
|
4
5
|
subtype?: 'info' | 'success' | 'warning' | 'error';
|
|
5
6
|
title?: ReactNode;
|
|
6
7
|
subtitle?: ReactNode;
|
|
@@ -13,5 +14,5 @@ interface ConfirmProps<B> {
|
|
|
13
14
|
ForegroundComponent?: ForegroundComponent;
|
|
14
15
|
BackgroundComponent?: BackgroundComponent;
|
|
15
16
|
}
|
|
16
|
-
export declare const confirm: <B = any>({ subtype, title, subtitle, content, background, footer, dimmed, manualDestroy, closeOnBackdropClick, ForegroundComponent, BackgroundComponent, }: ConfirmProps<B>) => Promise<boolean>;
|
|
17
|
+
export declare const confirm: <B = any>({ group, subtype, title, subtitle, content, background, footer, dimmed, manualDestroy, closeOnBackdropClick, ForegroundComponent, BackgroundComponent, }: ConfirmProps<B>) => Promise<boolean>;
|
|
17
18
|
export {};
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import type { ComponentType, ReactNode } from 'react';
|
|
2
2
|
import type { BackgroundComponent, FooterOptions, ForegroundComponent, ModalBackground, PromptContentProps, PromptFooterRender, PromptInputProps } from '../../types';
|
|
3
3
|
interface PromptProps<T, B = any> {
|
|
4
|
+
group?: string;
|
|
4
5
|
title?: ReactNode;
|
|
5
6
|
subtitle?: ReactNode;
|
|
6
7
|
content?: ReactNode | ComponentType<PromptContentProps>;
|
|
7
|
-
Input: (props: PromptInputProps<T>) => ReactNode;
|
|
8
8
|
defaultValue?: T;
|
|
9
|
+
Input: (props: PromptInputProps<T>) => ReactNode;
|
|
9
10
|
disabled?: (value: T) => boolean;
|
|
10
11
|
returnOnCancel?: boolean;
|
|
11
12
|
background?: ModalBackground<B>;
|
|
@@ -16,5 +17,5 @@ interface PromptProps<T, B = any> {
|
|
|
16
17
|
ForegroundComponent?: ForegroundComponent;
|
|
17
18
|
BackgroundComponent?: BackgroundComponent;
|
|
18
19
|
}
|
|
19
|
-
export declare const prompt: <T, B = any>({
|
|
20
|
+
export declare const prompt: <T, B = any>({ group, title, subtitle, content, defaultValue, Input, disabled, returnOnCancel, background, footer, dimmed, manualDestroy, closeOnBackdropClick, ForegroundComponent, BackgroundComponent, }: PromptProps<T, B>) => Promise<T>;
|
|
20
21
|
export {};
|
|
@@ -5,6 +5,7 @@ type AbstractNodeProps<T, B> = BaseModal<T, B> & ManagedEntity;
|
|
|
5
5
|
export declare abstract class AbstractNode<T, B> {
|
|
6
6
|
#private;
|
|
7
7
|
readonly id: number;
|
|
8
|
+
readonly group?: string;
|
|
8
9
|
readonly initiator: string;
|
|
9
10
|
readonly title?: ReactNode;
|
|
10
11
|
readonly subtitle?: ReactNode;
|
|
@@ -16,7 +17,7 @@ export declare abstract class AbstractNode<T, B> {
|
|
|
16
17
|
readonly BackgroundComponent?: BackgroundComponent;
|
|
17
18
|
get alive(): boolean;
|
|
18
19
|
get visible(): boolean;
|
|
19
|
-
constructor({ id, initiator, title, subtitle, background, dimmed, manualDestroy, closeOnBackdropClick, resolve, ForegroundComponent, BackgroundComponent, }: AbstractNodeProps<T, B>);
|
|
20
|
+
constructor({ id, initiator, group, title, subtitle, background, dimmed, manualDestroy, closeOnBackdropClick, resolve, ForegroundComponent, BackgroundComponent, }: AbstractNodeProps<T, B>);
|
|
20
21
|
subscribe(listener: Fn): () => void;
|
|
21
22
|
publish(): void;
|
|
22
23
|
protected resolve(result: T | null): void;
|
|
@@ -7,7 +7,7 @@ export declare class AlertNode<B> extends AbstractNode<null, B> {
|
|
|
7
7
|
readonly subtype?: 'info' | 'success' | 'warning' | 'error';
|
|
8
8
|
readonly content?: ReactNode | ComponentType<AlertContentProps>;
|
|
9
9
|
readonly footer?: AlertFooterRender | Pick<FooterOptions, 'confirm' | 'hideConfirm'> | false;
|
|
10
|
-
constructor({ id, initiator, type, subtype, title, subtitle, content, footer, background, dimmed, manualDestroy, closeOnBackdropClick, resolve, ForegroundComponent, BackgroundComponent, }: AlertNodeProps<B>);
|
|
10
|
+
constructor({ id, group, initiator, type, subtype, title, subtitle, content, footer, background, dimmed, manualDestroy, closeOnBackdropClick, resolve, ForegroundComponent, BackgroundComponent, }: AlertNodeProps<B>);
|
|
11
11
|
onClose(): void;
|
|
12
12
|
onConfirm(): void;
|
|
13
13
|
}
|
|
@@ -7,7 +7,7 @@ export declare class ConfirmNode<B> extends AbstractNode<boolean, B> {
|
|
|
7
7
|
readonly subtype?: 'info' | 'success' | 'warning' | 'error';
|
|
8
8
|
readonly content?: ReactNode | ComponentType<ConfirmContentProps>;
|
|
9
9
|
readonly footer?: ConfirmFooterRender | FooterOptions | false;
|
|
10
|
-
constructor({ id, initiator, type, subtype, title, subtitle, content, footer, background, dimmed, manualDestroy, closeOnBackdropClick, resolve, ForegroundComponent, BackgroundComponent, }: ConfirmNodeProps<B>);
|
|
10
|
+
constructor({ id, group, initiator, type, subtype, title, subtitle, content, footer, background, dimmed, manualDestroy, closeOnBackdropClick, resolve, ForegroundComponent, BackgroundComponent, }: ConfirmNodeProps<B>);
|
|
11
11
|
onClose(): void;
|
|
12
12
|
onConfirm(): void;
|
|
13
13
|
}
|
|
@@ -11,7 +11,7 @@ export declare class PromptNode<T, B> extends AbstractNode<T, B> {
|
|
|
11
11
|
readonly disabled?: (value: T) => boolean;
|
|
12
12
|
readonly returnOnCancel?: boolean;
|
|
13
13
|
readonly footer?: PromptFooterRender<T> | FooterOptions | false;
|
|
14
|
-
constructor({ id, initiator, type, title, subtitle, content, defaultValue, Input, disabled, returnOnCancel, footer, background, dimmed, manualDestroy, closeOnBackdropClick, resolve, ForegroundComponent, BackgroundComponent, }: PromptNodeProps<T, B>);
|
|
14
|
+
constructor({ id, group, initiator, type, title, subtitle, content, defaultValue, Input, disabled, returnOnCancel, footer, background, dimmed, manualDestroy, closeOnBackdropClick, resolve, ForegroundComponent, BackgroundComponent, }: PromptNodeProps<T, B>);
|
|
15
15
|
onChange(value: T): void;
|
|
16
16
|
onConfirm(): void;
|
|
17
17
|
onClose(): void;
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import type { Fn } from '../@aileron/declare';
|
|
2
2
|
import type { ModalNode } from '../core';
|
|
3
|
-
export declare const useActiveModalCount: (validate?: Fn<[ModalNode
|
|
3
|
+
export declare const useActiveModalCount: (validate?: Fn<[node?: ModalNode], boolean | undefined>, refreshKey?: string | number) => number;
|
package/dist/index.cjs
CHANGED
|
@@ -4,11 +4,14 @@ const jsxRuntime = require('react/jsx-runtime');
|
|
|
4
4
|
const react = require('react');
|
|
5
5
|
const convert = require('@winglet/common-utils/convert');
|
|
6
6
|
const hook = require('@winglet/react-utils/hook');
|
|
7
|
+
const hash = require('@winglet/common-utils/hash');
|
|
7
8
|
const lib = require('@winglet/common-utils/lib');
|
|
8
|
-
const
|
|
9
|
+
const compressCss = require('@winglet/style-utils/compressCss');
|
|
10
|
+
const styleManager = require('@winglet/style-utils/styleManager');
|
|
9
11
|
const reactDom = require('react-dom');
|
|
10
12
|
const array = require('@winglet/common-utils/array');
|
|
11
13
|
const hoc = require('@winglet/react-utils/hoc');
|
|
14
|
+
const styleUtils = require('@winglet/style-utils');
|
|
12
15
|
const filter = require('@winglet/common-utils/filter');
|
|
13
16
|
const render = require('@winglet/react-utils/render');
|
|
14
17
|
const console = require('@winglet/common-utils/console');
|
|
@@ -21,15 +24,15 @@ class ModalManager {
|
|
|
21
24
|
return (ModalManager.#active = true);
|
|
22
25
|
}
|
|
23
26
|
static #anchor = null;
|
|
27
|
+
static #scope = `promise-modal-${lib.getRandomString(36)}`;
|
|
28
|
+
static #hash = hash.polynomialHash(ModalManager.#scope);
|
|
24
29
|
static anchor(options) {
|
|
25
|
-
if (ModalManager.#anchor)
|
|
26
|
-
|
|
27
|
-
if (anchor)
|
|
28
|
-
return anchor;
|
|
29
|
-
}
|
|
30
|
+
if (ModalManager.#anchor)
|
|
31
|
+
return ModalManager.#anchor;
|
|
30
32
|
const { tag = 'div', prefix = 'promise-modal', root = document.body, } = options || {};
|
|
31
33
|
const node = document.createElement(tag);
|
|
32
|
-
node.
|
|
34
|
+
node.id = `${prefix}-${lib.getRandomString(36)}`;
|
|
35
|
+
node.className = ModalManager.#scope;
|
|
33
36
|
root.appendChild(node);
|
|
34
37
|
ModalManager.#anchor = node;
|
|
35
38
|
return node;
|
|
@@ -46,22 +49,36 @@ class ModalManager {
|
|
|
46
49
|
static get unanchored() {
|
|
47
50
|
return !ModalManager.#anchor;
|
|
48
51
|
}
|
|
52
|
+
static #styleManager = styleManager.styleManagerFactory(ModalManager.#scope);
|
|
53
|
+
static #styleSheetDefinition = new Map();
|
|
54
|
+
static defineStyleSheet(styleId, css) {
|
|
55
|
+
ModalManager.#styleSheetDefinition.set(styleId, compressCss.compressCss(css));
|
|
56
|
+
}
|
|
57
|
+
static applyStyleSheet() {
|
|
58
|
+
for (const [styleId, css] of ModalManager.#styleSheetDefinition)
|
|
59
|
+
ModalManager.#styleManager(styleId, css, true);
|
|
60
|
+
}
|
|
61
|
+
static getHashedClassNames(styleId) {
|
|
62
|
+
return `${styleId}-${ModalManager.#hash}`;
|
|
63
|
+
}
|
|
49
64
|
static reset() {
|
|
50
65
|
ModalManager.#active = false;
|
|
51
66
|
ModalManager.#anchor = null;
|
|
52
67
|
ModalManager.#prerenderList = [];
|
|
53
68
|
ModalManager.#openHandler = (modal) => ModalManager.#prerenderList.push(modal);
|
|
69
|
+
styleManager.destroyScope(ModalManager.#scope);
|
|
54
70
|
}
|
|
55
71
|
static open(modal) {
|
|
56
72
|
ModalManager.#openHandler(modal);
|
|
57
73
|
}
|
|
58
74
|
}
|
|
59
75
|
|
|
60
|
-
const alert = ({ subtype, title, subtitle, content, background, footer, dimmed, manualDestroy, closeOnBackdropClick, ForegroundComponent, BackgroundComponent, }) => {
|
|
76
|
+
const alert = ({ group, subtype, title, subtitle, content, background, footer, dimmed, manualDestroy, closeOnBackdropClick, ForegroundComponent, BackgroundComponent, }) => {
|
|
61
77
|
return new Promise((resolve, reject) => {
|
|
62
78
|
try {
|
|
63
79
|
ModalManager.open({
|
|
64
80
|
type: 'alert',
|
|
81
|
+
group,
|
|
65
82
|
subtype,
|
|
66
83
|
resolve: () => resolve(),
|
|
67
84
|
title,
|
|
@@ -82,11 +99,12 @@ const alert = ({ subtype, title, subtitle, content, background, footer, dimmed,
|
|
|
82
99
|
});
|
|
83
100
|
};
|
|
84
101
|
|
|
85
|
-
const confirm = ({ subtype, title, subtitle, content, background, footer, dimmed, manualDestroy, closeOnBackdropClick, ForegroundComponent, BackgroundComponent, }) => {
|
|
102
|
+
const confirm = ({ group, subtype, title, subtitle, content, background, footer, dimmed, manualDestroy, closeOnBackdropClick, ForegroundComponent, BackgroundComponent, }) => {
|
|
86
103
|
return new Promise((resolve, reject) => {
|
|
87
104
|
try {
|
|
88
105
|
ModalManager.open({
|
|
89
106
|
type: 'confirm',
|
|
107
|
+
group,
|
|
90
108
|
subtype,
|
|
91
109
|
resolve: (result) => resolve(result ?? false),
|
|
92
110
|
title,
|
|
@@ -107,11 +125,12 @@ const confirm = ({ subtype, title, subtitle, content, background, footer, dimmed
|
|
|
107
125
|
});
|
|
108
126
|
};
|
|
109
127
|
|
|
110
|
-
const prompt = ({
|
|
128
|
+
const prompt = ({ group, title, subtitle, content, defaultValue, Input, disabled, returnOnCancel, background, footer, dimmed, manualDestroy, closeOnBackdropClick, ForegroundComponent, BackgroundComponent, }) => {
|
|
111
129
|
return new Promise((resolve, reject) => {
|
|
112
130
|
try {
|
|
113
131
|
ModalManager.open({
|
|
114
132
|
type: 'prompt',
|
|
133
|
+
group,
|
|
115
134
|
resolve: (result) => resolve(result),
|
|
116
135
|
title,
|
|
117
136
|
subtitle,
|
|
@@ -137,6 +156,7 @@ const prompt = ({ defaultValue, title, subtitle, content, Input, disabled, retur
|
|
|
137
156
|
|
|
138
157
|
class AbstractNode {
|
|
139
158
|
id;
|
|
159
|
+
group;
|
|
140
160
|
initiator;
|
|
141
161
|
title;
|
|
142
162
|
subtitle;
|
|
@@ -156,8 +176,9 @@ class AbstractNode {
|
|
|
156
176
|
}
|
|
157
177
|
#resolve;
|
|
158
178
|
#listeners = new Set();
|
|
159
|
-
constructor({ id, initiator, title, subtitle, background, dimmed = true, manualDestroy = false, closeOnBackdropClick = true, resolve, ForegroundComponent, BackgroundComponent, }) {
|
|
179
|
+
constructor({ id, initiator, group, title, subtitle, background, dimmed = true, manualDestroy = false, closeOnBackdropClick = true, resolve, ForegroundComponent, BackgroundComponent, }) {
|
|
160
180
|
this.id = id;
|
|
181
|
+
this.group = group;
|
|
161
182
|
this.initiator = initiator;
|
|
162
183
|
this.title = title;
|
|
163
184
|
this.subtitle = subtitle;
|
|
@@ -209,9 +230,10 @@ class AlertNode extends AbstractNode {
|
|
|
209
230
|
subtype;
|
|
210
231
|
content;
|
|
211
232
|
footer;
|
|
212
|
-
constructor({ id, initiator, type, subtype, title, subtitle, content, footer, background, dimmed, manualDestroy, closeOnBackdropClick, resolve, ForegroundComponent, BackgroundComponent, }) {
|
|
233
|
+
constructor({ id, group, initiator, type, subtype, title, subtitle, content, footer, background, dimmed, manualDestroy, closeOnBackdropClick, resolve, ForegroundComponent, BackgroundComponent, }) {
|
|
213
234
|
super({
|
|
214
235
|
id,
|
|
236
|
+
group,
|
|
215
237
|
initiator,
|
|
216
238
|
title,
|
|
217
239
|
subtitle,
|
|
@@ -241,9 +263,10 @@ class ConfirmNode extends AbstractNode {
|
|
|
241
263
|
subtype;
|
|
242
264
|
content;
|
|
243
265
|
footer;
|
|
244
|
-
constructor({ id, initiator, type, subtype, title, subtitle, content, footer, background, dimmed, manualDestroy, closeOnBackdropClick, resolve, ForegroundComponent, BackgroundComponent, }) {
|
|
266
|
+
constructor({ id, group, initiator, type, subtype, title, subtitle, content, footer, background, dimmed, manualDestroy, closeOnBackdropClick, resolve, ForegroundComponent, BackgroundComponent, }) {
|
|
245
267
|
super({
|
|
246
268
|
id,
|
|
269
|
+
group,
|
|
247
270
|
initiator,
|
|
248
271
|
title,
|
|
249
272
|
subtitle,
|
|
@@ -277,9 +300,10 @@ class PromptNode extends AbstractNode {
|
|
|
277
300
|
returnOnCancel;
|
|
278
301
|
footer;
|
|
279
302
|
#value;
|
|
280
|
-
constructor({ id, initiator, type, title, subtitle, content, defaultValue, Input, disabled, returnOnCancel, footer, background, dimmed, manualDestroy, closeOnBackdropClick, resolve, ForegroundComponent, BackgroundComponent, }) {
|
|
303
|
+
constructor({ id, group, initiator, type, title, subtitle, content, defaultValue, Input, disabled, returnOnCancel, footer, background, dimmed, manualDestroy, closeOnBackdropClick, resolve, ForegroundComponent, BackgroundComponent, }) {
|
|
281
304
|
super({
|
|
282
305
|
id,
|
|
306
|
+
group,
|
|
283
307
|
initiator,
|
|
284
308
|
title,
|
|
285
309
|
subtitle,
|
|
@@ -329,30 +353,16 @@ const nodeFactory = (modal) => {
|
|
|
329
353
|
const DEFAULT_ANIMATION_DURATION = '300ms';
|
|
330
354
|
const DEFAULT_BACKDROP_COLOR = 'rgba(0, 0, 0, 0.5)';
|
|
331
355
|
|
|
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
356
|
const FallbackTitle = ({ children }) => {
|
|
347
|
-
return jsxRuntime.jsx("h2", {
|
|
357
|
+
return jsxRuntime.jsx("h2", { style: { margin: 'unset' }, children: children });
|
|
348
358
|
};
|
|
349
359
|
|
|
350
360
|
const FallbackSubtitle = ({ children }) => {
|
|
351
|
-
return jsxRuntime.jsx("h3", {
|
|
361
|
+
return jsxRuntime.jsx("h3", { style: { margin: 'unset' }, children: children });
|
|
352
362
|
};
|
|
353
363
|
|
|
354
364
|
const FallbackContent = ({ children }) => {
|
|
355
|
-
return jsxRuntime.jsx("div", {
|
|
365
|
+
return jsxRuntime.jsx("div", { style: { margin: 'unset' }, children: children });
|
|
356
366
|
};
|
|
357
367
|
|
|
358
368
|
const FallbackFooter = ({ confirmLabel, hideConfirm = false, cancelLabel, hideCancel = false, disabled, onConfirm, onCancel, }) => {
|
|
@@ -372,7 +382,8 @@ const useActiveModalCount = (validate = defaultValidate, refreshKey = 0) => {
|
|
|
372
382
|
const { modalIds, getModalNode } = useModalManagerContext();
|
|
373
383
|
return react.useMemo(() => {
|
|
374
384
|
let count = 0;
|
|
375
|
-
for (
|
|
385
|
+
for (let index = 0; index < modalIds.length; index++) {
|
|
386
|
+
const id = modalIds[index];
|
|
376
387
|
if (validate(getModalNode(id)))
|
|
377
388
|
count++;
|
|
378
389
|
}
|
|
@@ -392,10 +403,18 @@ const FallbackForegroundFrame = react.forwardRef(({ id, onChangeOrder, children
|
|
|
392
403
|
const offset = stacked ? (id % MAX_MODAL_COUNT) * 35 : 0;
|
|
393
404
|
return [level, offset];
|
|
394
405
|
}, [activeCount, id]);
|
|
395
|
-
return (jsxRuntime.jsx("div", { ref: ref,
|
|
406
|
+
return (jsxRuntime.jsx("div", { ref: ref, onClick: onChangeOrder, style: {
|
|
396
407
|
marginBottom: `calc(25vh + ${level}px)`,
|
|
397
408
|
marginLeft: `${level}px`,
|
|
398
409
|
transform: `translate(${offset}px, ${offset}px)`,
|
|
410
|
+
display: 'flex',
|
|
411
|
+
flexDirection: 'column',
|
|
412
|
+
justifyContent: 'center',
|
|
413
|
+
alignItems: 'center',
|
|
414
|
+
backgroundColor: 'white',
|
|
415
|
+
padding: '20px 80px',
|
|
416
|
+
gap: '10px',
|
|
417
|
+
border: '1px solid black',
|
|
399
418
|
}, children: children }));
|
|
400
419
|
});
|
|
401
420
|
|
|
@@ -497,9 +516,6 @@ const ModalManagerContextProvider = react.memo(({ usePathname, children, }) => {
|
|
|
497
516
|
return [...aliveIds, modal.id];
|
|
498
517
|
});
|
|
499
518
|
};
|
|
500
|
-
return () => {
|
|
501
|
-
ModalManager.reset();
|
|
502
|
-
};
|
|
503
519
|
});
|
|
504
520
|
react.useLayoutEffect(() => {
|
|
505
521
|
for (const id of modalIdsRef.current) {
|
|
@@ -622,24 +638,33 @@ const usePathname = () => {
|
|
|
622
638
|
return { pathname };
|
|
623
639
|
};
|
|
624
640
|
|
|
625
|
-
const background =
|
|
641
|
+
const background = ModalManager.getHashedClassNames('background');
|
|
642
|
+
const active$1 = ModalManager.getHashedClassNames('background-active');
|
|
643
|
+
const visible$1 = ModalManager.getHashedClassNames('background-visible');
|
|
644
|
+
const style$3 = `
|
|
645
|
+
.${background} {
|
|
626
646
|
display: none;
|
|
627
647
|
position: fixed;
|
|
628
648
|
inset: 0;
|
|
629
649
|
z-index: -999;
|
|
630
650
|
pointer-events: none;
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
651
|
+
}
|
|
652
|
+
|
|
653
|
+
.${background} > * {
|
|
654
|
+
pointer-events: none;
|
|
655
|
+
}
|
|
656
|
+
|
|
657
|
+
.${background}.${active$1} {
|
|
636
658
|
pointer-events: all;
|
|
637
|
-
|
|
638
|
-
|
|
659
|
+
}
|
|
660
|
+
|
|
661
|
+
.${background}.${visible$1} {
|
|
639
662
|
display: flex;
|
|
640
663
|
align-items: center;
|
|
641
664
|
justify-content: center;
|
|
665
|
+
}
|
|
642
666
|
`;
|
|
667
|
+
ModalManager.defineStyleSheet('background', style$3);
|
|
643
668
|
|
|
644
669
|
const BackgroundFrame = ({ modalId, onChangeOrder, }) => {
|
|
645
670
|
const { BackgroundComponent } = useConfigurationContext();
|
|
@@ -653,30 +678,12 @@ const BackgroundFrame = ({ modalId, onChangeOrder, }) => {
|
|
|
653
678
|
const Background = react.useMemo(() => modal?.BackgroundComponent || BackgroundComponent, [BackgroundComponent, modal]);
|
|
654
679
|
if (!modal)
|
|
655
680
|
return null;
|
|
656
|
-
return (jsxRuntime.jsx("div", { className:
|
|
657
|
-
[visible$1]: modal.manualDestroy ? modal.alive : modal.visible,
|
|
681
|
+
return (jsxRuntime.jsx("div", { className: styleUtils.cx(background, {
|
|
658
682
|
[active$1]: modal.closeOnBackdropClick && modal.visible,
|
|
683
|
+
[visible$1]: modal.manualDestroy ? modal.alive : modal.visible,
|
|
659
684
|
}), 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
685
|
};
|
|
661
686
|
|
|
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
687
|
const AlertInner = react.memo(({ modal, handlers }) => {
|
|
681
688
|
const { title, subtitle, content, footer } = react.useMemo(() => modal, [modal]);
|
|
682
689
|
const { context: userDefinedContext } = useUserDefinedContext();
|
|
@@ -754,6 +761,30 @@ const PromptInner = react.memo(({ modal, handlers }) => {
|
|
|
754
761
|
})) : (jsxRuntime.jsx(FooterComponent, { disabled: disabled, onConfirm: handleConfirm, onCancel: handleClose, confirmLabel: footer?.confirm, cancelLabel: footer?.cancel, hideConfirm: footer?.hideConfirm, hideCancel: footer?.hideCancel, context: userDefinedContext })))] }));
|
|
755
762
|
});
|
|
756
763
|
|
|
764
|
+
const foreground = ModalManager.getHashedClassNames('foreground');
|
|
765
|
+
const active = ModalManager.getHashedClassNames('foreground-active');
|
|
766
|
+
const visible = ModalManager.getHashedClassNames('foreground-visible');
|
|
767
|
+
const style$2 = `
|
|
768
|
+
.${foreground} {
|
|
769
|
+
pointer-events: none;
|
|
770
|
+
display: none;
|
|
771
|
+
position: fixed;
|
|
772
|
+
inset: 0;
|
|
773
|
+
z-index: 1;
|
|
774
|
+
}
|
|
775
|
+
|
|
776
|
+
.${foreground}.${active} > * {
|
|
777
|
+
pointer-events: all;
|
|
778
|
+
}
|
|
779
|
+
|
|
780
|
+
.${foreground}.${visible} {
|
|
781
|
+
display: flex !important;
|
|
782
|
+
justify-content: center;
|
|
783
|
+
align-items: center;
|
|
784
|
+
}
|
|
785
|
+
`;
|
|
786
|
+
ModalManager.defineStyleSheet('foreground', style$2);
|
|
787
|
+
|
|
757
788
|
const ForegroundFrame = ({ modalId, onChangeOrder, }) => {
|
|
758
789
|
const { ForegroundComponent } = useConfigurationContext();
|
|
759
790
|
const { context: userDefinedContext } = useUserDefinedContext();
|
|
@@ -761,9 +792,9 @@ const ForegroundFrame = ({ modalId, onChangeOrder, }) => {
|
|
|
761
792
|
const Foreground = react.useMemo(() => modal?.ForegroundComponent || ForegroundComponent, [ForegroundComponent, modal]);
|
|
762
793
|
if (!modal)
|
|
763
794
|
return null;
|
|
764
|
-
return (jsxRuntime.jsx("div", { className:
|
|
765
|
-
[visible]: modal.manualDestroy ? modal.alive : modal.visible,
|
|
795
|
+
return (jsxRuntime.jsx("div", { className: styleUtils.cx(foreground, {
|
|
766
796
|
[active]: modal.visible,
|
|
797
|
+
[visible]: modal.manualDestroy ? modal.alive : modal.visible,
|
|
767
798
|
}), 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
799
|
};
|
|
769
800
|
|
|
@@ -778,12 +809,15 @@ const useSubscribeModal = (modal) => {
|
|
|
778
809
|
return version;
|
|
779
810
|
};
|
|
780
811
|
|
|
781
|
-
const presenter =
|
|
812
|
+
const presenter = ModalManager.getHashedClassNames('presenter');
|
|
813
|
+
const style$1 = `
|
|
814
|
+
.${presenter} {
|
|
782
815
|
position: fixed;
|
|
783
816
|
inset: 0;
|
|
784
817
|
pointer-events: none;
|
|
785
818
|
overflow: hidden;
|
|
786
819
|
`;
|
|
820
|
+
ModalManager.defineStyleSheet('presenter', style$1);
|
|
787
821
|
|
|
788
822
|
const { increment } = lib.counterFactory(1);
|
|
789
823
|
const Presenter = react.memo(({ modalId }) => {
|
|
@@ -798,16 +832,19 @@ const Presenter = react.memo(({ modalId }) => {
|
|
|
798
832
|
return (jsxRuntime.jsxs("div", { ref: ref, className: presenter, children: [jsxRuntime.jsx(BackgroundFrame, { modalId: modalId, onChangeOrder: handleChangeOrder }), jsxRuntime.jsx(ForegroundFrame, { modalId: modalId, onChangeOrder: handleChangeOrder })] }));
|
|
799
833
|
});
|
|
800
834
|
|
|
801
|
-
const anchor =
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
835
|
+
const anchor = ModalManager.getHashedClassNames('anchor');
|
|
836
|
+
const style = `
|
|
837
|
+
.${anchor} {
|
|
838
|
+
display: flex;
|
|
839
|
+
align-items: center;
|
|
840
|
+
justify-content: center;
|
|
841
|
+
position: fixed;
|
|
842
|
+
inset: 0;
|
|
843
|
+
pointer-events: none;
|
|
844
|
+
z-index: 1000;
|
|
845
|
+
transition: background-color ease-in-out;
|
|
846
|
+
}`;
|
|
847
|
+
ModalManager.defineStyleSheet('anchor', style);
|
|
811
848
|
|
|
812
849
|
const AnchorInner = () => {
|
|
813
850
|
const [version, update] = hook.useVersion();
|
|
@@ -834,6 +871,7 @@ const useInitialize = () => {
|
|
|
834
871
|
const handleInitialize = react.useCallback((root) => {
|
|
835
872
|
if (permitted.current) {
|
|
836
873
|
anchorRef.current = ModalManager.anchor({ root });
|
|
874
|
+
ModalManager.applyStyleSheet();
|
|
837
875
|
update();
|
|
838
876
|
}
|
|
839
877
|
else
|
|
@@ -844,15 +882,19 @@ const useInitialize = () => {
|
|
|
844
882
|
info: 'Something is wrong with the ModalProvider initialization...',
|
|
845
883
|
});
|
|
846
884
|
}, [update]);
|
|
885
|
+
const handleReset = react.useCallback(() => {
|
|
886
|
+
ModalManager.reset();
|
|
887
|
+
}, []);
|
|
847
888
|
return {
|
|
848
889
|
anchorRef,
|
|
849
890
|
handleInitialize,
|
|
891
|
+
handleReset,
|
|
850
892
|
};
|
|
851
893
|
};
|
|
852
894
|
|
|
853
895
|
const BootstrapProvider = react.forwardRef(({ usePathname: useExternalPathname, ForegroundComponent, BackgroundComponent, TitleComponent, SubtitleComponent, ContentComponent, FooterComponent, options, context, children, }, handleRef) => {
|
|
854
896
|
const usePathname$1 = react.useMemo(() => useExternalPathname || usePathname, [useExternalPathname]);
|
|
855
|
-
const { anchorRef, handleInitialize } = useInitialize();
|
|
897
|
+
const { anchorRef, handleInitialize, handleReset } = useInitialize();
|
|
856
898
|
react.useImperativeHandle(handleRef, () => ({
|
|
857
899
|
initialize: handleInitialize,
|
|
858
900
|
}), [handleInitialize]);
|
|
@@ -862,6 +904,7 @@ const BootstrapProvider = react.forwardRef(({ usePathname: useExternalPathname,
|
|
|
862
904
|
return () => {
|
|
863
905
|
if (anchorRef.current)
|
|
864
906
|
anchorRef.current.remove();
|
|
907
|
+
handleReset();
|
|
865
908
|
};
|
|
866
909
|
});
|
|
867
910
|
return (jsxRuntime.jsxs(react.Fragment, { children: [children, anchorRef.current &&
|
package/dist/index.mjs
CHANGED
|
@@ -2,11 +2,14 @@ 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
4
|
import { useReference, useOnMountLayout, useHandle, useVersion, useOnMount } from '@winglet/react-utils/hook';
|
|
5
|
+
import { polynomialHash } from '@winglet/common-utils/hash';
|
|
5
6
|
import { getRandomString, counterFactory } from '@winglet/common-utils/lib';
|
|
6
|
-
import {
|
|
7
|
+
import { compressCss } from '@winglet/style-utils/compressCss';
|
|
8
|
+
import { styleManagerFactory, destroyScope } from '@winglet/style-utils/styleManager';
|
|
7
9
|
import { createPortal } from 'react-dom';
|
|
8
10
|
import { map } from '@winglet/common-utils/array';
|
|
9
11
|
import { withErrorBoundary } from '@winglet/react-utils/hoc';
|
|
12
|
+
import { cx } from '@winglet/style-utils';
|
|
10
13
|
import { isString, isFunction } from '@winglet/common-utils/filter';
|
|
11
14
|
import { renderComponent } from '@winglet/react-utils/render';
|
|
12
15
|
import { printError } from '@winglet/common-utils/console';
|
|
@@ -19,15 +22,15 @@ class ModalManager {
|
|
|
19
22
|
return (ModalManager.#active = true);
|
|
20
23
|
}
|
|
21
24
|
static #anchor = null;
|
|
25
|
+
static #scope = `promise-modal-${getRandomString(36)}`;
|
|
26
|
+
static #hash = polynomialHash(ModalManager.#scope);
|
|
22
27
|
static anchor(options) {
|
|
23
|
-
if (ModalManager.#anchor)
|
|
24
|
-
|
|
25
|
-
if (anchor)
|
|
26
|
-
return anchor;
|
|
27
|
-
}
|
|
28
|
+
if (ModalManager.#anchor)
|
|
29
|
+
return ModalManager.#anchor;
|
|
28
30
|
const { tag = 'div', prefix = 'promise-modal', root = document.body, } = options || {};
|
|
29
31
|
const node = document.createElement(tag);
|
|
30
|
-
node.
|
|
32
|
+
node.id = `${prefix}-${getRandomString(36)}`;
|
|
33
|
+
node.className = ModalManager.#scope;
|
|
31
34
|
root.appendChild(node);
|
|
32
35
|
ModalManager.#anchor = node;
|
|
33
36
|
return node;
|
|
@@ -44,22 +47,36 @@ class ModalManager {
|
|
|
44
47
|
static get unanchored() {
|
|
45
48
|
return !ModalManager.#anchor;
|
|
46
49
|
}
|
|
50
|
+
static #styleManager = styleManagerFactory(ModalManager.#scope);
|
|
51
|
+
static #styleSheetDefinition = new Map();
|
|
52
|
+
static defineStyleSheet(styleId, css) {
|
|
53
|
+
ModalManager.#styleSheetDefinition.set(styleId, compressCss(css));
|
|
54
|
+
}
|
|
55
|
+
static applyStyleSheet() {
|
|
56
|
+
for (const [styleId, css] of ModalManager.#styleSheetDefinition)
|
|
57
|
+
ModalManager.#styleManager(styleId, css, true);
|
|
58
|
+
}
|
|
59
|
+
static getHashedClassNames(styleId) {
|
|
60
|
+
return `${styleId}-${ModalManager.#hash}`;
|
|
61
|
+
}
|
|
47
62
|
static reset() {
|
|
48
63
|
ModalManager.#active = false;
|
|
49
64
|
ModalManager.#anchor = null;
|
|
50
65
|
ModalManager.#prerenderList = [];
|
|
51
66
|
ModalManager.#openHandler = (modal) => ModalManager.#prerenderList.push(modal);
|
|
67
|
+
destroyScope(ModalManager.#scope);
|
|
52
68
|
}
|
|
53
69
|
static open(modal) {
|
|
54
70
|
ModalManager.#openHandler(modal);
|
|
55
71
|
}
|
|
56
72
|
}
|
|
57
73
|
|
|
58
|
-
const alert = ({ subtype, title, subtitle, content, background, footer, dimmed, manualDestroy, closeOnBackdropClick, ForegroundComponent, BackgroundComponent, }) => {
|
|
74
|
+
const alert = ({ group, subtype, title, subtitle, content, background, footer, dimmed, manualDestroy, closeOnBackdropClick, ForegroundComponent, BackgroundComponent, }) => {
|
|
59
75
|
return new Promise((resolve, reject) => {
|
|
60
76
|
try {
|
|
61
77
|
ModalManager.open({
|
|
62
78
|
type: 'alert',
|
|
79
|
+
group,
|
|
63
80
|
subtype,
|
|
64
81
|
resolve: () => resolve(),
|
|
65
82
|
title,
|
|
@@ -80,11 +97,12 @@ const alert = ({ subtype, title, subtitle, content, background, footer, dimmed,
|
|
|
80
97
|
});
|
|
81
98
|
};
|
|
82
99
|
|
|
83
|
-
const confirm = ({ subtype, title, subtitle, content, background, footer, dimmed, manualDestroy, closeOnBackdropClick, ForegroundComponent, BackgroundComponent, }) => {
|
|
100
|
+
const confirm = ({ group, subtype, title, subtitle, content, background, footer, dimmed, manualDestroy, closeOnBackdropClick, ForegroundComponent, BackgroundComponent, }) => {
|
|
84
101
|
return new Promise((resolve, reject) => {
|
|
85
102
|
try {
|
|
86
103
|
ModalManager.open({
|
|
87
104
|
type: 'confirm',
|
|
105
|
+
group,
|
|
88
106
|
subtype,
|
|
89
107
|
resolve: (result) => resolve(result ?? false),
|
|
90
108
|
title,
|
|
@@ -105,11 +123,12 @@ const confirm = ({ subtype, title, subtitle, content, background, footer, dimmed
|
|
|
105
123
|
});
|
|
106
124
|
};
|
|
107
125
|
|
|
108
|
-
const prompt = ({
|
|
126
|
+
const prompt = ({ group, title, subtitle, content, defaultValue, Input, disabled, returnOnCancel, background, footer, dimmed, manualDestroy, closeOnBackdropClick, ForegroundComponent, BackgroundComponent, }) => {
|
|
109
127
|
return new Promise((resolve, reject) => {
|
|
110
128
|
try {
|
|
111
129
|
ModalManager.open({
|
|
112
130
|
type: 'prompt',
|
|
131
|
+
group,
|
|
113
132
|
resolve: (result) => resolve(result),
|
|
114
133
|
title,
|
|
115
134
|
subtitle,
|
|
@@ -135,6 +154,7 @@ const prompt = ({ defaultValue, title, subtitle, content, Input, disabled, retur
|
|
|
135
154
|
|
|
136
155
|
class AbstractNode {
|
|
137
156
|
id;
|
|
157
|
+
group;
|
|
138
158
|
initiator;
|
|
139
159
|
title;
|
|
140
160
|
subtitle;
|
|
@@ -154,8 +174,9 @@ class AbstractNode {
|
|
|
154
174
|
}
|
|
155
175
|
#resolve;
|
|
156
176
|
#listeners = new Set();
|
|
157
|
-
constructor({ id, initiator, title, subtitle, background, dimmed = true, manualDestroy = false, closeOnBackdropClick = true, resolve, ForegroundComponent, BackgroundComponent, }) {
|
|
177
|
+
constructor({ id, initiator, group, title, subtitle, background, dimmed = true, manualDestroy = false, closeOnBackdropClick = true, resolve, ForegroundComponent, BackgroundComponent, }) {
|
|
158
178
|
this.id = id;
|
|
179
|
+
this.group = group;
|
|
159
180
|
this.initiator = initiator;
|
|
160
181
|
this.title = title;
|
|
161
182
|
this.subtitle = subtitle;
|
|
@@ -207,9 +228,10 @@ class AlertNode extends AbstractNode {
|
|
|
207
228
|
subtype;
|
|
208
229
|
content;
|
|
209
230
|
footer;
|
|
210
|
-
constructor({ id, initiator, type, subtype, title, subtitle, content, footer, background, dimmed, manualDestroy, closeOnBackdropClick, resolve, ForegroundComponent, BackgroundComponent, }) {
|
|
231
|
+
constructor({ id, group, initiator, type, subtype, title, subtitle, content, footer, background, dimmed, manualDestroy, closeOnBackdropClick, resolve, ForegroundComponent, BackgroundComponent, }) {
|
|
211
232
|
super({
|
|
212
233
|
id,
|
|
234
|
+
group,
|
|
213
235
|
initiator,
|
|
214
236
|
title,
|
|
215
237
|
subtitle,
|
|
@@ -239,9 +261,10 @@ class ConfirmNode extends AbstractNode {
|
|
|
239
261
|
subtype;
|
|
240
262
|
content;
|
|
241
263
|
footer;
|
|
242
|
-
constructor({ id, initiator, type, subtype, title, subtitle, content, footer, background, dimmed, manualDestroy, closeOnBackdropClick, resolve, ForegroundComponent, BackgroundComponent, }) {
|
|
264
|
+
constructor({ id, group, initiator, type, subtype, title, subtitle, content, footer, background, dimmed, manualDestroy, closeOnBackdropClick, resolve, ForegroundComponent, BackgroundComponent, }) {
|
|
243
265
|
super({
|
|
244
266
|
id,
|
|
267
|
+
group,
|
|
245
268
|
initiator,
|
|
246
269
|
title,
|
|
247
270
|
subtitle,
|
|
@@ -275,9 +298,10 @@ class PromptNode extends AbstractNode {
|
|
|
275
298
|
returnOnCancel;
|
|
276
299
|
footer;
|
|
277
300
|
#value;
|
|
278
|
-
constructor({ id, initiator, type, title, subtitle, content, defaultValue, Input, disabled, returnOnCancel, footer, background, dimmed, manualDestroy, closeOnBackdropClick, resolve, ForegroundComponent, BackgroundComponent, }) {
|
|
301
|
+
constructor({ id, group, initiator, type, title, subtitle, content, defaultValue, Input, disabled, returnOnCancel, footer, background, dimmed, manualDestroy, closeOnBackdropClick, resolve, ForegroundComponent, BackgroundComponent, }) {
|
|
279
302
|
super({
|
|
280
303
|
id,
|
|
304
|
+
group,
|
|
281
305
|
initiator,
|
|
282
306
|
title,
|
|
283
307
|
subtitle,
|
|
@@ -327,30 +351,16 @@ const nodeFactory = (modal) => {
|
|
|
327
351
|
const DEFAULT_ANIMATION_DURATION = '300ms';
|
|
328
352
|
const DEFAULT_BACKDROP_COLOR = 'rgba(0, 0, 0, 0.5)';
|
|
329
353
|
|
|
330
|
-
const fallback = css `
|
|
331
|
-
margin: unset;
|
|
332
|
-
`;
|
|
333
|
-
const frame = css `
|
|
334
|
-
display: flex;
|
|
335
|
-
flex-direction: column;
|
|
336
|
-
justify-content: center;
|
|
337
|
-
align-items: center;
|
|
338
|
-
background-color: white;
|
|
339
|
-
padding: 20px 80px;
|
|
340
|
-
gap: 10px;
|
|
341
|
-
border: 1px solid black;
|
|
342
|
-
`;
|
|
343
|
-
|
|
344
354
|
const FallbackTitle = ({ children }) => {
|
|
345
|
-
return jsx("h2", {
|
|
355
|
+
return jsx("h2", { style: { margin: 'unset' }, children: children });
|
|
346
356
|
};
|
|
347
357
|
|
|
348
358
|
const FallbackSubtitle = ({ children }) => {
|
|
349
|
-
return jsx("h3", {
|
|
359
|
+
return jsx("h3", { style: { margin: 'unset' }, children: children });
|
|
350
360
|
};
|
|
351
361
|
|
|
352
362
|
const FallbackContent = ({ children }) => {
|
|
353
|
-
return jsx("div", {
|
|
363
|
+
return jsx("div", { style: { margin: 'unset' }, children: children });
|
|
354
364
|
};
|
|
355
365
|
|
|
356
366
|
const FallbackFooter = ({ confirmLabel, hideConfirm = false, cancelLabel, hideCancel = false, disabled, onConfirm, onCancel, }) => {
|
|
@@ -370,7 +380,8 @@ const useActiveModalCount = (validate = defaultValidate, refreshKey = 0) => {
|
|
|
370
380
|
const { modalIds, getModalNode } = useModalManagerContext();
|
|
371
381
|
return useMemo(() => {
|
|
372
382
|
let count = 0;
|
|
373
|
-
for (
|
|
383
|
+
for (let index = 0; index < modalIds.length; index++) {
|
|
384
|
+
const id = modalIds[index];
|
|
374
385
|
if (validate(getModalNode(id)))
|
|
375
386
|
count++;
|
|
376
387
|
}
|
|
@@ -390,10 +401,18 @@ const FallbackForegroundFrame = forwardRef(({ id, onChangeOrder, children }, ref
|
|
|
390
401
|
const offset = stacked ? (id % MAX_MODAL_COUNT) * 35 : 0;
|
|
391
402
|
return [level, offset];
|
|
392
403
|
}, [activeCount, id]);
|
|
393
|
-
return (jsx("div", { ref: ref,
|
|
404
|
+
return (jsx("div", { ref: ref, onClick: onChangeOrder, style: {
|
|
394
405
|
marginBottom: `calc(25vh + ${level}px)`,
|
|
395
406
|
marginLeft: `${level}px`,
|
|
396
407
|
transform: `translate(${offset}px, ${offset}px)`,
|
|
408
|
+
display: 'flex',
|
|
409
|
+
flexDirection: 'column',
|
|
410
|
+
justifyContent: 'center',
|
|
411
|
+
alignItems: 'center',
|
|
412
|
+
backgroundColor: 'white',
|
|
413
|
+
padding: '20px 80px',
|
|
414
|
+
gap: '10px',
|
|
415
|
+
border: '1px solid black',
|
|
397
416
|
}, children: children }));
|
|
398
417
|
});
|
|
399
418
|
|
|
@@ -495,9 +514,6 @@ const ModalManagerContextProvider = memo(({ usePathname, children, }) => {
|
|
|
495
514
|
return [...aliveIds, modal.id];
|
|
496
515
|
});
|
|
497
516
|
};
|
|
498
|
-
return () => {
|
|
499
|
-
ModalManager.reset();
|
|
500
|
-
};
|
|
501
517
|
});
|
|
502
518
|
useLayoutEffect(() => {
|
|
503
519
|
for (const id of modalIdsRef.current) {
|
|
@@ -620,24 +636,33 @@ const usePathname = () => {
|
|
|
620
636
|
return { pathname };
|
|
621
637
|
};
|
|
622
638
|
|
|
623
|
-
const background =
|
|
639
|
+
const background = ModalManager.getHashedClassNames('background');
|
|
640
|
+
const active$1 = ModalManager.getHashedClassNames('background-active');
|
|
641
|
+
const visible$1 = ModalManager.getHashedClassNames('background-visible');
|
|
642
|
+
const style$3 = `
|
|
643
|
+
.${background} {
|
|
624
644
|
display: none;
|
|
625
645
|
position: fixed;
|
|
626
646
|
inset: 0;
|
|
627
647
|
z-index: -999;
|
|
628
648
|
pointer-events: none;
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
649
|
+
}
|
|
650
|
+
|
|
651
|
+
.${background} > * {
|
|
652
|
+
pointer-events: none;
|
|
653
|
+
}
|
|
654
|
+
|
|
655
|
+
.${background}.${active$1} {
|
|
634
656
|
pointer-events: all;
|
|
635
|
-
|
|
636
|
-
|
|
657
|
+
}
|
|
658
|
+
|
|
659
|
+
.${background}.${visible$1} {
|
|
637
660
|
display: flex;
|
|
638
661
|
align-items: center;
|
|
639
662
|
justify-content: center;
|
|
663
|
+
}
|
|
640
664
|
`;
|
|
665
|
+
ModalManager.defineStyleSheet('background', style$3);
|
|
641
666
|
|
|
642
667
|
const BackgroundFrame = ({ modalId, onChangeOrder, }) => {
|
|
643
668
|
const { BackgroundComponent } = useConfigurationContext();
|
|
@@ -652,29 +677,11 @@ const BackgroundFrame = ({ modalId, onChangeOrder, }) => {
|
|
|
652
677
|
if (!modal)
|
|
653
678
|
return null;
|
|
654
679
|
return (jsx("div", { className: cx(background, {
|
|
655
|
-
[visible$1]: modal.manualDestroy ? modal.alive : modal.visible,
|
|
656
680
|
[active$1]: modal.closeOnBackdropClick && modal.visible,
|
|
681
|
+
[visible$1]: modal.manualDestroy ? modal.alive : modal.visible,
|
|
657
682
|
}), onClick: handleClose, children: Background && (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 })) }));
|
|
658
683
|
};
|
|
659
684
|
|
|
660
|
-
const foreground = css `
|
|
661
|
-
pointer-events: none;
|
|
662
|
-
display: none;
|
|
663
|
-
position: fixed;
|
|
664
|
-
inset: 0;
|
|
665
|
-
z-index: 1;
|
|
666
|
-
`;
|
|
667
|
-
const active = css `
|
|
668
|
-
> * {
|
|
669
|
-
pointer-events: all;
|
|
670
|
-
}
|
|
671
|
-
`;
|
|
672
|
-
const visible = css `
|
|
673
|
-
display: flex !important;
|
|
674
|
-
justify-content: center;
|
|
675
|
-
align-items: center;
|
|
676
|
-
`;
|
|
677
|
-
|
|
678
685
|
const AlertInner = memo(({ modal, handlers }) => {
|
|
679
686
|
const { title, subtitle, content, footer } = useMemo(() => modal, [modal]);
|
|
680
687
|
const { context: userDefinedContext } = useUserDefinedContext();
|
|
@@ -752,6 +759,30 @@ const PromptInner = memo(({ modal, handlers }) => {
|
|
|
752
759
|
})) : (jsx(FooterComponent, { disabled: disabled, onConfirm: handleConfirm, onCancel: handleClose, confirmLabel: footer?.confirm, cancelLabel: footer?.cancel, hideConfirm: footer?.hideConfirm, hideCancel: footer?.hideCancel, context: userDefinedContext })))] }));
|
|
753
760
|
});
|
|
754
761
|
|
|
762
|
+
const foreground = ModalManager.getHashedClassNames('foreground');
|
|
763
|
+
const active = ModalManager.getHashedClassNames('foreground-active');
|
|
764
|
+
const visible = ModalManager.getHashedClassNames('foreground-visible');
|
|
765
|
+
const style$2 = `
|
|
766
|
+
.${foreground} {
|
|
767
|
+
pointer-events: none;
|
|
768
|
+
display: none;
|
|
769
|
+
position: fixed;
|
|
770
|
+
inset: 0;
|
|
771
|
+
z-index: 1;
|
|
772
|
+
}
|
|
773
|
+
|
|
774
|
+
.${foreground}.${active} > * {
|
|
775
|
+
pointer-events: all;
|
|
776
|
+
}
|
|
777
|
+
|
|
778
|
+
.${foreground}.${visible} {
|
|
779
|
+
display: flex !important;
|
|
780
|
+
justify-content: center;
|
|
781
|
+
align-items: center;
|
|
782
|
+
}
|
|
783
|
+
`;
|
|
784
|
+
ModalManager.defineStyleSheet('foreground', style$2);
|
|
785
|
+
|
|
755
786
|
const ForegroundFrame = ({ modalId, onChangeOrder, }) => {
|
|
756
787
|
const { ForegroundComponent } = useConfigurationContext();
|
|
757
788
|
const { context: userDefinedContext } = useUserDefinedContext();
|
|
@@ -760,8 +791,8 @@ const ForegroundFrame = ({ modalId, onChangeOrder, }) => {
|
|
|
760
791
|
if (!modal)
|
|
761
792
|
return null;
|
|
762
793
|
return (jsx("div", { className: cx(foreground, {
|
|
763
|
-
[visible]: modal.manualDestroy ? modal.alive : modal.visible,
|
|
764
794
|
[active]: modal.visible,
|
|
795
|
+
[visible]: modal.manualDestroy ? modal.alive : modal.visible,
|
|
765
796
|
}), children: 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' && (jsx(AlertInner, { modal: modal, handlers: { onConfirm } })), modal.type === 'confirm' && (jsx(ConfirmInner, { modal: modal, handlers: { onConfirm, onClose } })), modal.type === 'prompt' && (jsx(PromptInner, { modal: modal, handlers: { onChange, onConfirm, onClose } }))] }) }));
|
|
766
797
|
};
|
|
767
798
|
|
|
@@ -776,12 +807,15 @@ const useSubscribeModal = (modal) => {
|
|
|
776
807
|
return version;
|
|
777
808
|
};
|
|
778
809
|
|
|
779
|
-
const presenter =
|
|
810
|
+
const presenter = ModalManager.getHashedClassNames('presenter');
|
|
811
|
+
const style$1 = `
|
|
812
|
+
.${presenter} {
|
|
780
813
|
position: fixed;
|
|
781
814
|
inset: 0;
|
|
782
815
|
pointer-events: none;
|
|
783
816
|
overflow: hidden;
|
|
784
817
|
`;
|
|
818
|
+
ModalManager.defineStyleSheet('presenter', style$1);
|
|
785
819
|
|
|
786
820
|
const { increment } = counterFactory(1);
|
|
787
821
|
const Presenter = memo(({ modalId }) => {
|
|
@@ -796,16 +830,19 @@ const Presenter = memo(({ modalId }) => {
|
|
|
796
830
|
return (jsxs("div", { ref: ref, className: presenter, children: [jsx(BackgroundFrame, { modalId: modalId, onChangeOrder: handleChangeOrder }), jsx(ForegroundFrame, { modalId: modalId, onChangeOrder: handleChangeOrder })] }));
|
|
797
831
|
});
|
|
798
832
|
|
|
799
|
-
const anchor =
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
833
|
+
const anchor = ModalManager.getHashedClassNames('anchor');
|
|
834
|
+
const style = `
|
|
835
|
+
.${anchor} {
|
|
836
|
+
display: flex;
|
|
837
|
+
align-items: center;
|
|
838
|
+
justify-content: center;
|
|
839
|
+
position: fixed;
|
|
840
|
+
inset: 0;
|
|
841
|
+
pointer-events: none;
|
|
842
|
+
z-index: 1000;
|
|
843
|
+
transition: background-color ease-in-out;
|
|
844
|
+
}`;
|
|
845
|
+
ModalManager.defineStyleSheet('anchor', style);
|
|
809
846
|
|
|
810
847
|
const AnchorInner = () => {
|
|
811
848
|
const [version, update] = useVersion();
|
|
@@ -832,6 +869,7 @@ const useInitialize = () => {
|
|
|
832
869
|
const handleInitialize = useCallback((root) => {
|
|
833
870
|
if (permitted.current) {
|
|
834
871
|
anchorRef.current = ModalManager.anchor({ root });
|
|
872
|
+
ModalManager.applyStyleSheet();
|
|
835
873
|
update();
|
|
836
874
|
}
|
|
837
875
|
else
|
|
@@ -842,15 +880,19 @@ const useInitialize = () => {
|
|
|
842
880
|
info: 'Something is wrong with the ModalProvider initialization...',
|
|
843
881
|
});
|
|
844
882
|
}, [update]);
|
|
883
|
+
const handleReset = useCallback(() => {
|
|
884
|
+
ModalManager.reset();
|
|
885
|
+
}, []);
|
|
845
886
|
return {
|
|
846
887
|
anchorRef,
|
|
847
888
|
handleInitialize,
|
|
889
|
+
handleReset,
|
|
848
890
|
};
|
|
849
891
|
};
|
|
850
892
|
|
|
851
893
|
const BootstrapProvider = forwardRef(({ usePathname: useExternalPathname, ForegroundComponent, BackgroundComponent, TitleComponent, SubtitleComponent, ContentComponent, FooterComponent, options, context, children, }, handleRef) => {
|
|
852
894
|
const usePathname$1 = useMemo(() => useExternalPathname || usePathname, [useExternalPathname]);
|
|
853
|
-
const { anchorRef, handleInitialize } = useInitialize();
|
|
895
|
+
const { anchorRef, handleInitialize, handleReset } = useInitialize();
|
|
854
896
|
useImperativeHandle(handleRef, () => ({
|
|
855
897
|
initialize: handleInitialize,
|
|
856
898
|
}), [handleInitialize]);
|
|
@@ -860,6 +902,7 @@ const BootstrapProvider = forwardRef(({ usePathname: useExternalPathname, Foregr
|
|
|
860
902
|
return () => {
|
|
861
903
|
if (anchorRef.current)
|
|
862
904
|
anchorRef.current.remove();
|
|
905
|
+
handleReset();
|
|
863
906
|
};
|
|
864
907
|
});
|
|
865
908
|
return (jsxs(Fragment, { children: [children, anchorRef.current &&
|
package/dist/types/base.d.ts
CHANGED
|
@@ -3,6 +3,7 @@ import type { Dictionary } from '../@aileron/declare';
|
|
|
3
3
|
import type { ModalBackground } from './background';
|
|
4
4
|
import type { ModalFrameProps } from './modal';
|
|
5
5
|
export interface BaseModal<T, B> {
|
|
6
|
+
group?: string;
|
|
6
7
|
title?: ReactNode;
|
|
7
8
|
subtitle?: ReactNode;
|
|
8
9
|
background?: ModalBackground<B>;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lerx/promise-modal",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.3",
|
|
4
4
|
"description": "Universal React modal utility that can be used outside React components with promise-based results for alert, confirm, and prompt modals",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"react",
|
|
@@ -65,9 +65,9 @@
|
|
|
65
65
|
"version:patch": "yarn version patch"
|
|
66
66
|
},
|
|
67
67
|
"dependencies": {
|
|
68
|
-
"@
|
|
69
|
-
"@winglet/
|
|
70
|
-
"@winglet/
|
|
68
|
+
"@winglet/common-utils": "^0.2.2",
|
|
69
|
+
"@winglet/react-utils": "^0.2.3",
|
|
70
|
+
"@winglet/style-utils": "^0.2.0"
|
|
71
71
|
},
|
|
72
72
|
"devDependencies": {
|
|
73
73
|
"@chromatic-com/storybook": "^3.2.6",
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|