@ionic/core 8.5.7 → 8.5.8-dev.11748364689.107665ad
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 +58 -157
- package/dist/cjs/ion-modal.cjs.entry.js +58 -157
- 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 +1 -41
- package/dist/collection/components/modal/animations/md.leave.js +2 -24
- package/dist/collection/components/modal/gestures/sheet.js +52 -27
- package/dist/docs.json +1 -1
- package/dist/esm/ion-modal.entry.js +58 -157
- package/dist/esm-es5/ion-modal.entry.js +1 -1
- package/dist/ionic/ionic.esm.js +1 -1
- package/dist/ionic/p-451706f5.entry.js +4 -0
- package/dist/ionic/p-c8731f25.system.entry.js +4 -0
- package/dist/ionic/p-f725bf9e.system.js +1 -1
- package/hydrate/index.js +58 -157
- package/hydrate/index.mjs +58 -157
- package/package.json +1 -1
- package/dist/ionic/p-12914457.entry.js +0 -4
- package/dist/ionic/p-cec902a0.system.entry.js +0 -4
package/components/modal.js
CHANGED
|
@@ -582,47 +582,7 @@ const iosEnterAnimation = (baseEl, opts) => {
|
|
|
582
582
|
.addElement(baseEl)
|
|
583
583
|
.easing('cubic-bezier(0.32,0.72,0,1)')
|
|
584
584
|
.duration(500)
|
|
585
|
-
.addAnimation([wrapperAnimation])
|
|
586
|
-
.beforeAddWrite(() => {
|
|
587
|
-
if (expandToScroll) {
|
|
588
|
-
// Scroll can only be done when the modal is fully expanded.
|
|
589
|
-
return;
|
|
590
|
-
}
|
|
591
|
-
/**
|
|
592
|
-
* There are some browsers that causes flickering when
|
|
593
|
-
* dragging the content when scroll is enabled at every
|
|
594
|
-
* breakpoint. This is due to the wrapper element being
|
|
595
|
-
* transformed off the screen and having a snap animation.
|
|
596
|
-
*
|
|
597
|
-
* A workaround is to clone the footer element and append
|
|
598
|
-
* it outside of the wrapper element. This way, the footer
|
|
599
|
-
* is still visible and the drag can be done without
|
|
600
|
-
* flickering. The original footer is hidden until the modal
|
|
601
|
-
* is dismissed. This maintains the animation of the footer
|
|
602
|
-
* when the modal is dismissed.
|
|
603
|
-
*
|
|
604
|
-
* The workaround needs to be done before the animation starts
|
|
605
|
-
* so there are no flickering issues.
|
|
606
|
-
*/
|
|
607
|
-
const ionFooter = baseEl.querySelector('ion-footer');
|
|
608
|
-
/**
|
|
609
|
-
* This check is needed to prevent more than one footer
|
|
610
|
-
* from being appended to the shadow root.
|
|
611
|
-
* Otherwise, iOS and MD enter animations would append
|
|
612
|
-
* the footer twice.
|
|
613
|
-
*/
|
|
614
|
-
const ionFooterAlreadyAppended = baseEl.shadowRoot.querySelector('ion-footer');
|
|
615
|
-
if (ionFooter && !ionFooterAlreadyAppended) {
|
|
616
|
-
const footerHeight = ionFooter.clientHeight;
|
|
617
|
-
const clonedFooter = ionFooter.cloneNode(true);
|
|
618
|
-
baseEl.shadowRoot.appendChild(clonedFooter);
|
|
619
|
-
ionFooter.style.setProperty('display', 'none');
|
|
620
|
-
ionFooter.setAttribute('aria-hidden', 'true');
|
|
621
|
-
// Padding is added to prevent some content from being hidden.
|
|
622
|
-
const page = baseEl.querySelector('.ion-page');
|
|
623
|
-
page.style.setProperty('padding-bottom', `${footerHeight}px`);
|
|
624
|
-
}
|
|
625
|
-
});
|
|
585
|
+
.addAnimation([wrapperAnimation]);
|
|
626
586
|
if (contentAnimation) {
|
|
627
587
|
baseAnimation.addAnimation(contentAnimation);
|
|
628
588
|
}
|
|
@@ -703,7 +663,7 @@ const createLeaveAnimation$1 = () => {
|
|
|
703
663
|
* iOS Modal Leave Animation
|
|
704
664
|
*/
|
|
705
665
|
const iosLeaveAnimation = (baseEl, opts, duration = 500) => {
|
|
706
|
-
const { presentingEl, currentBreakpoint
|
|
666
|
+
const { presentingEl, currentBreakpoint } = opts;
|
|
707
667
|
const root = getElementRoot(baseEl);
|
|
708
668
|
const { wrapperAnimation, backdropAnimation } = currentBreakpoint !== undefined ? createSheetLeaveAnimation(opts) : createLeaveAnimation$1();
|
|
709
669
|
backdropAnimation.addElement(root.querySelector('ion-backdrop'));
|
|
@@ -712,29 +672,7 @@ const iosLeaveAnimation = (baseEl, opts, duration = 500) => {
|
|
|
712
672
|
.addElement(baseEl)
|
|
713
673
|
.easing('cubic-bezier(0.32,0.72,0,1)')
|
|
714
674
|
.duration(duration)
|
|
715
|
-
.addAnimation(wrapperAnimation)
|
|
716
|
-
.beforeAddWrite(() => {
|
|
717
|
-
if (expandToScroll) {
|
|
718
|
-
// Scroll can only be done when the modal is fully expanded.
|
|
719
|
-
return;
|
|
720
|
-
}
|
|
721
|
-
/**
|
|
722
|
-
* If expandToScroll is disabled, we need to swap
|
|
723
|
-
* the visibility to the original, so the footer
|
|
724
|
-
* dismisses with the modal and doesn't stay
|
|
725
|
-
* until the modal is removed from the DOM.
|
|
726
|
-
*/
|
|
727
|
-
const ionFooter = baseEl.querySelector('ion-footer');
|
|
728
|
-
if (ionFooter) {
|
|
729
|
-
const clonedFooter = baseEl.shadowRoot.querySelector('ion-footer');
|
|
730
|
-
ionFooter.style.removeProperty('display');
|
|
731
|
-
ionFooter.removeAttribute('aria-hidden');
|
|
732
|
-
clonedFooter.style.setProperty('display', 'none');
|
|
733
|
-
clonedFooter.setAttribute('aria-hidden', 'true');
|
|
734
|
-
const page = baseEl.querySelector('.ion-page');
|
|
735
|
-
page.style.removeProperty('padding-bottom');
|
|
736
|
-
}
|
|
737
|
-
});
|
|
675
|
+
.addAnimation(wrapperAnimation);
|
|
738
676
|
if (presentingEl) {
|
|
739
677
|
const isMobile = window.innerWidth < 768;
|
|
740
678
|
const hasCardModal = presentingEl.tagName === 'ION-MODAL' && presentingEl.presentingElement !== undefined;
|
|
@@ -830,47 +768,7 @@ const mdEnterAnimation = (baseEl, opts) => {
|
|
|
830
768
|
.addElement(baseEl)
|
|
831
769
|
.easing('cubic-bezier(0.36,0.66,0.04,1)')
|
|
832
770
|
.duration(280)
|
|
833
|
-
.addAnimation([backdropAnimation, wrapperAnimation])
|
|
834
|
-
.beforeAddWrite(() => {
|
|
835
|
-
if (expandToScroll) {
|
|
836
|
-
// Scroll can only be done when the modal is fully expanded.
|
|
837
|
-
return;
|
|
838
|
-
}
|
|
839
|
-
/**
|
|
840
|
-
* There are some browsers that causes flickering when
|
|
841
|
-
* dragging the content when scroll is enabled at every
|
|
842
|
-
* breakpoint. This is due to the wrapper element being
|
|
843
|
-
* transformed off the screen and having a snap animation.
|
|
844
|
-
*
|
|
845
|
-
* A workaround is to clone the footer element and append
|
|
846
|
-
* it outside of the wrapper element. This way, the footer
|
|
847
|
-
* is still visible and the drag can be done without
|
|
848
|
-
* flickering. The original footer is hidden until the modal
|
|
849
|
-
* is dismissed. This maintains the animation of the footer
|
|
850
|
-
* when the modal is dismissed.
|
|
851
|
-
*
|
|
852
|
-
* The workaround needs to be done before the animation starts
|
|
853
|
-
* so there are no flickering issues.
|
|
854
|
-
*/
|
|
855
|
-
const ionFooter = baseEl.querySelector('ion-footer');
|
|
856
|
-
/**
|
|
857
|
-
* This check is needed to prevent more than one footer
|
|
858
|
-
* from being appended to the shadow root.
|
|
859
|
-
* Otherwise, iOS and MD enter animations would append
|
|
860
|
-
* the footer twice.
|
|
861
|
-
*/
|
|
862
|
-
const ionFooterAlreadyAppended = baseEl.shadowRoot.querySelector('ion-footer');
|
|
863
|
-
if (ionFooter && !ionFooterAlreadyAppended) {
|
|
864
|
-
const footerHeight = ionFooter.clientHeight;
|
|
865
|
-
const clonedFooter = ionFooter.cloneNode(true);
|
|
866
|
-
baseEl.shadowRoot.appendChild(clonedFooter);
|
|
867
|
-
ionFooter.style.setProperty('display', 'none');
|
|
868
|
-
ionFooter.setAttribute('aria-hidden', 'true');
|
|
869
|
-
// Padding is added to prevent some content from being hidden.
|
|
870
|
-
const page = baseEl.querySelector('.ion-page');
|
|
871
|
-
page.style.setProperty('padding-bottom', `${footerHeight}px`);
|
|
872
|
-
}
|
|
873
|
-
});
|
|
771
|
+
.addAnimation([backdropAnimation, wrapperAnimation]);
|
|
874
772
|
if (contentAnimation) {
|
|
875
773
|
baseAnimation.addAnimation(contentAnimation);
|
|
876
774
|
}
|
|
@@ -889,7 +787,7 @@ const createLeaveAnimation = () => {
|
|
|
889
787
|
* Md Modal Leave Animation
|
|
890
788
|
*/
|
|
891
789
|
const mdLeaveAnimation = (baseEl, opts) => {
|
|
892
|
-
const { currentBreakpoint
|
|
790
|
+
const { currentBreakpoint } = opts;
|
|
893
791
|
const root = getElementRoot(baseEl);
|
|
894
792
|
const { wrapperAnimation, backdropAnimation } = currentBreakpoint !== undefined ? createSheetLeaveAnimation(opts) : createLeaveAnimation();
|
|
895
793
|
backdropAnimation.addElement(root.querySelector('ion-backdrop'));
|
|
@@ -897,29 +795,7 @@ const mdLeaveAnimation = (baseEl, opts) => {
|
|
|
897
795
|
const baseAnimation = createAnimation()
|
|
898
796
|
.easing('cubic-bezier(0.47,0,0.745,0.715)')
|
|
899
797
|
.duration(200)
|
|
900
|
-
.addAnimation([backdropAnimation, wrapperAnimation])
|
|
901
|
-
.beforeAddWrite(() => {
|
|
902
|
-
if (expandToScroll) {
|
|
903
|
-
// Scroll can only be done when the modal is fully expanded.
|
|
904
|
-
return;
|
|
905
|
-
}
|
|
906
|
-
/**
|
|
907
|
-
* If expandToScroll is disabled, we need to swap
|
|
908
|
-
* the visibility to the original, so the footer
|
|
909
|
-
* dismisses with the modal and doesn't stay
|
|
910
|
-
* until the modal is removed from the DOM.
|
|
911
|
-
*/
|
|
912
|
-
const ionFooter = baseEl.querySelector('ion-footer');
|
|
913
|
-
if (ionFooter) {
|
|
914
|
-
const clonedFooter = baseEl.shadowRoot.querySelector('ion-footer');
|
|
915
|
-
ionFooter.style.removeProperty('display');
|
|
916
|
-
ionFooter.removeAttribute('aria-hidden');
|
|
917
|
-
clonedFooter.style.setProperty('display', 'none');
|
|
918
|
-
clonedFooter.setAttribute('aria-hidden', 'true');
|
|
919
|
-
const page = baseEl.querySelector('.ion-page');
|
|
920
|
-
page.style.removeProperty('padding-bottom');
|
|
921
|
-
}
|
|
922
|
-
});
|
|
798
|
+
.addAnimation([backdropAnimation, wrapperAnimation]);
|
|
923
799
|
return baseAnimation;
|
|
924
800
|
};
|
|
925
801
|
|
|
@@ -951,6 +827,8 @@ const createSheetGesture = (baseEl, backdropEl, wrapperEl, initialBreakpoint, ba
|
|
|
951
827
|
let offset = 0;
|
|
952
828
|
let canDismissBlocksGesture = false;
|
|
953
829
|
let cachedScrollEl = null;
|
|
830
|
+
let cachedFooterYPosition = null;
|
|
831
|
+
let currentFooterState = null;
|
|
954
832
|
const canDismissMaxStep = 0.95;
|
|
955
833
|
const maxBreakpoint = breakpoints[breakpoints.length - 1];
|
|
956
834
|
const minBreakpoint = breakpoints[0];
|
|
@@ -980,29 +858,38 @@ const createSheetGesture = (baseEl, backdropEl, wrapperEl, initialBreakpoint, ba
|
|
|
980
858
|
baseEl.classList.add(FOCUS_TRAP_DISABLE_CLASS);
|
|
981
859
|
};
|
|
982
860
|
/**
|
|
983
|
-
* Toggles the
|
|
984
|
-
*
|
|
861
|
+
* Toggles the footer to an absolute position while moving to prevent
|
|
862
|
+
* it from shaking while the sheet is being dragged.
|
|
863
|
+
* @param footer Whether the footer is in a moving or stationary position.
|
|
985
864
|
*/
|
|
986
|
-
const
|
|
865
|
+
const swapFooterPosition = (newPosition) => {
|
|
866
|
+
var _a, _b;
|
|
987
867
|
const originalFooter = baseEl.querySelector('ion-footer');
|
|
988
868
|
if (!originalFooter) {
|
|
989
869
|
return;
|
|
990
870
|
}
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
if (footer === 'original') {
|
|
998
|
-
page.style.removeProperty('padding-bottom');
|
|
871
|
+
currentFooterState = newPosition;
|
|
872
|
+
if (newPosition === 'stationary') {
|
|
873
|
+
// Reset positioning styles to allow normal document flow
|
|
874
|
+
originalFooter.style.removeProperty('position');
|
|
875
|
+
originalFooter.style.removeProperty('bottom');
|
|
876
|
+
(_a = originalFooter.parentElement) === null || _a === void 0 ? void 0 : _a.style.removeProperty('padding-bottom');
|
|
999
877
|
}
|
|
1000
878
|
else {
|
|
1001
|
-
|
|
1002
|
-
|
|
879
|
+
// Add padding to the parent element to prevent content from being hidden
|
|
880
|
+
// when the footer is positioned absolutely. This has to be done before we
|
|
881
|
+
// make the footer absolutely positioned or we may accidentally cause the
|
|
882
|
+
// sheet to scroll.
|
|
883
|
+
const footerHeight = originalFooter.clientHeight;
|
|
884
|
+
(_b = originalFooter.parentElement) === null || _b === void 0 ? void 0 : _b.style.setProperty('padding-bottom', `${footerHeight}px`);
|
|
885
|
+
// Apply positioning styles to keep footer at bottom
|
|
886
|
+
originalFooter.style.setProperty('position', 'absolute');
|
|
887
|
+
originalFooter.style.setProperty('bottom', '0');
|
|
888
|
+
// Also cache the footer Y position, which we use to determine if the
|
|
889
|
+
// sheet has been moved below the footer. When that happens, we need to swap
|
|
890
|
+
// the position back so it will collapse correctly.
|
|
891
|
+
cachedFooterYPosition = originalFooter.getBoundingClientRect().top + window.scrollY;
|
|
1003
892
|
}
|
|
1004
|
-
footerToHide.style.setProperty('display', 'none');
|
|
1005
|
-
footerToHide.setAttribute('aria-hidden', 'true');
|
|
1006
893
|
};
|
|
1007
894
|
/**
|
|
1008
895
|
* After the entering animation completes,
|
|
@@ -1096,12 +983,11 @@ const createSheetGesture = (baseEl, backdropEl, wrapperEl, initialBreakpoint, ba
|
|
|
1096
983
|
}
|
|
1097
984
|
/**
|
|
1098
985
|
* If expandToScroll is disabled, we need to swap
|
|
1099
|
-
* the footer
|
|
1100
|
-
*
|
|
1101
|
-
* and doesn't stay on the screen after the modal is gone.
|
|
986
|
+
* the footer position to moving so that it doesn't shake
|
|
987
|
+
* while the sheet is being dragged.
|
|
1102
988
|
*/
|
|
1103
989
|
if (!expandToScroll) {
|
|
1104
|
-
|
|
990
|
+
swapFooterPosition('moving');
|
|
1105
991
|
}
|
|
1106
992
|
/**
|
|
1107
993
|
* If we are pulling down, then it is possible we are pulling on the content.
|
|
@@ -1120,6 +1006,21 @@ const createSheetGesture = (baseEl, backdropEl, wrapperEl, initialBreakpoint, ba
|
|
|
1120
1006
|
animation.progressStart(true, 1 - currentBreakpoint);
|
|
1121
1007
|
};
|
|
1122
1008
|
const onMove = (detail) => {
|
|
1009
|
+
/**
|
|
1010
|
+
* If `expandToScroll` is disabled, we need to see if we're currently below
|
|
1011
|
+
* the footer element and the footer is in a stationary position. If so,
|
|
1012
|
+
* we need to make the stationary the original position so that the footer
|
|
1013
|
+
* collapses with the sheet.
|
|
1014
|
+
*/
|
|
1015
|
+
if (!expandToScroll && cachedFooterYPosition !== null && currentFooterState !== null) {
|
|
1016
|
+
// Check if we need to swap the footer position
|
|
1017
|
+
if (detail.currentY >= cachedFooterYPosition && currentFooterState === 'moving') {
|
|
1018
|
+
swapFooterPosition('stationary');
|
|
1019
|
+
}
|
|
1020
|
+
else if (detail.currentY < cachedFooterYPosition && currentFooterState === 'stationary') {
|
|
1021
|
+
swapFooterPosition('moving');
|
|
1022
|
+
}
|
|
1023
|
+
}
|
|
1123
1024
|
/**
|
|
1124
1025
|
* If `expandToScroll` is disabled, and an upwards swipe gesture is done within
|
|
1125
1026
|
* the scrollable content, we should not allow the swipe gesture to continue.
|
|
@@ -1253,14 +1154,6 @@ const createSheetGesture = (baseEl, backdropEl, wrapperEl, initialBreakpoint, ba
|
|
|
1253
1154
|
* snapping animation completes.
|
|
1254
1155
|
*/
|
|
1255
1156
|
gesture.enable(false);
|
|
1256
|
-
/**
|
|
1257
|
-
* If expandToScroll is disabled, we need to swap
|
|
1258
|
-
* the footer visibility to the cloned one so the footer
|
|
1259
|
-
* doesn't flicker when the sheet's height is animated.
|
|
1260
|
-
*/
|
|
1261
|
-
if (!expandToScroll && shouldRemainOpen) {
|
|
1262
|
-
swapFooterVisibility('cloned');
|
|
1263
|
-
}
|
|
1264
1157
|
if (shouldPreventDismiss) {
|
|
1265
1158
|
handleCanDismiss(baseEl, animation);
|
|
1266
1159
|
}
|
|
@@ -1281,6 +1174,14 @@ const createSheetGesture = (baseEl, backdropEl, wrapperEl, initialBreakpoint, ba
|
|
|
1281
1174
|
animation
|
|
1282
1175
|
.onFinish(() => {
|
|
1283
1176
|
if (shouldRemainOpen) {
|
|
1177
|
+
/**
|
|
1178
|
+
* If expandToScroll is disabled, we need to swap
|
|
1179
|
+
* the footer position to stationary so that it
|
|
1180
|
+
* will act as it would by default
|
|
1181
|
+
*/
|
|
1182
|
+
if (!expandToScroll) {
|
|
1183
|
+
swapFooterPosition('stationary');
|
|
1184
|
+
}
|
|
1284
1185
|
/**
|
|
1285
1186
|
* Once the snapping animation completes,
|
|
1286
1187
|
* we need to reset the animation to go
|
|
@@ -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;
|
|
@@ -836,47 +774,7 @@ const mdEnterAnimation = (baseEl, opts) => {
|
|
|
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,8 @@ const createSheetGesture = (baseEl, backdropEl, wrapperEl, initialBreakpoint, ba
|
|
|
957
833
|
let offset = 0;
|
|
958
834
|
let canDismissBlocksGesture = false;
|
|
959
835
|
let cachedScrollEl = null;
|
|
836
|
+
let cachedFooterYPosition = null;
|
|
837
|
+
let currentFooterState = null;
|
|
960
838
|
const canDismissMaxStep = 0.95;
|
|
961
839
|
const maxBreakpoint = breakpoints[breakpoints.length - 1];
|
|
962
840
|
const minBreakpoint = breakpoints[0];
|
|
@@ -986,29 +864,38 @@ const createSheetGesture = (baseEl, backdropEl, wrapperEl, initialBreakpoint, ba
|
|
|
986
864
|
baseEl.classList.add(overlays.FOCUS_TRAP_DISABLE_CLASS);
|
|
987
865
|
};
|
|
988
866
|
/**
|
|
989
|
-
* Toggles the
|
|
990
|
-
*
|
|
867
|
+
* Toggles the footer to an absolute position while moving to prevent
|
|
868
|
+
* it from shaking while the sheet is being dragged.
|
|
869
|
+
* @param footer Whether the footer is in a moving or stationary position.
|
|
991
870
|
*/
|
|
992
|
-
const
|
|
871
|
+
const swapFooterPosition = (newPosition) => {
|
|
872
|
+
var _a, _b;
|
|
993
873
|
const originalFooter = baseEl.querySelector('ion-footer');
|
|
994
874
|
if (!originalFooter) {
|
|
995
875
|
return;
|
|
996
876
|
}
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
if (footer === 'original') {
|
|
1004
|
-
page.style.removeProperty('padding-bottom');
|
|
877
|
+
currentFooterState = newPosition;
|
|
878
|
+
if (newPosition === 'stationary') {
|
|
879
|
+
// Reset positioning styles to allow normal document flow
|
|
880
|
+
originalFooter.style.removeProperty('position');
|
|
881
|
+
originalFooter.style.removeProperty('bottom');
|
|
882
|
+
(_a = originalFooter.parentElement) === null || _a === void 0 ? void 0 : _a.style.removeProperty('padding-bottom');
|
|
1005
883
|
}
|
|
1006
884
|
else {
|
|
1007
|
-
|
|
1008
|
-
|
|
885
|
+
// Add padding to the parent element to prevent content from being hidden
|
|
886
|
+
// when the footer is positioned absolutely. This has to be done before we
|
|
887
|
+
// make the footer absolutely positioned or we may accidentally cause the
|
|
888
|
+
// sheet to scroll.
|
|
889
|
+
const footerHeight = originalFooter.clientHeight;
|
|
890
|
+
(_b = originalFooter.parentElement) === null || _b === void 0 ? void 0 : _b.style.setProperty('padding-bottom', `${footerHeight}px`);
|
|
891
|
+
// Apply positioning styles to keep footer at bottom
|
|
892
|
+
originalFooter.style.setProperty('position', 'absolute');
|
|
893
|
+
originalFooter.style.setProperty('bottom', '0');
|
|
894
|
+
// Also cache the footer Y position, which we use to determine if the
|
|
895
|
+
// sheet has been moved below the footer. When that happens, we need to swap
|
|
896
|
+
// the position back so it will collapse correctly.
|
|
897
|
+
cachedFooterYPosition = originalFooter.getBoundingClientRect().top + window.scrollY;
|
|
1009
898
|
}
|
|
1010
|
-
footerToHide.style.setProperty('display', 'none');
|
|
1011
|
-
footerToHide.setAttribute('aria-hidden', 'true');
|
|
1012
899
|
};
|
|
1013
900
|
/**
|
|
1014
901
|
* After the entering animation completes,
|
|
@@ -1102,12 +989,11 @@ const createSheetGesture = (baseEl, backdropEl, wrapperEl, initialBreakpoint, ba
|
|
|
1102
989
|
}
|
|
1103
990
|
/**
|
|
1104
991
|
* 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.
|
|
992
|
+
* the footer position to moving so that it doesn't shake
|
|
993
|
+
* while the sheet is being dragged.
|
|
1108
994
|
*/
|
|
1109
995
|
if (!expandToScroll) {
|
|
1110
|
-
|
|
996
|
+
swapFooterPosition('moving');
|
|
1111
997
|
}
|
|
1112
998
|
/**
|
|
1113
999
|
* If we are pulling down, then it is possible we are pulling on the content.
|
|
@@ -1126,6 +1012,21 @@ const createSheetGesture = (baseEl, backdropEl, wrapperEl, initialBreakpoint, ba
|
|
|
1126
1012
|
animation.progressStart(true, 1 - currentBreakpoint);
|
|
1127
1013
|
};
|
|
1128
1014
|
const onMove = (detail) => {
|
|
1015
|
+
/**
|
|
1016
|
+
* If `expandToScroll` is disabled, we need to see if we're currently below
|
|
1017
|
+
* the footer element and the footer is in a stationary position. If so,
|
|
1018
|
+
* we need to make the stationary the original position so that the footer
|
|
1019
|
+
* collapses with the sheet.
|
|
1020
|
+
*/
|
|
1021
|
+
if (!expandToScroll && cachedFooterYPosition !== null && currentFooterState !== null) {
|
|
1022
|
+
// Check if we need to swap the footer position
|
|
1023
|
+
if (detail.currentY >= cachedFooterYPosition && currentFooterState === 'moving') {
|
|
1024
|
+
swapFooterPosition('stationary');
|
|
1025
|
+
}
|
|
1026
|
+
else if (detail.currentY < cachedFooterYPosition && currentFooterState === 'stationary') {
|
|
1027
|
+
swapFooterPosition('moving');
|
|
1028
|
+
}
|
|
1029
|
+
}
|
|
1129
1030
|
/**
|
|
1130
1031
|
* If `expandToScroll` is disabled, and an upwards swipe gesture is done within
|
|
1131
1032
|
* the scrollable content, we should not allow the swipe gesture to continue.
|
|
@@ -1259,14 +1160,6 @@ const createSheetGesture = (baseEl, backdropEl, wrapperEl, initialBreakpoint, ba
|
|
|
1259
1160
|
* snapping animation completes.
|
|
1260
1161
|
*/
|
|
1261
1162
|
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
1163
|
if (shouldPreventDismiss) {
|
|
1271
1164
|
handleCanDismiss(baseEl, animation);
|
|
1272
1165
|
}
|
|
@@ -1287,6 +1180,14 @@ const createSheetGesture = (baseEl, backdropEl, wrapperEl, initialBreakpoint, ba
|
|
|
1287
1180
|
animation
|
|
1288
1181
|
.onFinish(() => {
|
|
1289
1182
|
if (shouldRemainOpen) {
|
|
1183
|
+
/**
|
|
1184
|
+
* If expandToScroll is disabled, we need to swap
|
|
1185
|
+
* the footer position to stationary so that it
|
|
1186
|
+
* will act as it would by default
|
|
1187
|
+
*/
|
|
1188
|
+
if (!expandToScroll) {
|
|
1189
|
+
swapFooterPosition('stationary');
|
|
1190
|
+
}
|
|
1290
1191
|
/**
|
|
1291
1192
|
* Once the snapping animation completes,
|
|
1292
1193
|
* we need to reset the animation to go
|
|
@@ -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
|
}
|