@lerx/promise-modal 0.2.1 → 0.2.2
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 +2 -0
- package/dist/bootstrap/BootstrapProvider/hooks/useInitialize.d.ts +1 -0
- package/dist/components/Anchor/style.d.ts +1 -0
- package/dist/components/Background/style.d.ts +1 -0
- package/dist/components/Foreground/style.d.ts +1 -0
- package/dist/components/Presenter/style.d.ts +1 -0
- package/dist/index.cjs +89 -76
- package/dist/index.mjs +89 -76
- package/package.json +2 -3
- package/dist/components/Anchor/classNames.emotion.d.ts +0 -1
- package/dist/components/Background/classNames.emotion.d.ts +0 -3
- package/dist/components/FallbackComponents/classNames.emotion.d.ts +0 -2
- package/dist/components/Foreground/classNames.emotion.d.ts +0 -3
- package/dist/components/Presenter/classNames.emotion.d.ts +0 -1
|
@@ -11,6 +11,8 @@ 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;
|
|
14
16
|
static reset(): void;
|
|
15
17
|
static open(modal: Modal): void;
|
|
16
18
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const style = "\n[data-anchor] {\n display: flex;\n align-items: center;\n justify-content: center;\n position: fixed;\n inset: 0;\n pointer-events: none;\n z-index: 1000;\n transition: background-color ease-in-out;\n}";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const style = "\n[data-background] {\n display: none;\n position: fixed;\n inset: 0;\n z-index: -999;\n pointer-events: none;\n}\n\n[data-background] > * {\n pointer-events: none;\n}\n\n[data-background][data-active] {\n pointer-events: all;\n}\n\n[data-background][data-visible] {\n display: flex;\n align-items: center;\n justify-content: center;\n}\n";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const style = "\n[data-foreground] {\n pointer-events: none;\n display: none;\n position: fixed;\n inset: 0;\n z-index: 1;\n}\n\n[data-foreground][data-active] > * {\n pointer-events: all;\n}\n\n[data-foreground][data-visible] {\n display: flex !important;\n justify-content: center;\n align-items: center;\n}\n";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const style = "\n[data-presenter] {\n position: fixed;\n inset: 0;\n pointer-events: none;\n overflow: hidden;\n";
|
package/dist/index.cjs
CHANGED
|
@@ -5,7 +5,7 @@ const react = require('react');
|
|
|
5
5
|
const convert = require('@winglet/common-utils/convert');
|
|
6
6
|
const hook = require('@winglet/react-utils/hook');
|
|
7
7
|
const lib = require('@winglet/common-utils/lib');
|
|
8
|
-
const
|
|
8
|
+
const styleManager = require('@winglet/react-utils/style-manager');
|
|
9
9
|
const reactDom = require('react-dom');
|
|
10
10
|
const array = require('@winglet/common-utils/array');
|
|
11
11
|
const hoc = require('@winglet/react-utils/hoc');
|
|
@@ -21,15 +21,14 @@ class ModalManager {
|
|
|
21
21
|
return (ModalManager.#active = true);
|
|
22
22
|
}
|
|
23
23
|
static #anchor = null;
|
|
24
|
+
static #scope = `promise-modal-${lib.getRandomString(36)}`;
|
|
24
25
|
static anchor(options) {
|
|
25
|
-
if (ModalManager.#anchor)
|
|
26
|
-
|
|
27
|
-
if (anchor)
|
|
28
|
-
return anchor;
|
|
29
|
-
}
|
|
26
|
+
if (ModalManager.#anchor)
|
|
27
|
+
return ModalManager.#anchor;
|
|
30
28
|
const { tag = 'div', prefix = 'promise-modal', root = document.body, } = options || {};
|
|
31
29
|
const node = document.createElement(tag);
|
|
32
30
|
node.setAttribute('id', `${prefix}-${lib.getRandomString(36)}`);
|
|
31
|
+
node.setAttribute('data-scope', ModalManager.#scope);
|
|
33
32
|
root.appendChild(node);
|
|
34
33
|
ModalManager.#anchor = node;
|
|
35
34
|
return node;
|
|
@@ -46,11 +45,21 @@ class ModalManager {
|
|
|
46
45
|
static get unanchored() {
|
|
47
46
|
return !ModalManager.#anchor;
|
|
48
47
|
}
|
|
48
|
+
static #styleManager = styleManager.styleManagerFactory(ModalManager.#scope);
|
|
49
|
+
static #styleSheetDefinition = new Map();
|
|
50
|
+
static defineStyleSheet(styleId, css) {
|
|
51
|
+
ModalManager.#styleSheetDefinition.set(styleId, styleManager.compressCss(css));
|
|
52
|
+
}
|
|
53
|
+
static applyStyleSheet() {
|
|
54
|
+
for (const [styleId, css] of ModalManager.#styleSheetDefinition)
|
|
55
|
+
ModalManager.#styleManager(styleId, css, true);
|
|
56
|
+
}
|
|
49
57
|
static reset() {
|
|
50
58
|
ModalManager.#active = false;
|
|
51
59
|
ModalManager.#anchor = null;
|
|
52
60
|
ModalManager.#prerenderList = [];
|
|
53
61
|
ModalManager.#openHandler = (modal) => ModalManager.#prerenderList.push(modal);
|
|
62
|
+
styleManager.destroyScope(ModalManager.#scope);
|
|
54
63
|
}
|
|
55
64
|
static open(modal) {
|
|
56
65
|
ModalManager.#openHandler(modal);
|
|
@@ -329,30 +338,16 @@ const nodeFactory = (modal) => {
|
|
|
329
338
|
const DEFAULT_ANIMATION_DURATION = '300ms';
|
|
330
339
|
const DEFAULT_BACKDROP_COLOR = 'rgba(0, 0, 0, 0.5)';
|
|
331
340
|
|
|
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
341
|
const FallbackTitle = ({ children }) => {
|
|
347
|
-
return jsxRuntime.jsx("h2", {
|
|
342
|
+
return jsxRuntime.jsx("h2", { style: { margin: 'unset' }, children: children });
|
|
348
343
|
};
|
|
349
344
|
|
|
350
345
|
const FallbackSubtitle = ({ children }) => {
|
|
351
|
-
return jsxRuntime.jsx("h3", {
|
|
346
|
+
return jsxRuntime.jsx("h3", { style: { margin: 'unset' }, children: children });
|
|
352
347
|
};
|
|
353
348
|
|
|
354
349
|
const FallbackContent = ({ children }) => {
|
|
355
|
-
return jsxRuntime.jsx("div", {
|
|
350
|
+
return jsxRuntime.jsx("div", { style: { margin: 'unset' }, children: children });
|
|
356
351
|
};
|
|
357
352
|
|
|
358
353
|
const FallbackFooter = ({ confirmLabel, hideConfirm = false, cancelLabel, hideCancel = false, disabled, onConfirm, onCancel, }) => {
|
|
@@ -392,10 +387,18 @@ const FallbackForegroundFrame = react.forwardRef(({ id, onChangeOrder, children
|
|
|
392
387
|
const offset = stacked ? (id % MAX_MODAL_COUNT) * 35 : 0;
|
|
393
388
|
return [level, offset];
|
|
394
389
|
}, [activeCount, id]);
|
|
395
|
-
return (jsxRuntime.jsx("div", { ref: ref,
|
|
390
|
+
return (jsxRuntime.jsx("div", { ref: ref, onClick: onChangeOrder, style: {
|
|
396
391
|
marginBottom: `calc(25vh + ${level}px)`,
|
|
397
392
|
marginLeft: `${level}px`,
|
|
398
393
|
transform: `translate(${offset}px, ${offset}px)`,
|
|
394
|
+
display: 'flex',
|
|
395
|
+
flexDirection: 'column',
|
|
396
|
+
justifyContent: 'center',
|
|
397
|
+
alignItems: 'center',
|
|
398
|
+
backgroundColor: 'white',
|
|
399
|
+
padding: '20px 80px',
|
|
400
|
+
gap: '10px',
|
|
401
|
+
border: '1px solid black',
|
|
399
402
|
}, children: children }));
|
|
400
403
|
});
|
|
401
404
|
|
|
@@ -497,9 +500,6 @@ const ModalManagerContextProvider = react.memo(({ usePathname, children, }) => {
|
|
|
497
500
|
return [...aliveIds, modal.id];
|
|
498
501
|
});
|
|
499
502
|
};
|
|
500
|
-
return () => {
|
|
501
|
-
ModalManager.reset();
|
|
502
|
-
};
|
|
503
503
|
});
|
|
504
504
|
react.useLayoutEffect(() => {
|
|
505
505
|
for (const id of modalIdsRef.current) {
|
|
@@ -622,25 +622,31 @@ const usePathname = () => {
|
|
|
622
622
|
return { pathname };
|
|
623
623
|
};
|
|
624
624
|
|
|
625
|
-
const
|
|
625
|
+
const style$3 = `
|
|
626
|
+
[data-background] {
|
|
626
627
|
display: none;
|
|
627
628
|
position: fixed;
|
|
628
629
|
inset: 0;
|
|
629
630
|
z-index: -999;
|
|
630
631
|
pointer-events: none;
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
632
|
+
}
|
|
633
|
+
|
|
634
|
+
[data-background] > * {
|
|
635
|
+
pointer-events: none;
|
|
636
|
+
}
|
|
637
|
+
|
|
638
|
+
[data-background][data-active] {
|
|
636
639
|
pointer-events: all;
|
|
637
|
-
|
|
638
|
-
|
|
640
|
+
}
|
|
641
|
+
|
|
642
|
+
[data-background][data-visible] {
|
|
639
643
|
display: flex;
|
|
640
644
|
align-items: center;
|
|
641
645
|
justify-content: center;
|
|
646
|
+
}
|
|
642
647
|
`;
|
|
643
648
|
|
|
649
|
+
ModalManager.defineStyleSheet('background', style$3);
|
|
644
650
|
const BackgroundFrame = ({ modalId, onChangeOrder, }) => {
|
|
645
651
|
const { BackgroundComponent } = useConfigurationContext();
|
|
646
652
|
const { context: userDefinedContext } = useUserDefinedContext();
|
|
@@ -653,30 +659,9 @@ const BackgroundFrame = ({ modalId, onChangeOrder, }) => {
|
|
|
653
659
|
const Background = react.useMemo(() => modal?.BackgroundComponent || BackgroundComponent, [BackgroundComponent, modal]);
|
|
654
660
|
if (!modal)
|
|
655
661
|
return null;
|
|
656
|
-
return (jsxRuntime.jsx("div", {
|
|
657
|
-
[visible$1]: modal.manualDestroy ? modal.alive : modal.visible,
|
|
658
|
-
[active$1]: modal.closeOnBackdropClick && modal.visible,
|
|
659
|
-
}), onClick: handleClose, children: Background && (jsxRuntime.jsx(Background, { id: modal.id, type: modal.type, alive: modal.alive, visible: modal.visible, initiator: modal.initiator, manualDestroy: modal.manualDestroy, closeOnBackdropClick: modal.closeOnBackdropClick, background: modal.background, onChange: onChange, onConfirm: onConfirm, onClose: onClose, onDestroy: onDestroy, onChangeOrder: onChangeOrder, context: userDefinedContext })) }));
|
|
662
|
+
return (jsxRuntime.jsx("div", { "data-background": true, "data-active": styleManager.dataCondition(modal.closeOnBackdropClick && modal.visible), "data-visible": styleManager.dataCondition(modal.manualDestroy ? modal.alive : modal.visible), 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
663
|
};
|
|
661
664
|
|
|
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
665
|
const AlertInner = react.memo(({ modal, handlers }) => {
|
|
681
666
|
const { title, subtitle, content, footer } = react.useMemo(() => modal, [modal]);
|
|
682
667
|
const { context: userDefinedContext } = useUserDefinedContext();
|
|
@@ -754,6 +739,27 @@ const PromptInner = react.memo(({ modal, handlers }) => {
|
|
|
754
739
|
})) : (jsxRuntime.jsx(FooterComponent, { disabled: disabled, onConfirm: handleConfirm, onCancel: handleClose, confirmLabel: footer?.confirm, cancelLabel: footer?.cancel, hideConfirm: footer?.hideConfirm, hideCancel: footer?.hideCancel, context: userDefinedContext })))] }));
|
|
755
740
|
});
|
|
756
741
|
|
|
742
|
+
const style$2 = `
|
|
743
|
+
[data-foreground] {
|
|
744
|
+
pointer-events: none;
|
|
745
|
+
display: none;
|
|
746
|
+
position: fixed;
|
|
747
|
+
inset: 0;
|
|
748
|
+
z-index: 1;
|
|
749
|
+
}
|
|
750
|
+
|
|
751
|
+
[data-foreground][data-active] > * {
|
|
752
|
+
pointer-events: all;
|
|
753
|
+
}
|
|
754
|
+
|
|
755
|
+
[data-foreground][data-visible] {
|
|
756
|
+
display: flex !important;
|
|
757
|
+
justify-content: center;
|
|
758
|
+
align-items: center;
|
|
759
|
+
}
|
|
760
|
+
`;
|
|
761
|
+
|
|
762
|
+
ModalManager.defineStyleSheet('foreground', style$2);
|
|
757
763
|
const ForegroundFrame = ({ modalId, onChangeOrder, }) => {
|
|
758
764
|
const { ForegroundComponent } = useConfigurationContext();
|
|
759
765
|
const { context: userDefinedContext } = useUserDefinedContext();
|
|
@@ -761,10 +767,7 @@ const ForegroundFrame = ({ modalId, onChangeOrder, }) => {
|
|
|
761
767
|
const Foreground = react.useMemo(() => modal?.ForegroundComponent || ForegroundComponent, [ForegroundComponent, modal]);
|
|
762
768
|
if (!modal)
|
|
763
769
|
return null;
|
|
764
|
-
return (jsxRuntime.jsx("div", {
|
|
765
|
-
[visible]: modal.manualDestroy ? modal.alive : modal.visible,
|
|
766
|
-
[active]: modal.visible,
|
|
767
|
-
}), children: jsxRuntime.jsxs(Foreground, { id: modal.id, type: modal.type, alive: modal.alive, visible: modal.visible, initiator: modal.initiator, manualDestroy: modal.manualDestroy, closeOnBackdropClick: modal.closeOnBackdropClick, background: modal.background, onChange: onChange, onConfirm: onConfirm, onClose: onClose, onDestroy: onDestroy, onChangeOrder: onChangeOrder, context: userDefinedContext, children: [modal.type === 'alert' && (jsxRuntime.jsx(AlertInner, { modal: modal, handlers: { onConfirm } })), modal.type === 'confirm' && (jsxRuntime.jsx(ConfirmInner, { modal: modal, handlers: { onConfirm, onClose } })), modal.type === 'prompt' && (jsxRuntime.jsx(PromptInner, { modal: modal, handlers: { onChange, onConfirm, onClose } }))] }) }));
|
|
770
|
+
return (jsxRuntime.jsx("div", { "data-foreground": true, "data-active": styleManager.dataCondition(modal.visible), "data-visible": styleManager.dataCondition(modal.manualDestroy ? modal.alive : modal.visible), 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
771
|
};
|
|
769
772
|
|
|
770
773
|
const useSubscribeModal = (modal) => {
|
|
@@ -778,13 +781,15 @@ const useSubscribeModal = (modal) => {
|
|
|
778
781
|
return version;
|
|
779
782
|
};
|
|
780
783
|
|
|
781
|
-
const
|
|
784
|
+
const style$1 = `
|
|
785
|
+
[data-presenter] {
|
|
782
786
|
position: fixed;
|
|
783
787
|
inset: 0;
|
|
784
788
|
pointer-events: none;
|
|
785
789
|
overflow: hidden;
|
|
786
790
|
`;
|
|
787
791
|
|
|
792
|
+
ModalManager.defineStyleSheet('presenter', style$1);
|
|
788
793
|
const { increment } = lib.counterFactory(1);
|
|
789
794
|
const Presenter = react.memo(({ modalId }) => {
|
|
790
795
|
const ref = react.useRef(null);
|
|
@@ -795,20 +800,22 @@ const Presenter = react.memo(({ modalId }) => {
|
|
|
795
800
|
ref.current.style.zIndex = `${increment()}`;
|
|
796
801
|
}
|
|
797
802
|
});
|
|
798
|
-
return (jsxRuntime.jsxs("div", { ref: ref,
|
|
803
|
+
return (jsxRuntime.jsxs("div", { ref: ref, "data-presenter": true, children: [jsxRuntime.jsx(BackgroundFrame, { modalId: modalId, onChangeOrder: handleChangeOrder }), jsxRuntime.jsx(ForegroundFrame, { modalId: modalId, onChangeOrder: handleChangeOrder })] }));
|
|
799
804
|
});
|
|
800
805
|
|
|
801
|
-
const
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
806
|
+
const style = `
|
|
807
|
+
[data-anchor] {
|
|
808
|
+
display: flex;
|
|
809
|
+
align-items: center;
|
|
810
|
+
justify-content: center;
|
|
811
|
+
position: fixed;
|
|
812
|
+
inset: 0;
|
|
813
|
+
pointer-events: none;
|
|
814
|
+
z-index: 1000;
|
|
815
|
+
transition: background-color ease-in-out;
|
|
816
|
+
}`;
|
|
817
|
+
|
|
818
|
+
ModalManager.defineStyleSheet('anchor', style);
|
|
812
819
|
const AnchorInner = () => {
|
|
813
820
|
const [version, update] = hook.useVersion();
|
|
814
821
|
const { modalIds, setUpdater } = useModalManagerContext();
|
|
@@ -817,7 +824,7 @@ const AnchorInner = () => {
|
|
|
817
824
|
}, [setUpdater, update]);
|
|
818
825
|
const options = useConfigurationOptions();
|
|
819
826
|
const dimmed = useActiveModalCount(validateDimmable, version);
|
|
820
|
-
return (jsxRuntime.jsx("div", {
|
|
827
|
+
return (jsxRuntime.jsx("div", { "data-anchor": true, style: {
|
|
821
828
|
transitionDuration: options.duration,
|
|
822
829
|
backgroundColor: dimmed ? options.backdrop : 'transparent',
|
|
823
830
|
}, children: array.map(modalIds, (id) => (jsxRuntime.jsx(Presenter, { modalId: id }, id))) }));
|
|
@@ -834,6 +841,7 @@ const useInitialize = () => {
|
|
|
834
841
|
const handleInitialize = react.useCallback((root) => {
|
|
835
842
|
if (permitted.current) {
|
|
836
843
|
anchorRef.current = ModalManager.anchor({ root });
|
|
844
|
+
ModalManager.applyStyleSheet();
|
|
837
845
|
update();
|
|
838
846
|
}
|
|
839
847
|
else
|
|
@@ -844,15 +852,19 @@ const useInitialize = () => {
|
|
|
844
852
|
info: 'Something is wrong with the ModalProvider initialization...',
|
|
845
853
|
});
|
|
846
854
|
}, [update]);
|
|
855
|
+
const handleReset = react.useCallback(() => {
|
|
856
|
+
ModalManager.reset();
|
|
857
|
+
}, []);
|
|
847
858
|
return {
|
|
848
859
|
anchorRef,
|
|
849
860
|
handleInitialize,
|
|
861
|
+
handleReset,
|
|
850
862
|
};
|
|
851
863
|
};
|
|
852
864
|
|
|
853
865
|
const BootstrapProvider = react.forwardRef(({ usePathname: useExternalPathname, ForegroundComponent, BackgroundComponent, TitleComponent, SubtitleComponent, ContentComponent, FooterComponent, options, context, children, }, handleRef) => {
|
|
854
866
|
const usePathname$1 = react.useMemo(() => useExternalPathname || usePathname, [useExternalPathname]);
|
|
855
|
-
const { anchorRef, handleInitialize } = useInitialize();
|
|
867
|
+
const { anchorRef, handleInitialize, handleReset } = useInitialize();
|
|
856
868
|
react.useImperativeHandle(handleRef, () => ({
|
|
857
869
|
initialize: handleInitialize,
|
|
858
870
|
}), [handleInitialize]);
|
|
@@ -862,6 +874,7 @@ const BootstrapProvider = react.forwardRef(({ usePathname: useExternalPathname,
|
|
|
862
874
|
return () => {
|
|
863
875
|
if (anchorRef.current)
|
|
864
876
|
anchorRef.current.remove();
|
|
877
|
+
handleReset();
|
|
865
878
|
};
|
|
866
879
|
});
|
|
867
880
|
return (jsxRuntime.jsxs(react.Fragment, { children: [children, anchorRef.current &&
|
package/dist/index.mjs
CHANGED
|
@@ -3,7 +3,7 @@ import { createContext, useContext, useMemo, forwardRef, memo, useRef, useState,
|
|
|
3
3
|
import { convertMsFromDuration } from '@winglet/common-utils/convert';
|
|
4
4
|
import { useReference, useOnMountLayout, useHandle, useVersion, useOnMount } from '@winglet/react-utils/hook';
|
|
5
5
|
import { getRandomString, counterFactory } from '@winglet/common-utils/lib';
|
|
6
|
-
import {
|
|
6
|
+
import { styleManagerFactory, compressCss, destroyScope, dataCondition } from '@winglet/react-utils/style-manager';
|
|
7
7
|
import { createPortal } from 'react-dom';
|
|
8
8
|
import { map } from '@winglet/common-utils/array';
|
|
9
9
|
import { withErrorBoundary } from '@winglet/react-utils/hoc';
|
|
@@ -19,15 +19,14 @@ class ModalManager {
|
|
|
19
19
|
return (ModalManager.#active = true);
|
|
20
20
|
}
|
|
21
21
|
static #anchor = null;
|
|
22
|
+
static #scope = `promise-modal-${getRandomString(36)}`;
|
|
22
23
|
static anchor(options) {
|
|
23
|
-
if (ModalManager.#anchor)
|
|
24
|
-
|
|
25
|
-
if (anchor)
|
|
26
|
-
return anchor;
|
|
27
|
-
}
|
|
24
|
+
if (ModalManager.#anchor)
|
|
25
|
+
return ModalManager.#anchor;
|
|
28
26
|
const { tag = 'div', prefix = 'promise-modal', root = document.body, } = options || {};
|
|
29
27
|
const node = document.createElement(tag);
|
|
30
28
|
node.setAttribute('id', `${prefix}-${getRandomString(36)}`);
|
|
29
|
+
node.setAttribute('data-scope', ModalManager.#scope);
|
|
31
30
|
root.appendChild(node);
|
|
32
31
|
ModalManager.#anchor = node;
|
|
33
32
|
return node;
|
|
@@ -44,11 +43,21 @@ class ModalManager {
|
|
|
44
43
|
static get unanchored() {
|
|
45
44
|
return !ModalManager.#anchor;
|
|
46
45
|
}
|
|
46
|
+
static #styleManager = styleManagerFactory(ModalManager.#scope);
|
|
47
|
+
static #styleSheetDefinition = new Map();
|
|
48
|
+
static defineStyleSheet(styleId, css) {
|
|
49
|
+
ModalManager.#styleSheetDefinition.set(styleId, compressCss(css));
|
|
50
|
+
}
|
|
51
|
+
static applyStyleSheet() {
|
|
52
|
+
for (const [styleId, css] of ModalManager.#styleSheetDefinition)
|
|
53
|
+
ModalManager.#styleManager(styleId, css, true);
|
|
54
|
+
}
|
|
47
55
|
static reset() {
|
|
48
56
|
ModalManager.#active = false;
|
|
49
57
|
ModalManager.#anchor = null;
|
|
50
58
|
ModalManager.#prerenderList = [];
|
|
51
59
|
ModalManager.#openHandler = (modal) => ModalManager.#prerenderList.push(modal);
|
|
60
|
+
destroyScope(ModalManager.#scope);
|
|
52
61
|
}
|
|
53
62
|
static open(modal) {
|
|
54
63
|
ModalManager.#openHandler(modal);
|
|
@@ -327,30 +336,16 @@ const nodeFactory = (modal) => {
|
|
|
327
336
|
const DEFAULT_ANIMATION_DURATION = '300ms';
|
|
328
337
|
const DEFAULT_BACKDROP_COLOR = 'rgba(0, 0, 0, 0.5)';
|
|
329
338
|
|
|
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
339
|
const FallbackTitle = ({ children }) => {
|
|
345
|
-
return jsx("h2", {
|
|
340
|
+
return jsx("h2", { style: { margin: 'unset' }, children: children });
|
|
346
341
|
};
|
|
347
342
|
|
|
348
343
|
const FallbackSubtitle = ({ children }) => {
|
|
349
|
-
return jsx("h3", {
|
|
344
|
+
return jsx("h3", { style: { margin: 'unset' }, children: children });
|
|
350
345
|
};
|
|
351
346
|
|
|
352
347
|
const FallbackContent = ({ children }) => {
|
|
353
|
-
return jsx("div", {
|
|
348
|
+
return jsx("div", { style: { margin: 'unset' }, children: children });
|
|
354
349
|
};
|
|
355
350
|
|
|
356
351
|
const FallbackFooter = ({ confirmLabel, hideConfirm = false, cancelLabel, hideCancel = false, disabled, onConfirm, onCancel, }) => {
|
|
@@ -390,10 +385,18 @@ const FallbackForegroundFrame = forwardRef(({ id, onChangeOrder, children }, ref
|
|
|
390
385
|
const offset = stacked ? (id % MAX_MODAL_COUNT) * 35 : 0;
|
|
391
386
|
return [level, offset];
|
|
392
387
|
}, [activeCount, id]);
|
|
393
|
-
return (jsx("div", { ref: ref,
|
|
388
|
+
return (jsx("div", { ref: ref, onClick: onChangeOrder, style: {
|
|
394
389
|
marginBottom: `calc(25vh + ${level}px)`,
|
|
395
390
|
marginLeft: `${level}px`,
|
|
396
391
|
transform: `translate(${offset}px, ${offset}px)`,
|
|
392
|
+
display: 'flex',
|
|
393
|
+
flexDirection: 'column',
|
|
394
|
+
justifyContent: 'center',
|
|
395
|
+
alignItems: 'center',
|
|
396
|
+
backgroundColor: 'white',
|
|
397
|
+
padding: '20px 80px',
|
|
398
|
+
gap: '10px',
|
|
399
|
+
border: '1px solid black',
|
|
397
400
|
}, children: children }));
|
|
398
401
|
});
|
|
399
402
|
|
|
@@ -495,9 +498,6 @@ const ModalManagerContextProvider = memo(({ usePathname, children, }) => {
|
|
|
495
498
|
return [...aliveIds, modal.id];
|
|
496
499
|
});
|
|
497
500
|
};
|
|
498
|
-
return () => {
|
|
499
|
-
ModalManager.reset();
|
|
500
|
-
};
|
|
501
501
|
});
|
|
502
502
|
useLayoutEffect(() => {
|
|
503
503
|
for (const id of modalIdsRef.current) {
|
|
@@ -620,25 +620,31 @@ const usePathname = () => {
|
|
|
620
620
|
return { pathname };
|
|
621
621
|
};
|
|
622
622
|
|
|
623
|
-
const
|
|
623
|
+
const style$3 = `
|
|
624
|
+
[data-background] {
|
|
624
625
|
display: none;
|
|
625
626
|
position: fixed;
|
|
626
627
|
inset: 0;
|
|
627
628
|
z-index: -999;
|
|
628
629
|
pointer-events: none;
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
630
|
+
}
|
|
631
|
+
|
|
632
|
+
[data-background] > * {
|
|
633
|
+
pointer-events: none;
|
|
634
|
+
}
|
|
635
|
+
|
|
636
|
+
[data-background][data-active] {
|
|
634
637
|
pointer-events: all;
|
|
635
|
-
|
|
636
|
-
|
|
638
|
+
}
|
|
639
|
+
|
|
640
|
+
[data-background][data-visible] {
|
|
637
641
|
display: flex;
|
|
638
642
|
align-items: center;
|
|
639
643
|
justify-content: center;
|
|
644
|
+
}
|
|
640
645
|
`;
|
|
641
646
|
|
|
647
|
+
ModalManager.defineStyleSheet('background', style$3);
|
|
642
648
|
const BackgroundFrame = ({ modalId, onChangeOrder, }) => {
|
|
643
649
|
const { BackgroundComponent } = useConfigurationContext();
|
|
644
650
|
const { context: userDefinedContext } = useUserDefinedContext();
|
|
@@ -651,30 +657,9 @@ const BackgroundFrame = ({ modalId, onChangeOrder, }) => {
|
|
|
651
657
|
const Background = useMemo(() => modal?.BackgroundComponent || BackgroundComponent, [BackgroundComponent, modal]);
|
|
652
658
|
if (!modal)
|
|
653
659
|
return null;
|
|
654
|
-
return (jsx("div", {
|
|
655
|
-
[visible$1]: modal.manualDestroy ? modal.alive : modal.visible,
|
|
656
|
-
[active$1]: modal.closeOnBackdropClick && modal.visible,
|
|
657
|
-
}), 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 })) }));
|
|
660
|
+
return (jsx("div", { "data-background": true, "data-active": dataCondition(modal.closeOnBackdropClick && modal.visible), "data-visible": dataCondition(modal.manualDestroy ? modal.alive : modal.visible), 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
661
|
};
|
|
659
662
|
|
|
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
663
|
const AlertInner = memo(({ modal, handlers }) => {
|
|
679
664
|
const { title, subtitle, content, footer } = useMemo(() => modal, [modal]);
|
|
680
665
|
const { context: userDefinedContext } = useUserDefinedContext();
|
|
@@ -752,6 +737,27 @@ const PromptInner = memo(({ modal, handlers }) => {
|
|
|
752
737
|
})) : (jsx(FooterComponent, { disabled: disabled, onConfirm: handleConfirm, onCancel: handleClose, confirmLabel: footer?.confirm, cancelLabel: footer?.cancel, hideConfirm: footer?.hideConfirm, hideCancel: footer?.hideCancel, context: userDefinedContext })))] }));
|
|
753
738
|
});
|
|
754
739
|
|
|
740
|
+
const style$2 = `
|
|
741
|
+
[data-foreground] {
|
|
742
|
+
pointer-events: none;
|
|
743
|
+
display: none;
|
|
744
|
+
position: fixed;
|
|
745
|
+
inset: 0;
|
|
746
|
+
z-index: 1;
|
|
747
|
+
}
|
|
748
|
+
|
|
749
|
+
[data-foreground][data-active] > * {
|
|
750
|
+
pointer-events: all;
|
|
751
|
+
}
|
|
752
|
+
|
|
753
|
+
[data-foreground][data-visible] {
|
|
754
|
+
display: flex !important;
|
|
755
|
+
justify-content: center;
|
|
756
|
+
align-items: center;
|
|
757
|
+
}
|
|
758
|
+
`;
|
|
759
|
+
|
|
760
|
+
ModalManager.defineStyleSheet('foreground', style$2);
|
|
755
761
|
const ForegroundFrame = ({ modalId, onChangeOrder, }) => {
|
|
756
762
|
const { ForegroundComponent } = useConfigurationContext();
|
|
757
763
|
const { context: userDefinedContext } = useUserDefinedContext();
|
|
@@ -759,10 +765,7 @@ const ForegroundFrame = ({ modalId, onChangeOrder, }) => {
|
|
|
759
765
|
const Foreground = useMemo(() => modal?.ForegroundComponent || ForegroundComponent, [ForegroundComponent, modal]);
|
|
760
766
|
if (!modal)
|
|
761
767
|
return null;
|
|
762
|
-
return (jsx("div", {
|
|
763
|
-
[visible]: modal.manualDestroy ? modal.alive : modal.visible,
|
|
764
|
-
[active]: modal.visible,
|
|
765
|
-
}), 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 } }))] }) }));
|
|
768
|
+
return (jsx("div", { "data-foreground": true, "data-active": dataCondition(modal.visible), "data-visible": dataCondition(modal.manualDestroy ? modal.alive : modal.visible), 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
769
|
};
|
|
767
770
|
|
|
768
771
|
const useSubscribeModal = (modal) => {
|
|
@@ -776,13 +779,15 @@ const useSubscribeModal = (modal) => {
|
|
|
776
779
|
return version;
|
|
777
780
|
};
|
|
778
781
|
|
|
779
|
-
const
|
|
782
|
+
const style$1 = `
|
|
783
|
+
[data-presenter] {
|
|
780
784
|
position: fixed;
|
|
781
785
|
inset: 0;
|
|
782
786
|
pointer-events: none;
|
|
783
787
|
overflow: hidden;
|
|
784
788
|
`;
|
|
785
789
|
|
|
790
|
+
ModalManager.defineStyleSheet('presenter', style$1);
|
|
786
791
|
const { increment } = counterFactory(1);
|
|
787
792
|
const Presenter = memo(({ modalId }) => {
|
|
788
793
|
const ref = useRef(null);
|
|
@@ -793,20 +798,22 @@ const Presenter = memo(({ modalId }) => {
|
|
|
793
798
|
ref.current.style.zIndex = `${increment()}`;
|
|
794
799
|
}
|
|
795
800
|
});
|
|
796
|
-
return (jsxs("div", { ref: ref,
|
|
801
|
+
return (jsxs("div", { ref: ref, "data-presenter": true, children: [jsx(BackgroundFrame, { modalId: modalId, onChangeOrder: handleChangeOrder }), jsx(ForegroundFrame, { modalId: modalId, onChangeOrder: handleChangeOrder })] }));
|
|
797
802
|
});
|
|
798
803
|
|
|
799
|
-
const
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
804
|
+
const style = `
|
|
805
|
+
[data-anchor] {
|
|
806
|
+
display: flex;
|
|
807
|
+
align-items: center;
|
|
808
|
+
justify-content: center;
|
|
809
|
+
position: fixed;
|
|
810
|
+
inset: 0;
|
|
811
|
+
pointer-events: none;
|
|
812
|
+
z-index: 1000;
|
|
813
|
+
transition: background-color ease-in-out;
|
|
814
|
+
}`;
|
|
815
|
+
|
|
816
|
+
ModalManager.defineStyleSheet('anchor', style);
|
|
810
817
|
const AnchorInner = () => {
|
|
811
818
|
const [version, update] = useVersion();
|
|
812
819
|
const { modalIds, setUpdater } = useModalManagerContext();
|
|
@@ -815,7 +822,7 @@ const AnchorInner = () => {
|
|
|
815
822
|
}, [setUpdater, update]);
|
|
816
823
|
const options = useConfigurationOptions();
|
|
817
824
|
const dimmed = useActiveModalCount(validateDimmable, version);
|
|
818
|
-
return (jsx("div", {
|
|
825
|
+
return (jsx("div", { "data-anchor": true, style: {
|
|
819
826
|
transitionDuration: options.duration,
|
|
820
827
|
backgroundColor: dimmed ? options.backdrop : 'transparent',
|
|
821
828
|
}, children: map(modalIds, (id) => (jsx(Presenter, { modalId: id }, id))) }));
|
|
@@ -832,6 +839,7 @@ const useInitialize = () => {
|
|
|
832
839
|
const handleInitialize = useCallback((root) => {
|
|
833
840
|
if (permitted.current) {
|
|
834
841
|
anchorRef.current = ModalManager.anchor({ root });
|
|
842
|
+
ModalManager.applyStyleSheet();
|
|
835
843
|
update();
|
|
836
844
|
}
|
|
837
845
|
else
|
|
@@ -842,15 +850,19 @@ const useInitialize = () => {
|
|
|
842
850
|
info: 'Something is wrong with the ModalProvider initialization...',
|
|
843
851
|
});
|
|
844
852
|
}, [update]);
|
|
853
|
+
const handleReset = useCallback(() => {
|
|
854
|
+
ModalManager.reset();
|
|
855
|
+
}, []);
|
|
845
856
|
return {
|
|
846
857
|
anchorRef,
|
|
847
858
|
handleInitialize,
|
|
859
|
+
handleReset,
|
|
848
860
|
};
|
|
849
861
|
};
|
|
850
862
|
|
|
851
863
|
const BootstrapProvider = forwardRef(({ usePathname: useExternalPathname, ForegroundComponent, BackgroundComponent, TitleComponent, SubtitleComponent, ContentComponent, FooterComponent, options, context, children, }, handleRef) => {
|
|
852
864
|
const usePathname$1 = useMemo(() => useExternalPathname || usePathname, [useExternalPathname]);
|
|
853
|
-
const { anchorRef, handleInitialize } = useInitialize();
|
|
865
|
+
const { anchorRef, handleInitialize, handleReset } = useInitialize();
|
|
854
866
|
useImperativeHandle(handleRef, () => ({
|
|
855
867
|
initialize: handleInitialize,
|
|
856
868
|
}), [handleInitialize]);
|
|
@@ -860,6 +872,7 @@ const BootstrapProvider = forwardRef(({ usePathname: useExternalPathname, Foregr
|
|
|
860
872
|
return () => {
|
|
861
873
|
if (anchorRef.current)
|
|
862
874
|
anchorRef.current.remove();
|
|
875
|
+
handleReset();
|
|
863
876
|
};
|
|
864
877
|
});
|
|
865
878
|
return (jsxs(Fragment, { children: [children, anchorRef.current &&
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lerx/promise-modal",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.2",
|
|
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,8 @@
|
|
|
65
65
|
"version:patch": "yarn version patch"
|
|
66
66
|
},
|
|
67
67
|
"dependencies": {
|
|
68
|
-
"@emotion/css": "^11.0.0",
|
|
69
68
|
"@winglet/common-utils": "^0.2.1",
|
|
70
|
-
"@winglet/react-utils": "^0.2.
|
|
69
|
+
"@winglet/react-utils": "^0.2.2"
|
|
71
70
|
},
|
|
72
71
|
"devDependencies": {
|
|
73
72
|
"@chromatic-com/storybook": "^3.2.6",
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export declare const anchor: string;
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export declare const presenter: string;
|