@trackunit/react-modal 2.2.7 → 2.2.8
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/index.cjs.js +54 -26
- package/index.esm.js +54 -26
- package/package.json +1 -1
package/index.cjs.js
CHANGED
|
@@ -326,6 +326,12 @@ const Modal = ({ children, container, dismiss, isOpen, mode, requestClose, role
|
|
|
326
326
|
// In card mode, there is no close animation so notify useModal immediately
|
|
327
327
|
// so it can call closeModal() without delay.
|
|
328
328
|
// In sheet mode, Sheet's onCloseComplete handles this instead.
|
|
329
|
+
//
|
|
330
|
+
// Must stay a passive effect (useWatch): useModal arms the close safety
|
|
331
|
+
// timeout in a layout effect, which has to flush before onCloseComplete
|
|
332
|
+
// cancels it. Moving this to a layout effect would run it first (child
|
|
333
|
+
// effects run before parent effects within a phase), leaving the timeout
|
|
334
|
+
// armed with nothing to cancel it.
|
|
329
335
|
reactComponents.useWatch({
|
|
330
336
|
value: isOpen,
|
|
331
337
|
onChange: (current, prev) => {
|
|
@@ -1014,33 +1020,55 @@ const useModal = (props) => {
|
|
|
1014
1020
|
void closeModal();
|
|
1015
1021
|
}
|
|
1016
1022
|
}, [stopCloseTimeout, closeModal]);
|
|
1017
|
-
//
|
|
1018
|
-
//
|
|
1019
|
-
//
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
if (result instanceof Promise) {
|
|
1029
|
-
setOpenDeferred(true);
|
|
1030
|
-
void result.then(() => {
|
|
1031
|
-
if (openIdRef.current === id) {
|
|
1032
|
-
setOpenDeferred(false);
|
|
1033
|
-
}
|
|
1034
|
-
});
|
|
1023
|
+
// Asks the host iframe to resize to fullscreen. While the resize is running,
|
|
1024
|
+
// rendering is deferred so the open animation plays after the resize, not
|
|
1025
|
+
// during it.
|
|
1026
|
+
const beginControlledOpen = react.useCallback(() => {
|
|
1027
|
+
const id = ++openIdRef.current;
|
|
1028
|
+
const result = openModal();
|
|
1029
|
+
if (result instanceof Promise) {
|
|
1030
|
+
setOpenDeferred(true);
|
|
1031
|
+
void result.then(() => {
|
|
1032
|
+
if (openIdRef.current === id) {
|
|
1033
|
+
setOpenDeferred(false);
|
|
1035
1034
|
}
|
|
1036
|
-
}
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1035
|
+
});
|
|
1036
|
+
}
|
|
1037
|
+
}, [openModal]);
|
|
1038
|
+
// Arms the pending close, so closeModal() resizes the iframe back once the
|
|
1039
|
+
// close animation completes (or the safety timeout fires as a fallback).
|
|
1040
|
+
const beginControlledClose = react.useCallback(() => {
|
|
1041
|
+
openIdRef.current++;
|
|
1042
|
+
setOpenDeferred(false);
|
|
1043
|
+
startPendingCloseModal();
|
|
1044
|
+
}, [startPendingCloseModal]);
|
|
1045
|
+
// Reacts to changes of the controlled isOpen prop.
|
|
1046
|
+
//
|
|
1047
|
+
// Must be a layout effect: layout effects flush before ALL passive effects,
|
|
1048
|
+
// so the close safety timeout is armed (or re-armed, after modal.close()'s
|
|
1049
|
+
// synchronous arm in handleClose) before the child Modal's passive effect
|
|
1050
|
+
// cancels it via onCloseComplete. Within the same phase child effects run
|
|
1051
|
+
// first, so this ordering only holds while Modal calls onCloseComplete from
|
|
1052
|
+
// a passive effect. With a passive effect here, the arm came after the
|
|
1053
|
+
// cancellation and the timeout fired on every controlled card-mode close
|
|
1054
|
+
// (sheet-mode closes usually completed later via transitionend).
|
|
1055
|
+
const prevControlledIsOpenRef = react.useRef(null);
|
|
1056
|
+
react.useLayoutEffect(() => {
|
|
1057
|
+
if (typeof controlledIsOpen !== "boolean") {
|
|
1058
|
+
return;
|
|
1059
|
+
}
|
|
1060
|
+
const wasOpen = prevControlledIsOpenRef.current;
|
|
1061
|
+
prevControlledIsOpenRef.current = controlledIsOpen;
|
|
1062
|
+
if (controlledIsOpen === wasOpen) {
|
|
1063
|
+
return;
|
|
1064
|
+
}
|
|
1065
|
+
if (controlledIsOpen) {
|
|
1066
|
+
beginControlledOpen();
|
|
1067
|
+
}
|
|
1068
|
+
else if (wasOpen) {
|
|
1069
|
+
beginControlledClose();
|
|
1070
|
+
}
|
|
1071
|
+
}, [controlledIsOpen, beginControlledOpen, beginControlledClose]);
|
|
1044
1072
|
// Cleanup: notify context when component unmounts while modal is open or mid-close.
|
|
1045
1073
|
// Calls closeModal() directly (no animation to wait for during unmount).
|
|
1046
1074
|
react.useEffect(() => {
|
package/index.esm.js
CHANGED
|
@@ -324,6 +324,12 @@ const Modal = ({ children, container, dismiss, isOpen, mode, requestClose, role
|
|
|
324
324
|
// In card mode, there is no close animation so notify useModal immediately
|
|
325
325
|
// so it can call closeModal() without delay.
|
|
326
326
|
// In sheet mode, Sheet's onCloseComplete handles this instead.
|
|
327
|
+
//
|
|
328
|
+
// Must stay a passive effect (useWatch): useModal arms the close safety
|
|
329
|
+
// timeout in a layout effect, which has to flush before onCloseComplete
|
|
330
|
+
// cancels it. Moving this to a layout effect would run it first (child
|
|
331
|
+
// effects run before parent effects within a phase), leaving the timeout
|
|
332
|
+
// armed with nothing to cancel it.
|
|
327
333
|
useWatch({
|
|
328
334
|
value: isOpen,
|
|
329
335
|
onChange: (current, prev) => {
|
|
@@ -1012,33 +1018,55 @@ const useModal = (props) => {
|
|
|
1012
1018
|
void closeModal();
|
|
1013
1019
|
}
|
|
1014
1020
|
}, [stopCloseTimeout, closeModal]);
|
|
1015
|
-
//
|
|
1016
|
-
//
|
|
1017
|
-
//
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
if (result instanceof Promise) {
|
|
1027
|
-
setOpenDeferred(true);
|
|
1028
|
-
void result.then(() => {
|
|
1029
|
-
if (openIdRef.current === id) {
|
|
1030
|
-
setOpenDeferred(false);
|
|
1031
|
-
}
|
|
1032
|
-
});
|
|
1021
|
+
// Asks the host iframe to resize to fullscreen. While the resize is running,
|
|
1022
|
+
// rendering is deferred so the open animation plays after the resize, not
|
|
1023
|
+
// during it.
|
|
1024
|
+
const beginControlledOpen = useCallback(() => {
|
|
1025
|
+
const id = ++openIdRef.current;
|
|
1026
|
+
const result = openModal();
|
|
1027
|
+
if (result instanceof Promise) {
|
|
1028
|
+
setOpenDeferred(true);
|
|
1029
|
+
void result.then(() => {
|
|
1030
|
+
if (openIdRef.current === id) {
|
|
1031
|
+
setOpenDeferred(false);
|
|
1033
1032
|
}
|
|
1034
|
-
}
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1033
|
+
});
|
|
1034
|
+
}
|
|
1035
|
+
}, [openModal]);
|
|
1036
|
+
// Arms the pending close, so closeModal() resizes the iframe back once the
|
|
1037
|
+
// close animation completes (or the safety timeout fires as a fallback).
|
|
1038
|
+
const beginControlledClose = useCallback(() => {
|
|
1039
|
+
openIdRef.current++;
|
|
1040
|
+
setOpenDeferred(false);
|
|
1041
|
+
startPendingCloseModal();
|
|
1042
|
+
}, [startPendingCloseModal]);
|
|
1043
|
+
// Reacts to changes of the controlled isOpen prop.
|
|
1044
|
+
//
|
|
1045
|
+
// Must be a layout effect: layout effects flush before ALL passive effects,
|
|
1046
|
+
// so the close safety timeout is armed (or re-armed, after modal.close()'s
|
|
1047
|
+
// synchronous arm in handleClose) before the child Modal's passive effect
|
|
1048
|
+
// cancels it via onCloseComplete. Within the same phase child effects run
|
|
1049
|
+
// first, so this ordering only holds while Modal calls onCloseComplete from
|
|
1050
|
+
// a passive effect. With a passive effect here, the arm came after the
|
|
1051
|
+
// cancellation and the timeout fired on every controlled card-mode close
|
|
1052
|
+
// (sheet-mode closes usually completed later via transitionend).
|
|
1053
|
+
const prevControlledIsOpenRef = useRef(null);
|
|
1054
|
+
useLayoutEffect(() => {
|
|
1055
|
+
if (typeof controlledIsOpen !== "boolean") {
|
|
1056
|
+
return;
|
|
1057
|
+
}
|
|
1058
|
+
const wasOpen = prevControlledIsOpenRef.current;
|
|
1059
|
+
prevControlledIsOpenRef.current = controlledIsOpen;
|
|
1060
|
+
if (controlledIsOpen === wasOpen) {
|
|
1061
|
+
return;
|
|
1062
|
+
}
|
|
1063
|
+
if (controlledIsOpen) {
|
|
1064
|
+
beginControlledOpen();
|
|
1065
|
+
}
|
|
1066
|
+
else if (wasOpen) {
|
|
1067
|
+
beginControlledClose();
|
|
1068
|
+
}
|
|
1069
|
+
}, [controlledIsOpen, beginControlledOpen, beginControlledClose]);
|
|
1042
1070
|
// Cleanup: notify context when component unmounts while modal is open or mid-close.
|
|
1043
1071
|
// Calls closeModal() directly (no animation to wait for during unmount).
|
|
1044
1072
|
useEffect(() => {
|