@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.
@@ -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,4 +1,5 @@
1
1
  export declare const useInitialize: () => {
2
2
  readonly anchorRef: import("react").RefObject<HTMLElement | null>;
3
3
  readonly handleInitialize: (root?: HTMLElement) => void;
4
+ readonly handleReset: () => void;
4
5
  };
@@ -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>({ defaultValue, title, subtitle, content, Input, disabled, returnOnCancel, background, footer, dimmed, manualDestroy, closeOnBackdropClick, ForegroundComponent, BackgroundComponent, }: PromptProps<T, B>) => Promise<T>;
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?], boolean | undefined>, refreshKey?: string | number) => number;
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 css = require('@emotion/css');
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
- const anchor = document.getElementById(ModalManager.#anchor.id);
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.setAttribute('id', `${prefix}-${lib.getRandomString(36)}`);
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 = ({ defaultValue, title, subtitle, content, Input, disabled, returnOnCancel, background, footer, dimmed, manualDestroy, closeOnBackdropClick, ForegroundComponent, BackgroundComponent, }) => {
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", { className: fallback, children: children });
357
+ return jsxRuntime.jsx("h2", { style: { margin: 'unset' }, children: children });
348
358
  };
349
359
 
350
360
  const FallbackSubtitle = ({ children }) => {
351
- return jsxRuntime.jsx("h3", { className: fallback, children: children });
361
+ return jsxRuntime.jsx("h3", { style: { margin: 'unset' }, children: children });
352
362
  };
353
363
 
354
364
  const FallbackContent = ({ children }) => {
355
- return jsxRuntime.jsx("div", { className: fallback, children: children });
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 (const id of modalIds) {
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, className: frame, onClick: onChangeOrder, style: {
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 = css.css `
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
- pointer-events: none;
633
- }
634
- `;
635
- const active$1 = css.css `
651
+ }
652
+
653
+ .${background} > * {
654
+ pointer-events: none;
655
+ }
656
+
657
+ .${background}.${active$1} {
636
658
  pointer-events: all;
637
- `;
638
- const visible$1 = css.css `
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: css.cx(background, {
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: css.cx(foreground, {
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 = css.css `
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 = 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
- `;
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 { css, cx } from '@emotion/css';
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
- const anchor = document.getElementById(ModalManager.#anchor.id);
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.setAttribute('id', `${prefix}-${getRandomString(36)}`);
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 = ({ defaultValue, title, subtitle, content, Input, disabled, returnOnCancel, background, footer, dimmed, manualDestroy, closeOnBackdropClick, ForegroundComponent, BackgroundComponent, }) => {
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", { className: fallback, children: children });
355
+ return jsx("h2", { style: { margin: 'unset' }, children: children });
346
356
  };
347
357
 
348
358
  const FallbackSubtitle = ({ children }) => {
349
- return jsx("h3", { className: fallback, children: children });
359
+ return jsx("h3", { style: { margin: 'unset' }, children: children });
350
360
  };
351
361
 
352
362
  const FallbackContent = ({ children }) => {
353
- return jsx("div", { className: fallback, children: children });
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 (const id of modalIds) {
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, className: frame, onClick: onChangeOrder, style: {
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 = css `
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
- pointer-events: none;
631
- }
632
- `;
633
- const active$1 = css `
649
+ }
650
+
651
+ .${background} > * {
652
+ pointer-events: none;
653
+ }
654
+
655
+ .${background}.${active$1} {
634
656
  pointer-events: all;
635
- `;
636
- const visible$1 = css `
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 = css `
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 = css `
800
- display: flex;
801
- align-items: center;
802
- justify-content: center;
803
- position: fixed;
804
- inset: 0;
805
- pointer-events: none;
806
- z-index: 1000;
807
- transition: background-color ease-in-out;
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 &&
@@ -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.1",
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
- "@emotion/css": "^11.0.0",
69
- "@winglet/common-utils": "^0.2.1",
70
- "@winglet/react-utils": "^0.2.1"
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",
@@ -1,2 +0,0 @@
1
- export declare const fallback: string;
2
- export declare const frame: string;