@ionic/core 8.5.9-nightly.20250603 → 8.5.9
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/components/modal.js +101 -161
- package/css/core.css +1 -1
- package/css/core.css.map +1 -1
- package/css/ionic.bundle.css +1 -1
- package/css/ionic.bundle.css.map +1 -1
- package/dist/cjs/ion-modal.cjs.entry.js +101 -161
- package/dist/collection/components/modal/animations/ios.enter.js +1 -41
- package/dist/collection/components/modal/animations/ios.leave.js +2 -24
- package/dist/collection/components/modal/animations/md.enter.js +2 -42
- package/dist/collection/components/modal/animations/md.leave.js +2 -24
- package/dist/collection/components/modal/gestures/sheet.js +93 -29
- package/dist/collection/components/modal/modal.ios.css +0 -10
- package/dist/docs.json +1 -1
- package/dist/esm/ion-modal.entry.js +101 -161
- package/dist/esm-es5/ion-modal.entry.js +1 -1
- package/dist/ionic/ionic.esm.js +1 -1
- package/dist/ionic/p-4393fc08.entry.js +4 -0
- package/dist/ionic/p-44548aa3.system.entry.js +4 -0
- package/dist/ionic/p-f725bf9e.system.js +1 -1
- package/hydrate/index.js +101 -161
- package/hydrate/index.mjs +101 -161
- package/package.json +1 -1
- package/dist/ionic/p-12914457.entry.js +0 -4
- package/dist/ionic/p-cec902a0.system.entry.js +0 -4
|
@@ -588,47 +588,7 @@ const iosEnterAnimation = (baseEl, opts) => {
|
|
|
588
588
|
.addElement(baseEl)
|
|
589
589
|
.easing('cubic-bezier(0.32,0.72,0,1)')
|
|
590
590
|
.duration(500)
|
|
591
|
-
.addAnimation([wrapperAnimation])
|
|
592
|
-
.beforeAddWrite(() => {
|
|
593
|
-
if (expandToScroll) {
|
|
594
|
-
// Scroll can only be done when the modal is fully expanded.
|
|
595
|
-
return;
|
|
596
|
-
}
|
|
597
|
-
/**
|
|
598
|
-
* There are some browsers that causes flickering when
|
|
599
|
-
* dragging the content when scroll is enabled at every
|
|
600
|
-
* breakpoint. This is due to the wrapper element being
|
|
601
|
-
* transformed off the screen and having a snap animation.
|
|
602
|
-
*
|
|
603
|
-
* A workaround is to clone the footer element and append
|
|
604
|
-
* it outside of the wrapper element. This way, the footer
|
|
605
|
-
* is still visible and the drag can be done without
|
|
606
|
-
* flickering. The original footer is hidden until the modal
|
|
607
|
-
* is dismissed. This maintains the animation of the footer
|
|
608
|
-
* when the modal is dismissed.
|
|
609
|
-
*
|
|
610
|
-
* The workaround needs to be done before the animation starts
|
|
611
|
-
* so there are no flickering issues.
|
|
612
|
-
*/
|
|
613
|
-
const ionFooter = baseEl.querySelector('ion-footer');
|
|
614
|
-
/**
|
|
615
|
-
* This check is needed to prevent more than one footer
|
|
616
|
-
* from being appended to the shadow root.
|
|
617
|
-
* Otherwise, iOS and MD enter animations would append
|
|
618
|
-
* the footer twice.
|
|
619
|
-
*/
|
|
620
|
-
const ionFooterAlreadyAppended = baseEl.shadowRoot.querySelector('ion-footer');
|
|
621
|
-
if (ionFooter && !ionFooterAlreadyAppended) {
|
|
622
|
-
const footerHeight = ionFooter.clientHeight;
|
|
623
|
-
const clonedFooter = ionFooter.cloneNode(true);
|
|
624
|
-
baseEl.shadowRoot.appendChild(clonedFooter);
|
|
625
|
-
ionFooter.style.setProperty('display', 'none');
|
|
626
|
-
ionFooter.setAttribute('aria-hidden', 'true');
|
|
627
|
-
// Padding is added to prevent some content from being hidden.
|
|
628
|
-
const page = baseEl.querySelector('.ion-page');
|
|
629
|
-
page.style.setProperty('padding-bottom', `${footerHeight}px`);
|
|
630
|
-
}
|
|
631
|
-
});
|
|
591
|
+
.addAnimation([wrapperAnimation]);
|
|
632
592
|
if (contentAnimation) {
|
|
633
593
|
baseAnimation.addAnimation(contentAnimation);
|
|
634
594
|
}
|
|
@@ -709,7 +669,7 @@ const createLeaveAnimation$1 = () => {
|
|
|
709
669
|
* iOS Modal Leave Animation
|
|
710
670
|
*/
|
|
711
671
|
const iosLeaveAnimation = (baseEl, opts, duration = 500) => {
|
|
712
|
-
const { presentingEl, currentBreakpoint
|
|
672
|
+
const { presentingEl, currentBreakpoint } = opts;
|
|
713
673
|
const root = helpers.getElementRoot(baseEl);
|
|
714
674
|
const { wrapperAnimation, backdropAnimation } = currentBreakpoint !== undefined ? createSheetLeaveAnimation(opts) : createLeaveAnimation$1();
|
|
715
675
|
backdropAnimation.addElement(root.querySelector('ion-backdrop'));
|
|
@@ -718,29 +678,7 @@ const iosLeaveAnimation = (baseEl, opts, duration = 500) => {
|
|
|
718
678
|
.addElement(baseEl)
|
|
719
679
|
.easing('cubic-bezier(0.32,0.72,0,1)')
|
|
720
680
|
.duration(duration)
|
|
721
|
-
.addAnimation(wrapperAnimation)
|
|
722
|
-
.beforeAddWrite(() => {
|
|
723
|
-
if (expandToScroll) {
|
|
724
|
-
// Scroll can only be done when the modal is fully expanded.
|
|
725
|
-
return;
|
|
726
|
-
}
|
|
727
|
-
/**
|
|
728
|
-
* If expandToScroll is disabled, we need to swap
|
|
729
|
-
* the visibility to the original, so the footer
|
|
730
|
-
* dismisses with the modal and doesn't stay
|
|
731
|
-
* until the modal is removed from the DOM.
|
|
732
|
-
*/
|
|
733
|
-
const ionFooter = baseEl.querySelector('ion-footer');
|
|
734
|
-
if (ionFooter) {
|
|
735
|
-
const clonedFooter = baseEl.shadowRoot.querySelector('ion-footer');
|
|
736
|
-
ionFooter.style.removeProperty('display');
|
|
737
|
-
ionFooter.removeAttribute('aria-hidden');
|
|
738
|
-
clonedFooter.style.setProperty('display', 'none');
|
|
739
|
-
clonedFooter.setAttribute('aria-hidden', 'true');
|
|
740
|
-
const page = baseEl.querySelector('.ion-page');
|
|
741
|
-
page.style.removeProperty('padding-bottom');
|
|
742
|
-
}
|
|
743
|
-
});
|
|
681
|
+
.addAnimation(wrapperAnimation);
|
|
744
682
|
if (presentingEl) {
|
|
745
683
|
const isMobile = window.innerWidth < 768;
|
|
746
684
|
const hasCardModal = presentingEl.tagName === 'ION-MODAL' && presentingEl.presentingElement !== undefined;
|
|
@@ -831,52 +769,12 @@ const mdEnterAnimation = (baseEl, opts) => {
|
|
|
831
769
|
wrapperAnimation.addElement(root.querySelector('.modal-wrapper'));
|
|
832
770
|
// The content animation is only added if scrolling is enabled for
|
|
833
771
|
// all the breakpoints.
|
|
834
|
-
expandToScroll && (contentAnimation === null || contentAnimation === void 0 ? void 0 : contentAnimation.addElement(baseEl.querySelector('.ion-page')));
|
|
772
|
+
!expandToScroll && (contentAnimation === null || contentAnimation === void 0 ? void 0 : contentAnimation.addElement(baseEl.querySelector('.ion-page')));
|
|
835
773
|
const baseAnimation = animation.createAnimation()
|
|
836
774
|
.addElement(baseEl)
|
|
837
775
|
.easing('cubic-bezier(0.36,0.66,0.04,1)')
|
|
838
776
|
.duration(280)
|
|
839
|
-
.addAnimation([backdropAnimation, wrapperAnimation])
|
|
840
|
-
.beforeAddWrite(() => {
|
|
841
|
-
if (expandToScroll) {
|
|
842
|
-
// Scroll can only be done when the modal is fully expanded.
|
|
843
|
-
return;
|
|
844
|
-
}
|
|
845
|
-
/**
|
|
846
|
-
* There are some browsers that causes flickering when
|
|
847
|
-
* dragging the content when scroll is enabled at every
|
|
848
|
-
* breakpoint. This is due to the wrapper element being
|
|
849
|
-
* transformed off the screen and having a snap animation.
|
|
850
|
-
*
|
|
851
|
-
* A workaround is to clone the footer element and append
|
|
852
|
-
* it outside of the wrapper element. This way, the footer
|
|
853
|
-
* is still visible and the drag can be done without
|
|
854
|
-
* flickering. The original footer is hidden until the modal
|
|
855
|
-
* is dismissed. This maintains the animation of the footer
|
|
856
|
-
* when the modal is dismissed.
|
|
857
|
-
*
|
|
858
|
-
* The workaround needs to be done before the animation starts
|
|
859
|
-
* so there are no flickering issues.
|
|
860
|
-
*/
|
|
861
|
-
const ionFooter = baseEl.querySelector('ion-footer');
|
|
862
|
-
/**
|
|
863
|
-
* This check is needed to prevent more than one footer
|
|
864
|
-
* from being appended to the shadow root.
|
|
865
|
-
* Otherwise, iOS and MD enter animations would append
|
|
866
|
-
* the footer twice.
|
|
867
|
-
*/
|
|
868
|
-
const ionFooterAlreadyAppended = baseEl.shadowRoot.querySelector('ion-footer');
|
|
869
|
-
if (ionFooter && !ionFooterAlreadyAppended) {
|
|
870
|
-
const footerHeight = ionFooter.clientHeight;
|
|
871
|
-
const clonedFooter = ionFooter.cloneNode(true);
|
|
872
|
-
baseEl.shadowRoot.appendChild(clonedFooter);
|
|
873
|
-
ionFooter.style.setProperty('display', 'none');
|
|
874
|
-
ionFooter.setAttribute('aria-hidden', 'true');
|
|
875
|
-
// Padding is added to prevent some content from being hidden.
|
|
876
|
-
const page = baseEl.querySelector('.ion-page');
|
|
877
|
-
page.style.setProperty('padding-bottom', `${footerHeight}px`);
|
|
878
|
-
}
|
|
879
|
-
});
|
|
777
|
+
.addAnimation([backdropAnimation, wrapperAnimation]);
|
|
880
778
|
if (contentAnimation) {
|
|
881
779
|
baseAnimation.addAnimation(contentAnimation);
|
|
882
780
|
}
|
|
@@ -895,7 +793,7 @@ const createLeaveAnimation = () => {
|
|
|
895
793
|
* Md Modal Leave Animation
|
|
896
794
|
*/
|
|
897
795
|
const mdLeaveAnimation = (baseEl, opts) => {
|
|
898
|
-
const { currentBreakpoint
|
|
796
|
+
const { currentBreakpoint } = opts;
|
|
899
797
|
const root = helpers.getElementRoot(baseEl);
|
|
900
798
|
const { wrapperAnimation, backdropAnimation } = currentBreakpoint !== undefined ? createSheetLeaveAnimation(opts) : createLeaveAnimation();
|
|
901
799
|
backdropAnimation.addElement(root.querySelector('ion-backdrop'));
|
|
@@ -903,29 +801,7 @@ const mdLeaveAnimation = (baseEl, opts) => {
|
|
|
903
801
|
const baseAnimation = animation.createAnimation()
|
|
904
802
|
.easing('cubic-bezier(0.47,0,0.745,0.715)')
|
|
905
803
|
.duration(200)
|
|
906
|
-
.addAnimation([backdropAnimation, wrapperAnimation])
|
|
907
|
-
.beforeAddWrite(() => {
|
|
908
|
-
if (expandToScroll) {
|
|
909
|
-
// Scroll can only be done when the modal is fully expanded.
|
|
910
|
-
return;
|
|
911
|
-
}
|
|
912
|
-
/**
|
|
913
|
-
* If expandToScroll is disabled, we need to swap
|
|
914
|
-
* the visibility to the original, so the footer
|
|
915
|
-
* dismisses with the modal and doesn't stay
|
|
916
|
-
* until the modal is removed from the DOM.
|
|
917
|
-
*/
|
|
918
|
-
const ionFooter = baseEl.querySelector('ion-footer');
|
|
919
|
-
if (ionFooter) {
|
|
920
|
-
const clonedFooter = baseEl.shadowRoot.querySelector('ion-footer');
|
|
921
|
-
ionFooter.style.removeProperty('display');
|
|
922
|
-
ionFooter.removeAttribute('aria-hidden');
|
|
923
|
-
clonedFooter.style.setProperty('display', 'none');
|
|
924
|
-
clonedFooter.setAttribute('aria-hidden', 'true');
|
|
925
|
-
const page = baseEl.querySelector('.ion-page');
|
|
926
|
-
page.style.removeProperty('padding-bottom');
|
|
927
|
-
}
|
|
928
|
-
});
|
|
804
|
+
.addAnimation([backdropAnimation, wrapperAnimation]);
|
|
929
805
|
return baseAnimation;
|
|
930
806
|
};
|
|
931
807
|
|
|
@@ -957,6 +833,9 @@ const createSheetGesture = (baseEl, backdropEl, wrapperEl, initialBreakpoint, ba
|
|
|
957
833
|
let offset = 0;
|
|
958
834
|
let canDismissBlocksGesture = false;
|
|
959
835
|
let cachedScrollEl = null;
|
|
836
|
+
let cachedFooterEl = null;
|
|
837
|
+
let cachedFooterYPosition = null;
|
|
838
|
+
let currentFooterState = null;
|
|
960
839
|
const canDismissMaxStep = 0.95;
|
|
961
840
|
const maxBreakpoint = breakpoints[breakpoints.length - 1];
|
|
962
841
|
const minBreakpoint = breakpoints[0];
|
|
@@ -986,29 +865,66 @@ const createSheetGesture = (baseEl, backdropEl, wrapperEl, initialBreakpoint, ba
|
|
|
986
865
|
baseEl.classList.add(overlays.FOCUS_TRAP_DISABLE_CLASS);
|
|
987
866
|
};
|
|
988
867
|
/**
|
|
989
|
-
* Toggles the
|
|
990
|
-
*
|
|
868
|
+
* Toggles the footer to an absolute position while moving to prevent
|
|
869
|
+
* it from shaking while the sheet is being dragged.
|
|
870
|
+
* @param newPosition Whether the footer is in a moving or stationary position.
|
|
991
871
|
*/
|
|
992
|
-
const
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
872
|
+
const swapFooterPosition = (newPosition) => {
|
|
873
|
+
if (!cachedFooterEl) {
|
|
874
|
+
cachedFooterEl = baseEl.querySelector('ion-footer');
|
|
875
|
+
if (!cachedFooterEl) {
|
|
876
|
+
return;
|
|
877
|
+
}
|
|
996
878
|
}
|
|
997
|
-
const clonedFooter = wrapperEl.nextElementSibling;
|
|
998
|
-
const footerToHide = footer === 'original' ? clonedFooter : originalFooter;
|
|
999
|
-
const footerToShow = footer === 'original' ? originalFooter : clonedFooter;
|
|
1000
|
-
footerToShow.style.removeProperty('display');
|
|
1001
|
-
footerToShow.removeAttribute('aria-hidden');
|
|
1002
879
|
const page = baseEl.querySelector('.ion-page');
|
|
1003
|
-
|
|
1004
|
-
|
|
880
|
+
currentFooterState = newPosition;
|
|
881
|
+
if (newPosition === 'stationary') {
|
|
882
|
+
// Reset positioning styles to allow normal document flow
|
|
883
|
+
cachedFooterEl.classList.remove('modal-footer-moving');
|
|
884
|
+
cachedFooterEl.style.removeProperty('position');
|
|
885
|
+
cachedFooterEl.style.removeProperty('width');
|
|
886
|
+
cachedFooterEl.style.removeProperty('height');
|
|
887
|
+
cachedFooterEl.style.removeProperty('top');
|
|
888
|
+
cachedFooterEl.style.removeProperty('left');
|
|
889
|
+
page === null || page === void 0 ? void 0 : page.style.removeProperty('padding-bottom');
|
|
890
|
+
// Move to page
|
|
891
|
+
page === null || page === void 0 ? void 0 : page.appendChild(cachedFooterEl);
|
|
1005
892
|
}
|
|
1006
893
|
else {
|
|
1007
|
-
|
|
1008
|
-
|
|
894
|
+
// Get both the footer and document body positions
|
|
895
|
+
const cachedFooterElRect = cachedFooterEl.getBoundingClientRect();
|
|
896
|
+
const bodyRect = document.body.getBoundingClientRect();
|
|
897
|
+
// Add padding to the parent element to prevent content from being hidden
|
|
898
|
+
// when the footer is positioned absolutely. This has to be done before we
|
|
899
|
+
// make the footer absolutely positioned or we may accidentally cause the
|
|
900
|
+
// sheet to scroll.
|
|
901
|
+
const footerHeight = cachedFooterEl.clientHeight;
|
|
902
|
+
page === null || page === void 0 ? void 0 : page.style.setProperty('padding-bottom', `${footerHeight}px`);
|
|
903
|
+
// Apply positioning styles to keep footer at bottom
|
|
904
|
+
cachedFooterEl.classList.add('modal-footer-moving');
|
|
905
|
+
// Calculate absolute position relative to body
|
|
906
|
+
// We need to subtract the body's offsetTop to get true position within document.body
|
|
907
|
+
const absoluteTop = cachedFooterElRect.top - bodyRect.top;
|
|
908
|
+
const absoluteLeft = cachedFooterElRect.left - bodyRect.left;
|
|
909
|
+
// Capture the footer's current dimensions and hard code them during the drag
|
|
910
|
+
cachedFooterEl.style.setProperty('position', 'absolute');
|
|
911
|
+
cachedFooterEl.style.setProperty('width', `${cachedFooterEl.clientWidth}px`);
|
|
912
|
+
cachedFooterEl.style.setProperty('height', `${cachedFooterEl.clientHeight}px`);
|
|
913
|
+
cachedFooterEl.style.setProperty('top', `${absoluteTop}px`);
|
|
914
|
+
cachedFooterEl.style.setProperty('left', `${absoluteLeft}px`);
|
|
915
|
+
// Also cache the footer Y position, which we use to determine if the
|
|
916
|
+
// sheet has been moved below the footer. When that happens, we need to swap
|
|
917
|
+
// the position back so it will collapse correctly.
|
|
918
|
+
cachedFooterYPosition = absoluteTop;
|
|
919
|
+
// If there's a toolbar, we need to combine the toolbar height with the footer position
|
|
920
|
+
// because the toolbar moves with the drag handle, so when it starts overlapping the footer,
|
|
921
|
+
// we need to account for that.
|
|
922
|
+
const toolbar = baseEl.querySelector('ion-toolbar');
|
|
923
|
+
if (toolbar) {
|
|
924
|
+
cachedFooterYPosition -= toolbar.clientHeight;
|
|
925
|
+
}
|
|
926
|
+
document.body.appendChild(cachedFooterEl);
|
|
1009
927
|
}
|
|
1010
|
-
footerToHide.style.setProperty('display', 'none');
|
|
1011
|
-
footerToHide.setAttribute('aria-hidden', 'true');
|
|
1012
928
|
};
|
|
1013
929
|
/**
|
|
1014
930
|
* After the entering animation completes,
|
|
@@ -1102,12 +1018,11 @@ const createSheetGesture = (baseEl, backdropEl, wrapperEl, initialBreakpoint, ba
|
|
|
1102
1018
|
}
|
|
1103
1019
|
/**
|
|
1104
1020
|
* If expandToScroll is disabled, we need to swap
|
|
1105
|
-
* the footer
|
|
1106
|
-
*
|
|
1107
|
-
* and doesn't stay on the screen after the modal is gone.
|
|
1021
|
+
* the footer position to moving so that it doesn't shake
|
|
1022
|
+
* while the sheet is being dragged.
|
|
1108
1023
|
*/
|
|
1109
1024
|
if (!expandToScroll) {
|
|
1110
|
-
|
|
1025
|
+
swapFooterPosition('moving');
|
|
1111
1026
|
}
|
|
1112
1027
|
/**
|
|
1113
1028
|
* If we are pulling down, then it is possible we are pulling on the content.
|
|
@@ -1126,6 +1041,21 @@ const createSheetGesture = (baseEl, backdropEl, wrapperEl, initialBreakpoint, ba
|
|
|
1126
1041
|
animation.progressStart(true, 1 - currentBreakpoint);
|
|
1127
1042
|
};
|
|
1128
1043
|
const onMove = (detail) => {
|
|
1044
|
+
/**
|
|
1045
|
+
* If `expandToScroll` is disabled, we need to see if we're currently below
|
|
1046
|
+
* the footer element and the footer is in a stationary position. If so,
|
|
1047
|
+
* we need to make the stationary the original position so that the footer
|
|
1048
|
+
* collapses with the sheet.
|
|
1049
|
+
*/
|
|
1050
|
+
if (!expandToScroll && cachedFooterYPosition !== null && currentFooterState !== null) {
|
|
1051
|
+
// Check if we need to swap the footer position
|
|
1052
|
+
if (detail.currentY >= cachedFooterYPosition && currentFooterState === 'moving') {
|
|
1053
|
+
swapFooterPosition('stationary');
|
|
1054
|
+
}
|
|
1055
|
+
else if (detail.currentY < cachedFooterYPosition && currentFooterState === 'stationary') {
|
|
1056
|
+
swapFooterPosition('moving');
|
|
1057
|
+
}
|
|
1058
|
+
}
|
|
1129
1059
|
/**
|
|
1130
1060
|
* If `expandToScroll` is disabled, and an upwards swipe gesture is done within
|
|
1131
1061
|
* the scrollable content, we should not allow the swipe gesture to continue.
|
|
@@ -1259,14 +1189,6 @@ const createSheetGesture = (baseEl, backdropEl, wrapperEl, initialBreakpoint, ba
|
|
|
1259
1189
|
* snapping animation completes.
|
|
1260
1190
|
*/
|
|
1261
1191
|
gesture.enable(false);
|
|
1262
|
-
/**
|
|
1263
|
-
* If expandToScroll is disabled, we need to swap
|
|
1264
|
-
* the footer visibility to the cloned one so the footer
|
|
1265
|
-
* doesn't flicker when the sheet's height is animated.
|
|
1266
|
-
*/
|
|
1267
|
-
if (!expandToScroll && shouldRemainOpen) {
|
|
1268
|
-
swapFooterVisibility('cloned');
|
|
1269
|
-
}
|
|
1270
1192
|
if (shouldPreventDismiss) {
|
|
1271
1193
|
handleCanDismiss(baseEl, animation);
|
|
1272
1194
|
}
|
|
@@ -1283,10 +1205,28 @@ const createSheetGesture = (baseEl, backdropEl, wrapperEl, initialBreakpoint, ba
|
|
|
1283
1205
|
if (contentEl && (snapToBreakpoint === breakpoints[breakpoints.length - 1] || !expandToScroll)) {
|
|
1284
1206
|
contentEl.scrollY = true;
|
|
1285
1207
|
}
|
|
1208
|
+
/**
|
|
1209
|
+
* If expandToScroll is disabled and we're animating
|
|
1210
|
+
* to close the sheet, we need to swap
|
|
1211
|
+
* the footer position to stationary so that it
|
|
1212
|
+
* will collapse correctly. We cannot just always swap
|
|
1213
|
+
* here or it'll be jittery while animating movement.
|
|
1214
|
+
*/
|
|
1215
|
+
if (!expandToScroll && snapToBreakpoint === 0) {
|
|
1216
|
+
swapFooterPosition('stationary');
|
|
1217
|
+
}
|
|
1286
1218
|
return new Promise((resolve) => {
|
|
1287
1219
|
animation
|
|
1288
1220
|
.onFinish(() => {
|
|
1289
1221
|
if (shouldRemainOpen) {
|
|
1222
|
+
/**
|
|
1223
|
+
* If expandToScroll is disabled, we need to swap
|
|
1224
|
+
* the footer position to stationary so that it
|
|
1225
|
+
* will act as it would by default.
|
|
1226
|
+
*/
|
|
1227
|
+
if (!expandToScroll) {
|
|
1228
|
+
swapFooterPosition('stationary');
|
|
1229
|
+
}
|
|
1290
1230
|
/**
|
|
1291
1231
|
* Once the snapping animation completes,
|
|
1292
1232
|
* we need to reset the animation to go
|
|
@@ -1351,7 +1291,7 @@ const createSheetGesture = (baseEl, backdropEl, wrapperEl, initialBreakpoint, ba
|
|
|
1351
1291
|
};
|
|
1352
1292
|
};
|
|
1353
1293
|
|
|
1354
|
-
const modalIosCss = ":host{--width:100%;--min-width:auto;--max-width:auto;--height:100%;--min-height:auto;--max-height:auto;--overflow:hidden;--border-radius:0;--border-width:0;--border-style:none;--border-color:transparent;--background:var(--ion-background-color, #fff);--box-shadow:none;--backdrop-opacity:0;left:0;right:0;top:0;bottom:0;display:-ms-flexbox;display:flex;position:absolute;-ms-flex-align:center;align-items:center;-ms-flex-pack:center;justify-content:center;outline:none;color:var(--ion-text-color, #000);contain:strict}.modal-wrapper,ion-backdrop{pointer-events:auto}:host(.overlay-hidden){display:none}.modal-wrapper,.modal-shadow{border-radius:var(--border-radius);width:var(--width);min-width:var(--min-width);max-width:var(--max-width);height:var(--height);min-height:var(--min-height);max-height:var(--max-height);border-width:var(--border-width);border-style:var(--border-style);border-color:var(--border-color);background:var(--background);-webkit-box-shadow:var(--box-shadow);box-shadow:var(--box-shadow);overflow:var(--overflow);z-index:10}.modal-shadow{position:absolute;background:transparent}@media only screen and (min-width: 768px) and (min-height: 600px){:host{--width:600px;--height:500px;--ion-safe-area-top:0px;--ion-safe-area-bottom:0px;--ion-safe-area-right:0px;--ion-safe-area-left:0px}}@media only screen and (min-width: 768px) and (min-height: 768px){:host{--width:600px;--height:600px}}.modal-handle{left:0px;right:0px;top:5px;border-radius:8px;-webkit-margin-start:auto;margin-inline-start:auto;-webkit-margin-end:auto;margin-inline-end:auto;position:absolute;width:36px;height:5px;-webkit-transform:translateZ(0);transform:translateZ(0);border:0;background:var(--ion-color-step-350, var(--ion-background-color-step-350, #c0c0be));cursor:pointer;z-index:11}.modal-handle::before{-webkit-padding-start:4px;padding-inline-start:4px;-webkit-padding-end:4px;padding-inline-end:4px;padding-top:4px;padding-bottom:4px;position:absolute;width:36px;height:5px;-webkit-transform:translate(-50%, -50%);transform:translate(-50%, -50%);content:\"\"}:host(.modal-sheet){--height:calc(100% - (var(--ion-safe-area-top) + 10px))}:host(.modal-sheet) .modal-wrapper,:host(.modal-sheet) .modal-shadow{position:absolute;bottom:0}:host(.modal-sheet.modal-no-expand-scroll) ion-footer{position:absolute;bottom:0;width:var(--width)}:host{--backdrop-opacity:var(--ion-backdrop-opacity, 0.4)}:host(.modal-card),:host(.modal-sheet){--border-radius:10px}@media only screen and (min-width: 768px) and (min-height: 600px){:host{--border-radius:10px}}.modal-wrapper{-webkit-transform:translate3d(0, 100%, 0);transform:translate3d(0, 100%, 0)}@media screen and (max-width: 767px){@supports (width: max(0px, 1px)){:host(.modal-card){--height:calc(100% - max(30px, var(--ion-safe-area-top)) - 10px)}}@supports not (width: max(0px, 1px)){:host(.modal-card){--height:calc(100% - 40px)}}:host(.modal-card) .modal-wrapper{border-start-start-radius:var(--border-radius);border-start-end-radius:var(--border-radius);border-end-end-radius:0;border-end-start-radius:0}:host(.modal-card){--backdrop-opacity:0;--width:100%;-ms-flex-align:end;align-items:flex-end}:host(.modal-card) .modal-shadow{display:none}:host(.modal-card) ion-backdrop{pointer-events:none}}@media screen and (min-width: 768px){:host(.modal-card){--width:calc(100% - 120px);--height:calc(100% - (120px + var(--ion-safe-area-top) + var(--ion-safe-area-bottom)));--max-width:720px;--max-height:1000px;--backdrop-opacity:0;--box-shadow:0px 0px 30px 10px rgba(0, 0, 0, 0.1);-webkit-transition:all 0.5s ease-in-out;transition:all 0.5s ease-in-out}:host(.modal-card) .modal-wrapper{-webkit-box-shadow:none;box-shadow:none}:host(.modal-card) .modal-shadow{-webkit-box-shadow:var(--box-shadow);box-shadow:var(--box-shadow)}}:host(.modal-sheet) .modal-wrapper{border-start-start-radius:var(--border-radius);border-start-end-radius:var(--border-radius);border-end-end-radius:0;border-end-start-radius:0}
|
|
1294
|
+
const modalIosCss = ":host{--width:100%;--min-width:auto;--max-width:auto;--height:100%;--min-height:auto;--max-height:auto;--overflow:hidden;--border-radius:0;--border-width:0;--border-style:none;--border-color:transparent;--background:var(--ion-background-color, #fff);--box-shadow:none;--backdrop-opacity:0;left:0;right:0;top:0;bottom:0;display:-ms-flexbox;display:flex;position:absolute;-ms-flex-align:center;align-items:center;-ms-flex-pack:center;justify-content:center;outline:none;color:var(--ion-text-color, #000);contain:strict}.modal-wrapper,ion-backdrop{pointer-events:auto}:host(.overlay-hidden){display:none}.modal-wrapper,.modal-shadow{border-radius:var(--border-radius);width:var(--width);min-width:var(--min-width);max-width:var(--max-width);height:var(--height);min-height:var(--min-height);max-height:var(--max-height);border-width:var(--border-width);border-style:var(--border-style);border-color:var(--border-color);background:var(--background);-webkit-box-shadow:var(--box-shadow);box-shadow:var(--box-shadow);overflow:var(--overflow);z-index:10}.modal-shadow{position:absolute;background:transparent}@media only screen and (min-width: 768px) and (min-height: 600px){:host{--width:600px;--height:500px;--ion-safe-area-top:0px;--ion-safe-area-bottom:0px;--ion-safe-area-right:0px;--ion-safe-area-left:0px}}@media only screen and (min-width: 768px) and (min-height: 768px){:host{--width:600px;--height:600px}}.modal-handle{left:0px;right:0px;top:5px;border-radius:8px;-webkit-margin-start:auto;margin-inline-start:auto;-webkit-margin-end:auto;margin-inline-end:auto;position:absolute;width:36px;height:5px;-webkit-transform:translateZ(0);transform:translateZ(0);border:0;background:var(--ion-color-step-350, var(--ion-background-color-step-350, #c0c0be));cursor:pointer;z-index:11}.modal-handle::before{-webkit-padding-start:4px;padding-inline-start:4px;-webkit-padding-end:4px;padding-inline-end:4px;padding-top:4px;padding-bottom:4px;position:absolute;width:36px;height:5px;-webkit-transform:translate(-50%, -50%);transform:translate(-50%, -50%);content:\"\"}:host(.modal-sheet){--height:calc(100% - (var(--ion-safe-area-top) + 10px))}:host(.modal-sheet) .modal-wrapper,:host(.modal-sheet) .modal-shadow{position:absolute;bottom:0}:host(.modal-sheet.modal-no-expand-scroll) ion-footer{position:absolute;bottom:0;width:var(--width)}:host{--backdrop-opacity:var(--ion-backdrop-opacity, 0.4)}:host(.modal-card),:host(.modal-sheet){--border-radius:10px}@media only screen and (min-width: 768px) and (min-height: 600px){:host{--border-radius:10px}}.modal-wrapper{-webkit-transform:translate3d(0, 100%, 0);transform:translate3d(0, 100%, 0)}@media screen and (max-width: 767px){@supports (width: max(0px, 1px)){:host(.modal-card){--height:calc(100% - max(30px, var(--ion-safe-area-top)) - 10px)}}@supports not (width: max(0px, 1px)){:host(.modal-card){--height:calc(100% - 40px)}}:host(.modal-card) .modal-wrapper{border-start-start-radius:var(--border-radius);border-start-end-radius:var(--border-radius);border-end-end-radius:0;border-end-start-radius:0}:host(.modal-card){--backdrop-opacity:0;--width:100%;-ms-flex-align:end;align-items:flex-end}:host(.modal-card) .modal-shadow{display:none}:host(.modal-card) ion-backdrop{pointer-events:none}}@media screen and (min-width: 768px){:host(.modal-card){--width:calc(100% - 120px);--height:calc(100% - (120px + var(--ion-safe-area-top) + var(--ion-safe-area-bottom)));--max-width:720px;--max-height:1000px;--backdrop-opacity:0;--box-shadow:0px 0px 30px 10px rgba(0, 0, 0, 0.1);-webkit-transition:all 0.5s ease-in-out;transition:all 0.5s ease-in-out}:host(.modal-card) .modal-wrapper{-webkit-box-shadow:none;box-shadow:none}:host(.modal-card) .modal-shadow{-webkit-box-shadow:var(--box-shadow);box-shadow:var(--box-shadow)}}:host(.modal-sheet) .modal-wrapper{border-start-start-radius:var(--border-radius);border-start-end-radius:var(--border-radius);border-end-end-radius:0;border-end-start-radius:0}";
|
|
1355
1295
|
const IonModalIosStyle0 = modalIosCss;
|
|
1356
1296
|
|
|
1357
1297
|
const modalMdCss = ":host{--width:100%;--min-width:auto;--max-width:auto;--height:100%;--min-height:auto;--max-height:auto;--overflow:hidden;--border-radius:0;--border-width:0;--border-style:none;--border-color:transparent;--background:var(--ion-background-color, #fff);--box-shadow:none;--backdrop-opacity:0;left:0;right:0;top:0;bottom:0;display:-ms-flexbox;display:flex;position:absolute;-ms-flex-align:center;align-items:center;-ms-flex-pack:center;justify-content:center;outline:none;color:var(--ion-text-color, #000);contain:strict}.modal-wrapper,ion-backdrop{pointer-events:auto}:host(.overlay-hidden){display:none}.modal-wrapper,.modal-shadow{border-radius:var(--border-radius);width:var(--width);min-width:var(--min-width);max-width:var(--max-width);height:var(--height);min-height:var(--min-height);max-height:var(--max-height);border-width:var(--border-width);border-style:var(--border-style);border-color:var(--border-color);background:var(--background);-webkit-box-shadow:var(--box-shadow);box-shadow:var(--box-shadow);overflow:var(--overflow);z-index:10}.modal-shadow{position:absolute;background:transparent}@media only screen and (min-width: 768px) and (min-height: 600px){:host{--width:600px;--height:500px;--ion-safe-area-top:0px;--ion-safe-area-bottom:0px;--ion-safe-area-right:0px;--ion-safe-area-left:0px}}@media only screen and (min-width: 768px) and (min-height: 768px){:host{--width:600px;--height:600px}}.modal-handle{left:0px;right:0px;top:5px;border-radius:8px;-webkit-margin-start:auto;margin-inline-start:auto;-webkit-margin-end:auto;margin-inline-end:auto;position:absolute;width:36px;height:5px;-webkit-transform:translateZ(0);transform:translateZ(0);border:0;background:var(--ion-color-step-350, var(--ion-background-color-step-350, #c0c0be));cursor:pointer;z-index:11}.modal-handle::before{-webkit-padding-start:4px;padding-inline-start:4px;-webkit-padding-end:4px;padding-inline-end:4px;padding-top:4px;padding-bottom:4px;position:absolute;width:36px;height:5px;-webkit-transform:translate(-50%, -50%);transform:translate(-50%, -50%);content:\"\"}:host(.modal-sheet){--height:calc(100% - (var(--ion-safe-area-top) + 10px))}:host(.modal-sheet) .modal-wrapper,:host(.modal-sheet) .modal-shadow{position:absolute;bottom:0}:host(.modal-sheet.modal-no-expand-scroll) ion-footer{position:absolute;bottom:0;width:var(--width)}:host{--backdrop-opacity:var(--ion-backdrop-opacity, 0.32)}@media only screen and (min-width: 768px) and (min-height: 600px){:host{--border-radius:2px;--box-shadow:0 28px 48px rgba(0, 0, 0, 0.4)}}.modal-wrapper{-webkit-transform:translate3d(0, 40px, 0);transform:translate3d(0, 40px, 0);opacity:0.01}";
|
|
@@ -31,47 +31,7 @@ export const iosEnterAnimation = (baseEl, opts) => {
|
|
|
31
31
|
.addElement(baseEl)
|
|
32
32
|
.easing('cubic-bezier(0.32,0.72,0,1)')
|
|
33
33
|
.duration(500)
|
|
34
|
-
.addAnimation([wrapperAnimation])
|
|
35
|
-
.beforeAddWrite(() => {
|
|
36
|
-
if (expandToScroll) {
|
|
37
|
-
// Scroll can only be done when the modal is fully expanded.
|
|
38
|
-
return;
|
|
39
|
-
}
|
|
40
|
-
/**
|
|
41
|
-
* There are some browsers that causes flickering when
|
|
42
|
-
* dragging the content when scroll is enabled at every
|
|
43
|
-
* breakpoint. This is due to the wrapper element being
|
|
44
|
-
* transformed off the screen and having a snap animation.
|
|
45
|
-
*
|
|
46
|
-
* A workaround is to clone the footer element and append
|
|
47
|
-
* it outside of the wrapper element. This way, the footer
|
|
48
|
-
* is still visible and the drag can be done without
|
|
49
|
-
* flickering. The original footer is hidden until the modal
|
|
50
|
-
* is dismissed. This maintains the animation of the footer
|
|
51
|
-
* when the modal is dismissed.
|
|
52
|
-
*
|
|
53
|
-
* The workaround needs to be done before the animation starts
|
|
54
|
-
* so there are no flickering issues.
|
|
55
|
-
*/
|
|
56
|
-
const ionFooter = baseEl.querySelector('ion-footer');
|
|
57
|
-
/**
|
|
58
|
-
* This check is needed to prevent more than one footer
|
|
59
|
-
* from being appended to the shadow root.
|
|
60
|
-
* Otherwise, iOS and MD enter animations would append
|
|
61
|
-
* the footer twice.
|
|
62
|
-
*/
|
|
63
|
-
const ionFooterAlreadyAppended = baseEl.shadowRoot.querySelector('ion-footer');
|
|
64
|
-
if (ionFooter && !ionFooterAlreadyAppended) {
|
|
65
|
-
const footerHeight = ionFooter.clientHeight;
|
|
66
|
-
const clonedFooter = ionFooter.cloneNode(true);
|
|
67
|
-
baseEl.shadowRoot.appendChild(clonedFooter);
|
|
68
|
-
ionFooter.style.setProperty('display', 'none');
|
|
69
|
-
ionFooter.setAttribute('aria-hidden', 'true');
|
|
70
|
-
// Padding is added to prevent some content from being hidden.
|
|
71
|
-
const page = baseEl.querySelector('.ion-page');
|
|
72
|
-
page.style.setProperty('padding-bottom', `${footerHeight}px`);
|
|
73
|
-
}
|
|
74
|
-
});
|
|
34
|
+
.addAnimation([wrapperAnimation]);
|
|
75
35
|
if (contentAnimation) {
|
|
76
36
|
baseAnimation.addAnimation(contentAnimation);
|
|
77
37
|
}
|
|
@@ -14,7 +14,7 @@ const createLeaveAnimation = () => {
|
|
|
14
14
|
* iOS Modal Leave Animation
|
|
15
15
|
*/
|
|
16
16
|
export const iosLeaveAnimation = (baseEl, opts, duration = 500) => {
|
|
17
|
-
const { presentingEl, currentBreakpoint
|
|
17
|
+
const { presentingEl, currentBreakpoint } = opts;
|
|
18
18
|
const root = getElementRoot(baseEl);
|
|
19
19
|
const { wrapperAnimation, backdropAnimation } = currentBreakpoint !== undefined ? createSheetLeaveAnimation(opts) : createLeaveAnimation();
|
|
20
20
|
backdropAnimation.addElement(root.querySelector('ion-backdrop'));
|
|
@@ -23,29 +23,7 @@ export const iosLeaveAnimation = (baseEl, opts, duration = 500) => {
|
|
|
23
23
|
.addElement(baseEl)
|
|
24
24
|
.easing('cubic-bezier(0.32,0.72,0,1)')
|
|
25
25
|
.duration(duration)
|
|
26
|
-
.addAnimation(wrapperAnimation)
|
|
27
|
-
.beforeAddWrite(() => {
|
|
28
|
-
if (expandToScroll) {
|
|
29
|
-
// Scroll can only be done when the modal is fully expanded.
|
|
30
|
-
return;
|
|
31
|
-
}
|
|
32
|
-
/**
|
|
33
|
-
* If expandToScroll is disabled, we need to swap
|
|
34
|
-
* the visibility to the original, so the footer
|
|
35
|
-
* dismisses with the modal and doesn't stay
|
|
36
|
-
* until the modal is removed from the DOM.
|
|
37
|
-
*/
|
|
38
|
-
const ionFooter = baseEl.querySelector('ion-footer');
|
|
39
|
-
if (ionFooter) {
|
|
40
|
-
const clonedFooter = baseEl.shadowRoot.querySelector('ion-footer');
|
|
41
|
-
ionFooter.style.removeProperty('display');
|
|
42
|
-
ionFooter.removeAttribute('aria-hidden');
|
|
43
|
-
clonedFooter.style.setProperty('display', 'none');
|
|
44
|
-
clonedFooter.setAttribute('aria-hidden', 'true');
|
|
45
|
-
const page = baseEl.querySelector('.ion-page');
|
|
46
|
-
page.style.removeProperty('padding-bottom');
|
|
47
|
-
}
|
|
48
|
-
});
|
|
26
|
+
.addAnimation(wrapperAnimation);
|
|
49
27
|
if (presentingEl) {
|
|
50
28
|
const isMobile = window.innerWidth < 768;
|
|
51
29
|
const hasCardModal = presentingEl.tagName === 'ION-MODAL' && presentingEl.presentingElement !== undefined;
|
|
@@ -28,52 +28,12 @@ export const mdEnterAnimation = (baseEl, opts) => {
|
|
|
28
28
|
wrapperAnimation.addElement(root.querySelector('.modal-wrapper'));
|
|
29
29
|
// The content animation is only added if scrolling is enabled for
|
|
30
30
|
// all the breakpoints.
|
|
31
|
-
expandToScroll && (contentAnimation === null || contentAnimation === void 0 ? void 0 : contentAnimation.addElement(baseEl.querySelector('.ion-page')));
|
|
31
|
+
!expandToScroll && (contentAnimation === null || contentAnimation === void 0 ? void 0 : contentAnimation.addElement(baseEl.querySelector('.ion-page')));
|
|
32
32
|
const baseAnimation = createAnimation()
|
|
33
33
|
.addElement(baseEl)
|
|
34
34
|
.easing('cubic-bezier(0.36,0.66,0.04,1)')
|
|
35
35
|
.duration(280)
|
|
36
|
-
.addAnimation([backdropAnimation, wrapperAnimation])
|
|
37
|
-
.beforeAddWrite(() => {
|
|
38
|
-
if (expandToScroll) {
|
|
39
|
-
// Scroll can only be done when the modal is fully expanded.
|
|
40
|
-
return;
|
|
41
|
-
}
|
|
42
|
-
/**
|
|
43
|
-
* There are some browsers that causes flickering when
|
|
44
|
-
* dragging the content when scroll is enabled at every
|
|
45
|
-
* breakpoint. This is due to the wrapper element being
|
|
46
|
-
* transformed off the screen and having a snap animation.
|
|
47
|
-
*
|
|
48
|
-
* A workaround is to clone the footer element and append
|
|
49
|
-
* it outside of the wrapper element. This way, the footer
|
|
50
|
-
* is still visible and the drag can be done without
|
|
51
|
-
* flickering. The original footer is hidden until the modal
|
|
52
|
-
* is dismissed. This maintains the animation of the footer
|
|
53
|
-
* when the modal is dismissed.
|
|
54
|
-
*
|
|
55
|
-
* The workaround needs to be done before the animation starts
|
|
56
|
-
* so there are no flickering issues.
|
|
57
|
-
*/
|
|
58
|
-
const ionFooter = baseEl.querySelector('ion-footer');
|
|
59
|
-
/**
|
|
60
|
-
* This check is needed to prevent more than one footer
|
|
61
|
-
* from being appended to the shadow root.
|
|
62
|
-
* Otherwise, iOS and MD enter animations would append
|
|
63
|
-
* the footer twice.
|
|
64
|
-
*/
|
|
65
|
-
const ionFooterAlreadyAppended = baseEl.shadowRoot.querySelector('ion-footer');
|
|
66
|
-
if (ionFooter && !ionFooterAlreadyAppended) {
|
|
67
|
-
const footerHeight = ionFooter.clientHeight;
|
|
68
|
-
const clonedFooter = ionFooter.cloneNode(true);
|
|
69
|
-
baseEl.shadowRoot.appendChild(clonedFooter);
|
|
70
|
-
ionFooter.style.setProperty('display', 'none');
|
|
71
|
-
ionFooter.setAttribute('aria-hidden', 'true');
|
|
72
|
-
// Padding is added to prevent some content from being hidden.
|
|
73
|
-
const page = baseEl.querySelector('.ion-page');
|
|
74
|
-
page.style.setProperty('padding-bottom', `${footerHeight}px`);
|
|
75
|
-
}
|
|
76
|
-
});
|
|
36
|
+
.addAnimation([backdropAnimation, wrapperAnimation]);
|
|
77
37
|
if (contentAnimation) {
|
|
78
38
|
baseAnimation.addAnimation(contentAnimation);
|
|
79
39
|
}
|
|
@@ -16,7 +16,7 @@ const createLeaveAnimation = () => {
|
|
|
16
16
|
* Md Modal Leave Animation
|
|
17
17
|
*/
|
|
18
18
|
export const mdLeaveAnimation = (baseEl, opts) => {
|
|
19
|
-
const { currentBreakpoint
|
|
19
|
+
const { currentBreakpoint } = opts;
|
|
20
20
|
const root = getElementRoot(baseEl);
|
|
21
21
|
const { wrapperAnimation, backdropAnimation } = currentBreakpoint !== undefined ? createSheetLeaveAnimation(opts) : createLeaveAnimation();
|
|
22
22
|
backdropAnimation.addElement(root.querySelector('ion-backdrop'));
|
|
@@ -24,28 +24,6 @@ export const mdLeaveAnimation = (baseEl, opts) => {
|
|
|
24
24
|
const baseAnimation = createAnimation()
|
|
25
25
|
.easing('cubic-bezier(0.47,0,0.745,0.715)')
|
|
26
26
|
.duration(200)
|
|
27
|
-
.addAnimation([backdropAnimation, wrapperAnimation])
|
|
28
|
-
.beforeAddWrite(() => {
|
|
29
|
-
if (expandToScroll) {
|
|
30
|
-
// Scroll can only be done when the modal is fully expanded.
|
|
31
|
-
return;
|
|
32
|
-
}
|
|
33
|
-
/**
|
|
34
|
-
* If expandToScroll is disabled, we need to swap
|
|
35
|
-
* the visibility to the original, so the footer
|
|
36
|
-
* dismisses with the modal and doesn't stay
|
|
37
|
-
* until the modal is removed from the DOM.
|
|
38
|
-
*/
|
|
39
|
-
const ionFooter = baseEl.querySelector('ion-footer');
|
|
40
|
-
if (ionFooter) {
|
|
41
|
-
const clonedFooter = baseEl.shadowRoot.querySelector('ion-footer');
|
|
42
|
-
ionFooter.style.removeProperty('display');
|
|
43
|
-
ionFooter.removeAttribute('aria-hidden');
|
|
44
|
-
clonedFooter.style.setProperty('display', 'none');
|
|
45
|
-
clonedFooter.setAttribute('aria-hidden', 'true');
|
|
46
|
-
const page = baseEl.querySelector('.ion-page');
|
|
47
|
-
page.style.removeProperty('padding-bottom');
|
|
48
|
-
}
|
|
49
|
-
});
|
|
27
|
+
.addAnimation([backdropAnimation, wrapperAnimation]);
|
|
50
28
|
return baseAnimation;
|
|
51
29
|
};
|