@lerx/promise-modal 0.8.0 → 0.8.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 +1 -2
- package/dist/app/constant.d.ts +1 -0
- package/dist/bootstrap/BootstrapProvider/BootstrapProvider.d.ts +1 -1
- package/dist/components/Presenter/Presenter.d.ts +2 -2
- package/dist/core/handle/prompt.d.ts +3 -2
- package/dist/core/node/ModalNode/PromptNode.d.ts +3 -2
- package/dist/index.cjs +43 -45
- package/dist/index.mjs +43 -45
- package/dist/types/alert.d.ts +7 -5
- package/dist/types/base.d.ts +6 -6
- package/dist/types/confirm.d.ts +8 -6
- package/dist/types/modal.d.ts +19 -13
- package/dist/types/option.d.ts +2 -0
- package/dist/types/prompt.d.ts +15 -13
- package/package.json +2 -2
|
@@ -2,15 +2,14 @@ import type { Fn } from '../@aileron/declare';
|
|
|
2
2
|
import type { Modal } from '../types';
|
|
3
3
|
export declare class ModalManager {
|
|
4
4
|
#private;
|
|
5
|
-
static initialize(): boolean;
|
|
6
5
|
static anchor(options?: {
|
|
7
6
|
tag?: string;
|
|
8
7
|
prefix?: string;
|
|
9
8
|
root?: HTMLElement;
|
|
10
9
|
}): HTMLElement;
|
|
10
|
+
static get anchored(): boolean;
|
|
11
11
|
static get prerender(): Modal[];
|
|
12
12
|
static set openHandler(handler: Fn<[Modal], void>);
|
|
13
|
-
static get unanchored(): boolean;
|
|
14
13
|
static defineStyleSheet(styleId: string, css: string): void;
|
|
15
14
|
static applyStyleSheet(): void;
|
|
16
15
|
static getHashedClassNames(styleId: string): string;
|
package/dist/app/constant.d.ts
CHANGED
|
@@ -114,7 +114,7 @@ import type { BootstrapProviderHandle } from './type';
|
|
|
114
114
|
* - All modals created within this provider share the same configuration
|
|
115
115
|
* - The provider creates a portal for rendering modals outside the React tree
|
|
116
116
|
*/
|
|
117
|
-
export declare const BootstrapProvider: import("react").
|
|
117
|
+
export declare const BootstrapProvider: import("react").NamedExoticComponent<{
|
|
118
118
|
usePathname?: import("../../@aileron/declare").Fn<[], {
|
|
119
119
|
pathname: string;
|
|
120
120
|
}>;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
export declare const Presenter: import("react").MemoExoticComponent<({ modalId }:
|
|
1
|
+
import type { PresenterProps } from '../../types';
|
|
2
|
+
export declare const Presenter: import("react").MemoExoticComponent<({ modalId, getValue, increment }: PresenterProps) => import("react/jsx-runtime").JSX.Element>;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { ComponentType, ReactNode } from 'react';
|
|
2
|
+
import type { Fn } from '../../@aileron/declare';
|
|
2
3
|
import type { BackgroundComponent, FooterOptions, ForegroundComponent, ModalBackground, PromptContentProps, PromptFooterRender, PromptInputProps } from '../../types';
|
|
3
4
|
interface PromptProps<InputValue, BackgroundValue = any> {
|
|
4
5
|
group?: string;
|
|
@@ -6,8 +7,8 @@ interface PromptProps<InputValue, BackgroundValue = any> {
|
|
|
6
7
|
subtitle?: ReactNode;
|
|
7
8
|
content?: ReactNode | ComponentType<PromptContentProps>;
|
|
8
9
|
defaultValue?: InputValue;
|
|
9
|
-
Input:
|
|
10
|
-
disabled?:
|
|
10
|
+
Input: Fn<[props: PromptInputProps<InputValue>], ReactNode>;
|
|
11
|
+
disabled?: Fn<[value: InputValue], boolean>;
|
|
11
12
|
returnOnCancel?: boolean;
|
|
12
13
|
background?: ModalBackground<BackgroundValue>;
|
|
13
14
|
footer?: PromptFooterRender<InputValue> | FooterOptions | false;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { ComponentType, ReactNode } from 'react';
|
|
2
|
+
import type { Fn } from '../../../@aileron/declare';
|
|
2
3
|
import type { FooterOptions, ManagedEntity, PromptContentProps, PromptFooterRender, PromptInputProps, PromptModal } from '../../../types';
|
|
3
4
|
import { AbstractNode } from './AbstractNode';
|
|
4
5
|
type PromptNodeProps<T, B> = PromptModal<T, B> & ManagedEntity;
|
|
@@ -7,8 +8,8 @@ export declare class PromptNode<T, B> extends AbstractNode<T, B> {
|
|
|
7
8
|
readonly type: 'prompt';
|
|
8
9
|
readonly content?: ReactNode | ComponentType<PromptContentProps>;
|
|
9
10
|
readonly defaultValue: T | undefined;
|
|
10
|
-
readonly Input:
|
|
11
|
-
readonly disabled?:
|
|
11
|
+
readonly Input: Fn<[props: PromptInputProps<T>], ReactNode>;
|
|
12
|
+
readonly disabled?: Fn<[value: T], boolean>;
|
|
12
13
|
readonly returnOnCancel?: boolean;
|
|
13
14
|
readonly footer?: PromptFooterRender<T> | FooterOptions | false;
|
|
14
15
|
constructor({ id, group, initiator, type, title, subtitle, content, defaultValue, Input, disabled, returnOnCancel, footer, background, dimmed, manualDestroy, closeOnBackdropClick, resolve, ForegroundComponent, BackgroundComponent, }: PromptNodeProps<T, B>);
|
package/dist/index.cjs
CHANGED
|
@@ -13,20 +13,13 @@ const array = require('@winglet/common-utils/array');
|
|
|
13
13
|
const hoc = require('@winglet/react-utils/hoc');
|
|
14
14
|
const filter = require('@winglet/common-utils/filter');
|
|
15
15
|
const render = require('@winglet/react-utils/render');
|
|
16
|
-
const console = require('@winglet/common-utils/console');
|
|
17
16
|
|
|
18
17
|
class ModalManager {
|
|
19
|
-
static #initialized = false;
|
|
20
|
-
static initialize() {
|
|
21
|
-
if (ModalManager.#initialized)
|
|
22
|
-
return false;
|
|
23
|
-
return (ModalManager.#initialized = true);
|
|
24
|
-
}
|
|
25
18
|
static #anchor = null;
|
|
26
19
|
static #scope = `promise-modal-${lib.getRandomString(36)}`;
|
|
27
20
|
static #hash = hash.polynomialHash(ModalManager.#scope);
|
|
28
21
|
static anchor(options) {
|
|
29
|
-
if (ModalManager.#anchor)
|
|
22
|
+
if (ModalManager.#anchor !== null)
|
|
30
23
|
return ModalManager.#anchor;
|
|
31
24
|
const { tag = 'div', prefix = 'promise-modal', root = document.body, } = options || {};
|
|
32
25
|
const node = document.createElement(tag);
|
|
@@ -36,6 +29,9 @@ class ModalManager {
|
|
|
36
29
|
ModalManager.#anchor = node;
|
|
37
30
|
return node;
|
|
38
31
|
}
|
|
32
|
+
static get anchored() {
|
|
33
|
+
return ModalManager.#anchor !== null;
|
|
34
|
+
}
|
|
39
35
|
static #prerenderList = [];
|
|
40
36
|
static get prerender() {
|
|
41
37
|
return ModalManager.#prerenderList;
|
|
@@ -45,9 +41,6 @@ class ModalManager {
|
|
|
45
41
|
ModalManager.#openHandler = handler;
|
|
46
42
|
ModalManager.#prerenderList = [];
|
|
47
43
|
}
|
|
48
|
-
static get unanchored() {
|
|
49
|
-
return !ModalManager.#anchor;
|
|
50
|
-
}
|
|
51
44
|
static #styleManager = styleManager.styleManagerFactory(ModalManager.#scope);
|
|
52
45
|
static #styleSheetDefinition = new Map();
|
|
53
46
|
static defineStyleSheet(styleId, css) {
|
|
@@ -61,7 +54,6 @@ class ModalManager {
|
|
|
61
54
|
return `${styleId}-${ModalManager.#hash}`;
|
|
62
55
|
}
|
|
63
56
|
static reset() {
|
|
64
|
-
ModalManager.#initialized = false;
|
|
65
57
|
ModalManager.#anchor = null;
|
|
66
58
|
ModalManager.#prerenderList = [];
|
|
67
59
|
ModalManager.#openHandler = (modal) => ModalManager.#prerenderList.push(modal);
|
|
@@ -349,6 +341,7 @@ const nodeFactory = (modal) => {
|
|
|
349
341
|
throw new Error(`Unknown modal: ${modal.type}`, { modal });
|
|
350
342
|
};
|
|
351
343
|
|
|
344
|
+
const DEFAULT_Z_INDEX = 1000;
|
|
352
345
|
const DEFAULT_ANIMATION_DURATION = '300ms';
|
|
353
346
|
const DEFAULT_BACKDROP_COLOR = 'rgba(0, 0, 0, 0.5)';
|
|
354
347
|
|
|
@@ -420,6 +413,7 @@ const FallbackForegroundFrame = react.forwardRef(({ id, onChangeOrder, children
|
|
|
420
413
|
const ConfigurationContext = react.createContext({});
|
|
421
414
|
|
|
422
415
|
const DEFAULT_OPTIONS = {
|
|
416
|
+
zIndex: DEFAULT_Z_INDEX,
|
|
423
417
|
duration: DEFAULT_ANIMATION_DURATION,
|
|
424
418
|
backdrop: DEFAULT_BACKDROP_COLOR,
|
|
425
419
|
closeOnBackdropClick: true,
|
|
@@ -811,21 +805,30 @@ const style$1 = `
|
|
|
811
805
|
.${presenter} {
|
|
812
806
|
position: fixed;
|
|
813
807
|
inset: 0;
|
|
808
|
+
z-index: var(--z-index);
|
|
814
809
|
pointer-events: none;
|
|
815
810
|
overflow: hidden;
|
|
816
811
|
`;
|
|
817
812
|
ModalManager.defineStyleSheet('presenter', style$1);
|
|
818
813
|
|
|
819
|
-
const { increment }
|
|
820
|
-
const Presenter = react.memo(({ modalId }) => {
|
|
814
|
+
const Presenter = react.memo(({ modalId, getValue, increment }) => {
|
|
821
815
|
const ref = react.useRef(null);
|
|
816
|
+
const options = useConfigurationOptions();
|
|
822
817
|
const { modal } = useModal(modalId);
|
|
823
818
|
useSubscribeModal(modal);
|
|
824
|
-
|
|
825
|
-
if (ref.current)
|
|
826
|
-
|
|
827
|
-
|
|
819
|
+
hook.useOnMountLayout(() => {
|
|
820
|
+
if (ref.current === null)
|
|
821
|
+
return;
|
|
822
|
+
ref.current.style.zIndex = '' + (options.zIndex + increment());
|
|
828
823
|
});
|
|
824
|
+
const handleChangeOrder = react.useCallback(() => {
|
|
825
|
+
const element = ref.current;
|
|
826
|
+
if (element === null)
|
|
827
|
+
return;
|
|
828
|
+
if (element.style.zIndex === '' + (options.zIndex + getValue()))
|
|
829
|
+
return;
|
|
830
|
+
element.style.zIndex = '' + (options.zIndex + increment());
|
|
831
|
+
}, [getValue, increment, options.zIndex]);
|
|
829
832
|
return (jsxRuntime.jsxs("div", { ref: ref, className: presenter, children: [jsxRuntime.jsx(BackgroundFrame, { modalId: modalId, onChangeOrder: handleChangeOrder }), jsxRuntime.jsx(ForegroundFrame, { modalId: modalId, onChangeOrder: handleChangeOrder })] }));
|
|
830
833
|
});
|
|
831
834
|
|
|
@@ -838,11 +841,12 @@ const style = `
|
|
|
838
841
|
position: fixed;
|
|
839
842
|
inset: 0;
|
|
840
843
|
pointer-events: none;
|
|
841
|
-
z-index:
|
|
844
|
+
z-index: var(--z-index);
|
|
842
845
|
transition: background-color ease-in-out;
|
|
843
846
|
}`;
|
|
844
847
|
ModalManager.defineStyleSheet('anchor', style);
|
|
845
848
|
|
|
849
|
+
const { getValue, increment, reset } = lib.counterFactory(0);
|
|
846
850
|
const AnchorInner = () => {
|
|
847
851
|
const [version, update] = hook.useVersion();
|
|
848
852
|
const { modalIds, setUpdater } = useModalManagerContext();
|
|
@@ -851,10 +855,13 @@ const AnchorInner = () => {
|
|
|
851
855
|
}, [setUpdater, update]);
|
|
852
856
|
const options = useConfigurationOptions();
|
|
853
857
|
const dimmed = useActiveModalCount(validateDimmable, version);
|
|
858
|
+
if (!dimmed)
|
|
859
|
+
reset();
|
|
854
860
|
return (jsxRuntime.jsx("div", { className: anchor, style: {
|
|
861
|
+
'--z-index': options.zIndex,
|
|
855
862
|
transitionDuration: options.duration,
|
|
856
863
|
backgroundColor: dimmed ? options.backdrop : 'transparent',
|
|
857
|
-
}, children: array.map(modalIds, (id) => (jsxRuntime.jsx(Presenter, { modalId: id }, id))) }));
|
|
864
|
+
}, children: array.map(modalIds, (id) => (jsxRuntime.jsx(Presenter, { modalId: id, getValue: getValue, increment: increment, reset: reset }, id))) }));
|
|
858
865
|
};
|
|
859
866
|
const validateDimmable = (modal) => modal?.visible && modal.dimmed;
|
|
860
867
|
const Anchor = react.memo(hoc.withErrorBoundary(AnchorInner));
|
|
@@ -862,42 +869,33 @@ const Anchor = react.memo(hoc.withErrorBoundary(AnchorInner));
|
|
|
862
869
|
const bootstrap = ({ ForegroundComponent, BackgroundComponent, TitleComponent, SubtitleComponent, ContentComponent, FooterComponent, usePathname, options, context, anchor, }) => reactDom.createPortal(jsxRuntime.jsx(UserDefinedContextProvider, { context: context, children: jsxRuntime.jsx(ConfigurationContextProvider, { ForegroundComponent: ForegroundComponent, BackgroundComponent: BackgroundComponent, TitleComponent: TitleComponent, SubtitleComponent: SubtitleComponent, ContentComponent: ContentComponent, FooterComponent: FooterComponent, options: options, children: jsxRuntime.jsx(ModalManagerContextProvider, { usePathname: usePathname, children: jsxRuntime.jsx(Anchor, {}) }) }) }), anchor);
|
|
863
870
|
|
|
864
871
|
const useInitialize = () => {
|
|
865
|
-
const permitted = react.useRef(ModalManager.initialize());
|
|
866
|
-
const anchorRef = react.useRef(null);
|
|
867
872
|
const [, update] = hook.useVersion();
|
|
868
|
-
const
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
'Nesting ModalProvider will be ignored...',
|
|
878
|
-
], {
|
|
879
|
-
info: 'Something is wrong with the ModalProvider initialization...',
|
|
880
|
-
});
|
|
881
|
-
}, [update]);
|
|
882
|
-
const handleReset = react.useCallback(() => {
|
|
883
|
-
ModalManager.reset();
|
|
884
|
-
}, []);
|
|
873
|
+
const anchorRef = react.useRef(null);
|
|
874
|
+
const handleInitialize = react.useRef((root) => {
|
|
875
|
+
if (ModalManager.anchored)
|
|
876
|
+
return;
|
|
877
|
+
anchorRef.current = ModalManager.anchor({ root });
|
|
878
|
+
ModalManager.applyStyleSheet();
|
|
879
|
+
update();
|
|
880
|
+
});
|
|
881
|
+
const handleReset = react.useRef(() => ModalManager.reset());
|
|
885
882
|
return {
|
|
886
883
|
anchorRef,
|
|
887
|
-
handleInitialize,
|
|
888
|
-
handleReset,
|
|
884
|
+
handleInitialize: handleInitialize.current,
|
|
885
|
+
handleReset: handleReset.current,
|
|
889
886
|
};
|
|
890
887
|
};
|
|
891
888
|
|
|
892
|
-
const BootstrapProvider = react.forwardRef(({ usePathname: useExternalPathname, ForegroundComponent, BackgroundComponent, TitleComponent, SubtitleComponent, ContentComponent, FooterComponent, options, context, children, }, handleRef) => {
|
|
889
|
+
const BootstrapProvider = react.memo(react.forwardRef(({ usePathname: useExternalPathname, ForegroundComponent, BackgroundComponent, TitleComponent, SubtitleComponent, ContentComponent, FooterComponent, options, context, children, }, handleRef) => {
|
|
893
890
|
const usePathname$1 = react.useMemo(() => useExternalPathname || usePathname, [useExternalPathname]);
|
|
894
891
|
const { anchorRef, handleInitialize, handleReset } = useInitialize();
|
|
895
892
|
react.useImperativeHandle(handleRef, () => ({
|
|
896
893
|
initialize: handleInitialize,
|
|
897
894
|
}), [handleInitialize]);
|
|
898
895
|
hook.useOnMount(() => {
|
|
899
|
-
if (handleRef
|
|
900
|
-
|
|
896
|
+
if (handleRef !== null)
|
|
897
|
+
return;
|
|
898
|
+
handleInitialize();
|
|
901
899
|
return () => {
|
|
902
900
|
if (anchorRef.current)
|
|
903
901
|
anchorRef.current.remove();
|
|
@@ -917,7 +915,7 @@ const BootstrapProvider = react.forwardRef(({ usePathname: useExternalPathname,
|
|
|
917
915
|
context,
|
|
918
916
|
anchor: anchorRef.current,
|
|
919
917
|
})] }));
|
|
920
|
-
});
|
|
918
|
+
}));
|
|
921
919
|
|
|
922
920
|
const useBootstrap = ({ usePathname: useExternalPathname, ForegroundComponent, BackgroundComponent, TitleComponent, SubtitleComponent, ContentComponent, FooterComponent, options, context, mode = 'auto', } = {}) => {
|
|
923
921
|
const usePathname$1 = react.useMemo(() => useExternalPathname || usePathname, [useExternalPathname]);
|
package/dist/index.mjs
CHANGED
|
@@ -11,20 +11,13 @@ import { map } from '@winglet/common-utils/array';
|
|
|
11
11
|
import { withErrorBoundary } from '@winglet/react-utils/hoc';
|
|
12
12
|
import { isString, isFunction } from '@winglet/common-utils/filter';
|
|
13
13
|
import { renderComponent } from '@winglet/react-utils/render';
|
|
14
|
-
import { printError } from '@winglet/common-utils/console';
|
|
15
14
|
|
|
16
15
|
class ModalManager {
|
|
17
|
-
static #initialized = false;
|
|
18
|
-
static initialize() {
|
|
19
|
-
if (ModalManager.#initialized)
|
|
20
|
-
return false;
|
|
21
|
-
return (ModalManager.#initialized = true);
|
|
22
|
-
}
|
|
23
16
|
static #anchor = null;
|
|
24
17
|
static #scope = `promise-modal-${getRandomString(36)}`;
|
|
25
18
|
static #hash = polynomialHash(ModalManager.#scope);
|
|
26
19
|
static anchor(options) {
|
|
27
|
-
if (ModalManager.#anchor)
|
|
20
|
+
if (ModalManager.#anchor !== null)
|
|
28
21
|
return ModalManager.#anchor;
|
|
29
22
|
const { tag = 'div', prefix = 'promise-modal', root = document.body, } = options || {};
|
|
30
23
|
const node = document.createElement(tag);
|
|
@@ -34,6 +27,9 @@ class ModalManager {
|
|
|
34
27
|
ModalManager.#anchor = node;
|
|
35
28
|
return node;
|
|
36
29
|
}
|
|
30
|
+
static get anchored() {
|
|
31
|
+
return ModalManager.#anchor !== null;
|
|
32
|
+
}
|
|
37
33
|
static #prerenderList = [];
|
|
38
34
|
static get prerender() {
|
|
39
35
|
return ModalManager.#prerenderList;
|
|
@@ -43,9 +39,6 @@ class ModalManager {
|
|
|
43
39
|
ModalManager.#openHandler = handler;
|
|
44
40
|
ModalManager.#prerenderList = [];
|
|
45
41
|
}
|
|
46
|
-
static get unanchored() {
|
|
47
|
-
return !ModalManager.#anchor;
|
|
48
|
-
}
|
|
49
42
|
static #styleManager = styleManagerFactory(ModalManager.#scope);
|
|
50
43
|
static #styleSheetDefinition = new Map();
|
|
51
44
|
static defineStyleSheet(styleId, css) {
|
|
@@ -59,7 +52,6 @@ class ModalManager {
|
|
|
59
52
|
return `${styleId}-${ModalManager.#hash}`;
|
|
60
53
|
}
|
|
61
54
|
static reset() {
|
|
62
|
-
ModalManager.#initialized = false;
|
|
63
55
|
ModalManager.#anchor = null;
|
|
64
56
|
ModalManager.#prerenderList = [];
|
|
65
57
|
ModalManager.#openHandler = (modal) => ModalManager.#prerenderList.push(modal);
|
|
@@ -347,6 +339,7 @@ const nodeFactory = (modal) => {
|
|
|
347
339
|
throw new Error(`Unknown modal: ${modal.type}`, { modal });
|
|
348
340
|
};
|
|
349
341
|
|
|
342
|
+
const DEFAULT_Z_INDEX = 1000;
|
|
350
343
|
const DEFAULT_ANIMATION_DURATION = '300ms';
|
|
351
344
|
const DEFAULT_BACKDROP_COLOR = 'rgba(0, 0, 0, 0.5)';
|
|
352
345
|
|
|
@@ -418,6 +411,7 @@ const FallbackForegroundFrame = forwardRef(({ id, onChangeOrder, children }, ref
|
|
|
418
411
|
const ConfigurationContext = createContext({});
|
|
419
412
|
|
|
420
413
|
const DEFAULT_OPTIONS = {
|
|
414
|
+
zIndex: DEFAULT_Z_INDEX,
|
|
421
415
|
duration: DEFAULT_ANIMATION_DURATION,
|
|
422
416
|
backdrop: DEFAULT_BACKDROP_COLOR,
|
|
423
417
|
closeOnBackdropClick: true,
|
|
@@ -809,21 +803,30 @@ const style$1 = `
|
|
|
809
803
|
.${presenter} {
|
|
810
804
|
position: fixed;
|
|
811
805
|
inset: 0;
|
|
806
|
+
z-index: var(--z-index);
|
|
812
807
|
pointer-events: none;
|
|
813
808
|
overflow: hidden;
|
|
814
809
|
`;
|
|
815
810
|
ModalManager.defineStyleSheet('presenter', style$1);
|
|
816
811
|
|
|
817
|
-
const { increment }
|
|
818
|
-
const Presenter = memo(({ modalId }) => {
|
|
812
|
+
const Presenter = memo(({ modalId, getValue, increment }) => {
|
|
819
813
|
const ref = useRef(null);
|
|
814
|
+
const options = useConfigurationOptions();
|
|
820
815
|
const { modal } = useModal(modalId);
|
|
821
816
|
useSubscribeModal(modal);
|
|
822
|
-
|
|
823
|
-
if (ref.current)
|
|
824
|
-
|
|
825
|
-
|
|
817
|
+
useOnMountLayout(() => {
|
|
818
|
+
if (ref.current === null)
|
|
819
|
+
return;
|
|
820
|
+
ref.current.style.zIndex = '' + (options.zIndex + increment());
|
|
826
821
|
});
|
|
822
|
+
const handleChangeOrder = useCallback(() => {
|
|
823
|
+
const element = ref.current;
|
|
824
|
+
if (element === null)
|
|
825
|
+
return;
|
|
826
|
+
if (element.style.zIndex === '' + (options.zIndex + getValue()))
|
|
827
|
+
return;
|
|
828
|
+
element.style.zIndex = '' + (options.zIndex + increment());
|
|
829
|
+
}, [getValue, increment, options.zIndex]);
|
|
827
830
|
return (jsxs("div", { ref: ref, className: presenter, children: [jsx(BackgroundFrame, { modalId: modalId, onChangeOrder: handleChangeOrder }), jsx(ForegroundFrame, { modalId: modalId, onChangeOrder: handleChangeOrder })] }));
|
|
828
831
|
});
|
|
829
832
|
|
|
@@ -836,11 +839,12 @@ const style = `
|
|
|
836
839
|
position: fixed;
|
|
837
840
|
inset: 0;
|
|
838
841
|
pointer-events: none;
|
|
839
|
-
z-index:
|
|
842
|
+
z-index: var(--z-index);
|
|
840
843
|
transition: background-color ease-in-out;
|
|
841
844
|
}`;
|
|
842
845
|
ModalManager.defineStyleSheet('anchor', style);
|
|
843
846
|
|
|
847
|
+
const { getValue, increment, reset } = counterFactory(0);
|
|
844
848
|
const AnchorInner = () => {
|
|
845
849
|
const [version, update] = useVersion();
|
|
846
850
|
const { modalIds, setUpdater } = useModalManagerContext();
|
|
@@ -849,10 +853,13 @@ const AnchorInner = () => {
|
|
|
849
853
|
}, [setUpdater, update]);
|
|
850
854
|
const options = useConfigurationOptions();
|
|
851
855
|
const dimmed = useActiveModalCount(validateDimmable, version);
|
|
856
|
+
if (!dimmed)
|
|
857
|
+
reset();
|
|
852
858
|
return (jsx("div", { className: anchor, style: {
|
|
859
|
+
'--z-index': options.zIndex,
|
|
853
860
|
transitionDuration: options.duration,
|
|
854
861
|
backgroundColor: dimmed ? options.backdrop : 'transparent',
|
|
855
|
-
}, children: map(modalIds, (id) => (jsx(Presenter, { modalId: id }, id))) }));
|
|
862
|
+
}, children: map(modalIds, (id) => (jsx(Presenter, { modalId: id, getValue: getValue, increment: increment, reset: reset }, id))) }));
|
|
856
863
|
};
|
|
857
864
|
const validateDimmable = (modal) => modal?.visible && modal.dimmed;
|
|
858
865
|
const Anchor = memo(withErrorBoundary(AnchorInner));
|
|
@@ -860,42 +867,33 @@ const Anchor = memo(withErrorBoundary(AnchorInner));
|
|
|
860
867
|
const bootstrap = ({ ForegroundComponent, BackgroundComponent, TitleComponent, SubtitleComponent, ContentComponent, FooterComponent, usePathname, options, context, anchor, }) => createPortal(jsx(UserDefinedContextProvider, { context: context, children: jsx(ConfigurationContextProvider, { ForegroundComponent: ForegroundComponent, BackgroundComponent: BackgroundComponent, TitleComponent: TitleComponent, SubtitleComponent: SubtitleComponent, ContentComponent: ContentComponent, FooterComponent: FooterComponent, options: options, children: jsx(ModalManagerContextProvider, { usePathname: usePathname, children: jsx(Anchor, {}) }) }) }), anchor);
|
|
861
868
|
|
|
862
869
|
const useInitialize = () => {
|
|
863
|
-
const permitted = useRef(ModalManager.initialize());
|
|
864
|
-
const anchorRef = useRef(null);
|
|
865
870
|
const [, update] = useVersion();
|
|
866
|
-
const
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
'Nesting ModalProvider will be ignored...',
|
|
876
|
-
], {
|
|
877
|
-
info: 'Something is wrong with the ModalProvider initialization...',
|
|
878
|
-
});
|
|
879
|
-
}, [update]);
|
|
880
|
-
const handleReset = useCallback(() => {
|
|
881
|
-
ModalManager.reset();
|
|
882
|
-
}, []);
|
|
871
|
+
const anchorRef = useRef(null);
|
|
872
|
+
const handleInitialize = useRef((root) => {
|
|
873
|
+
if (ModalManager.anchored)
|
|
874
|
+
return;
|
|
875
|
+
anchorRef.current = ModalManager.anchor({ root });
|
|
876
|
+
ModalManager.applyStyleSheet();
|
|
877
|
+
update();
|
|
878
|
+
});
|
|
879
|
+
const handleReset = useRef(() => ModalManager.reset());
|
|
883
880
|
return {
|
|
884
881
|
anchorRef,
|
|
885
|
-
handleInitialize,
|
|
886
|
-
handleReset,
|
|
882
|
+
handleInitialize: handleInitialize.current,
|
|
883
|
+
handleReset: handleReset.current,
|
|
887
884
|
};
|
|
888
885
|
};
|
|
889
886
|
|
|
890
|
-
const BootstrapProvider = forwardRef(({ usePathname: useExternalPathname, ForegroundComponent, BackgroundComponent, TitleComponent, SubtitleComponent, ContentComponent, FooterComponent, options, context, children, }, handleRef) => {
|
|
887
|
+
const BootstrapProvider = memo(forwardRef(({ usePathname: useExternalPathname, ForegroundComponent, BackgroundComponent, TitleComponent, SubtitleComponent, ContentComponent, FooterComponent, options, context, children, }, handleRef) => {
|
|
891
888
|
const usePathname$1 = useMemo(() => useExternalPathname || usePathname, [useExternalPathname]);
|
|
892
889
|
const { anchorRef, handleInitialize, handleReset } = useInitialize();
|
|
893
890
|
useImperativeHandle(handleRef, () => ({
|
|
894
891
|
initialize: handleInitialize,
|
|
895
892
|
}), [handleInitialize]);
|
|
896
893
|
useOnMount(() => {
|
|
897
|
-
if (handleRef
|
|
898
|
-
|
|
894
|
+
if (handleRef !== null)
|
|
895
|
+
return;
|
|
896
|
+
handleInitialize();
|
|
899
897
|
return () => {
|
|
900
898
|
if (anchorRef.current)
|
|
901
899
|
anchorRef.current.remove();
|
|
@@ -915,7 +913,7 @@ const BootstrapProvider = forwardRef(({ usePathname: useExternalPathname, Foregr
|
|
|
915
913
|
context,
|
|
916
914
|
anchor: anchorRef.current,
|
|
917
915
|
})] }));
|
|
918
|
-
});
|
|
916
|
+
}));
|
|
919
917
|
|
|
920
918
|
const useBootstrap = ({ usePathname: useExternalPathname, ForegroundComponent, BackgroundComponent, TitleComponent, SubtitleComponent, ContentComponent, FooterComponent, options, context, mode = 'auto', } = {}) => {
|
|
921
919
|
const usePathname$1 = useMemo(() => useExternalPathname || usePathname, [useExternalPathname]);
|
package/dist/types/alert.d.ts
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import type { ComponentType, ReactNode } from 'react';
|
|
2
|
-
import type { Dictionary } from '../@aileron/declare';
|
|
2
|
+
import type { Dictionary, Fn } from '../@aileron/declare';
|
|
3
3
|
import type { BaseModal, ContentComponentProps, FooterOptions } from './base';
|
|
4
|
-
export type AlertFooterRender<Context extends Dictionary = object> =
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
4
|
+
export type AlertFooterRender<Context extends Dictionary = object> = Fn<[
|
|
5
|
+
props: {
|
|
6
|
+
onConfirm: Fn;
|
|
7
|
+
context: Context;
|
|
8
|
+
}
|
|
9
|
+
], ReactNode>;
|
|
8
10
|
export type AlertContentProps<Context extends Dictionary = object> = Pick<ContentComponentProps<Context>, 'onConfirm'>;
|
|
9
11
|
export interface AlertModal<B = any, Context extends Dictionary = object> extends BaseModal<void, B> {
|
|
10
12
|
type: 'alert';
|
package/dist/types/base.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { ComponentType, PropsWithChildren, ReactNode } from 'react';
|
|
2
|
-
import type { Dictionary } from '../@aileron/declare';
|
|
2
|
+
import type { Dictionary, Fn } from '../@aileron/declare';
|
|
3
3
|
import type { ModalBackground } from './background';
|
|
4
4
|
import type { ModalFrameProps } from './modal';
|
|
5
5
|
export interface BaseModal<T, B> {
|
|
@@ -10,15 +10,15 @@ export interface BaseModal<T, B> {
|
|
|
10
10
|
dimmed?: boolean;
|
|
11
11
|
manualDestroy?: boolean;
|
|
12
12
|
closeOnBackdropClick?: boolean;
|
|
13
|
-
resolve:
|
|
13
|
+
resolve: Fn<[result: T | null]>;
|
|
14
14
|
ForegroundComponent?: ForegroundComponent;
|
|
15
15
|
BackgroundComponent?: BackgroundComponent;
|
|
16
16
|
}
|
|
17
17
|
export type ForegroundComponent = ComponentType<PropsWithChildren<ModalFrameProps>>;
|
|
18
18
|
export type BackgroundComponent = ComponentType<ModalFrameProps>;
|
|
19
19
|
export interface ContentComponentProps<Context extends Dictionary = object> {
|
|
20
|
-
onConfirm:
|
|
21
|
-
onCancel:
|
|
20
|
+
onConfirm: Fn;
|
|
21
|
+
onCancel: Fn;
|
|
22
22
|
context: Context;
|
|
23
23
|
}
|
|
24
24
|
export type WrapperComponentProps<Context extends Dictionary = object> = PropsWithChildren<{
|
|
@@ -36,7 +36,7 @@ export type FooterComponentProps<Context extends Dictionary = object> = {
|
|
|
36
36
|
cancelLabel?: ReactNode;
|
|
37
37
|
hideCancel?: boolean;
|
|
38
38
|
disabled?: boolean;
|
|
39
|
-
onConfirm:
|
|
40
|
-
onCancel?:
|
|
39
|
+
onConfirm: Fn;
|
|
40
|
+
onCancel?: Fn;
|
|
41
41
|
context: Context;
|
|
42
42
|
};
|
package/dist/types/confirm.d.ts
CHANGED
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
import type { ComponentType, ReactNode } from 'react';
|
|
2
|
-
import type { Dictionary } from '../@aileron/declare';
|
|
2
|
+
import type { Dictionary, Fn } from '../@aileron/declare';
|
|
3
3
|
import type { BaseModal, ContentComponentProps, FooterOptions } from './base';
|
|
4
|
-
export type ConfirmFooterRender<Context extends Dictionary = object> =
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
4
|
+
export type ConfirmFooterRender<Context extends Dictionary = object> = Fn<[
|
|
5
|
+
props: {
|
|
6
|
+
onConfirm: Fn;
|
|
7
|
+
onCancel: Fn;
|
|
8
|
+
context: Context;
|
|
9
|
+
}
|
|
10
|
+
], ReactNode>;
|
|
9
11
|
export type ConfirmContentProps<Context extends Dictionary = object> = ContentComponentProps<Context>;
|
|
10
12
|
export interface ConfirmModal<B = any, Context extends Dictionary = object> extends BaseModal<boolean, B> {
|
|
11
13
|
type: 'confirm';
|
package/dist/types/modal.d.ts
CHANGED
|
@@ -19,29 +19,35 @@ export type ModalFrameProps<Context extends Dictionary = object, B = any> = {
|
|
|
19
19
|
manualDestroy: boolean;
|
|
20
20
|
closeOnBackdropClick: boolean;
|
|
21
21
|
background?: ModalBackground<B>;
|
|
22
|
-
onConfirm:
|
|
23
|
-
onClose:
|
|
24
|
-
onChange:
|
|
25
|
-
onDestroy:
|
|
22
|
+
onConfirm: Fn;
|
|
23
|
+
onClose: Fn;
|
|
24
|
+
onChange: Fn<[value: any]>;
|
|
25
|
+
onDestroy: Fn;
|
|
26
26
|
onChangeOrder: Fn;
|
|
27
27
|
context: Context;
|
|
28
28
|
};
|
|
29
|
-
|
|
29
|
+
interface ModalIdProps {
|
|
30
30
|
modalId: ModalNode['id'];
|
|
31
31
|
}
|
|
32
|
+
export interface PresenterProps extends ModalIdProps {
|
|
33
|
+
getValue: Fn<[], number>;
|
|
34
|
+
increment: Fn<[], number>;
|
|
35
|
+
reset: Fn<[], number>;
|
|
36
|
+
}
|
|
32
37
|
export interface ModalLayerProps extends ModalIdProps {
|
|
33
38
|
onChangeOrder: Fn;
|
|
34
39
|
}
|
|
35
40
|
export interface ModalHandlersWithId {
|
|
36
|
-
onConfirm:
|
|
37
|
-
onClose:
|
|
38
|
-
onChange:
|
|
39
|
-
onDestroy:
|
|
41
|
+
onConfirm: Fn<[modalId: ModalNode['id']]>;
|
|
42
|
+
onClose: Fn<[modalId: ModalNode['id']]>;
|
|
43
|
+
onChange: Fn<[modalId: ModalNode['id'], value: any]>;
|
|
44
|
+
onDestroy: Fn<[modalId: ModalNode['id']]>;
|
|
40
45
|
}
|
|
41
46
|
export type ModalActions = {
|
|
42
47
|
modal: ModalNode | undefined;
|
|
43
|
-
onConfirm:
|
|
44
|
-
onClose:
|
|
45
|
-
onChange:
|
|
46
|
-
onDestroy:
|
|
48
|
+
onConfirm: Fn;
|
|
49
|
+
onClose: Fn;
|
|
50
|
+
onChange: Fn<[value: any]>;
|
|
51
|
+
onDestroy: Fn;
|
|
47
52
|
};
|
|
53
|
+
export {};
|
package/dist/types/option.d.ts
CHANGED
package/dist/types/prompt.d.ts
CHANGED
|
@@ -1,20 +1,22 @@
|
|
|
1
1
|
import type { ComponentType, ReactNode } from 'react';
|
|
2
|
-
import type { Dictionary, SetStateFn } from '../@aileron/declare';
|
|
2
|
+
import type { Dictionary, Fn, SetStateFn } from '../@aileron/declare';
|
|
3
3
|
import type { BaseModal, ContentComponentProps, FooterOptions } from './base';
|
|
4
|
-
export type PromptFooterRender<T, Context extends Dictionary = object> =
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
4
|
+
export type PromptFooterRender<T, Context extends Dictionary = object> = Fn<[
|
|
5
|
+
props: {
|
|
6
|
+
value: T | undefined;
|
|
7
|
+
onChange: SetStateFn<T | undefined>;
|
|
8
|
+
onConfirm: Fn;
|
|
9
|
+
onCancel: Fn;
|
|
10
|
+
disabled: boolean;
|
|
11
|
+
context: Context;
|
|
12
|
+
}
|
|
13
|
+
], ReactNode>;
|
|
12
14
|
export interface PromptInputProps<T, Context extends Dictionary = object> {
|
|
13
15
|
value?: T;
|
|
14
16
|
defaultValue?: T;
|
|
15
17
|
onChange: SetStateFn<T | undefined>;
|
|
16
|
-
onConfirm:
|
|
17
|
-
onCancel:
|
|
18
|
+
onConfirm: Fn;
|
|
19
|
+
onCancel: Fn;
|
|
18
20
|
context: Context;
|
|
19
21
|
}
|
|
20
22
|
export type PromptContentProps<Context extends Dictionary = object> = ContentComponentProps<Context>;
|
|
@@ -22,8 +24,8 @@ export interface PromptModal<T = any, B = any, Context extends Dictionary = obje
|
|
|
22
24
|
type: 'prompt';
|
|
23
25
|
content?: ReactNode | ComponentType<PromptContentProps<Context>>;
|
|
24
26
|
defaultValue?: T;
|
|
25
|
-
Input:
|
|
26
|
-
disabled?:
|
|
27
|
+
Input: Fn<[props: PromptInputProps<T, Context>], ReactNode>;
|
|
28
|
+
disabled?: Fn<[value: T | undefined], boolean>;
|
|
27
29
|
returnOnCancel?: boolean;
|
|
28
30
|
footer?: PromptFooterRender<T, Context> | FooterOptions | false;
|
|
29
31
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lerx/promise-modal",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.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",
|
|
@@ -64,7 +64,7 @@
|
|
|
64
64
|
"version:patch": "yarn version patch"
|
|
65
65
|
},
|
|
66
66
|
"dependencies": {
|
|
67
|
-
"@winglet/common-utils": "^0.8.
|
|
67
|
+
"@winglet/common-utils": "^0.8.1",
|
|
68
68
|
"@winglet/react-utils": "^0.8.0",
|
|
69
69
|
"@winglet/style-utils": "^0.8.0"
|
|
70
70
|
},
|