@ionic/core 8.5.7 → 8.5.8-dev.11748374591.17686118
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 +68 -159
- 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 +68 -159
- 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 +62 -29
- package/dist/docs.json +1 -1
- package/dist/esm/ion-modal.entry.js +68 -159
- package/dist/esm-es5/ion-modal.entry.js +1 -1
- package/dist/ionic/ionic.esm.js +1 -1
- package/dist/ionic/p-b7242f55.entry.js +4 -0
- package/dist/ionic/p-db06d822.system.entry.js +4 -0
- package/dist/ionic/p-f725bf9e.system.js +1 -1
- package/hydrate/index.js +68 -159
- package/hydrate/index.mjs +68 -159
- 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;
|
|
@@ -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,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,45 @@ 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 footer 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('bottom');
|
|
886
|
+
page === null || page === void 0 ? void 0 : page.style.removeProperty('padding-bottom');
|
|
887
|
+
// Move to page
|
|
888
|
+
page === null || page === void 0 ? void 0 : page.appendChild(cachedFooterEl);
|
|
1005
889
|
}
|
|
1006
890
|
else {
|
|
1007
|
-
|
|
1008
|
-
|
|
891
|
+
// Add padding to the parent element to prevent content from being hidden
|
|
892
|
+
// when the footer is positioned absolutely. This has to be done before we
|
|
893
|
+
// make the footer absolutely positioned or we may accidentally cause the
|
|
894
|
+
// sheet to scroll.
|
|
895
|
+
const footerHeight = cachedFooterEl.clientHeight;
|
|
896
|
+
page === null || page === void 0 ? void 0 : page.style.setProperty('padding-bottom', `${footerHeight}px`);
|
|
897
|
+
// Apply positioning styles to keep footer at bottom
|
|
898
|
+
cachedFooterEl.classList.add('modal-footer-moving');
|
|
899
|
+
cachedFooterEl.style.setProperty('position', 'absolute');
|
|
900
|
+
cachedFooterEl.style.setProperty('bottom', '0');
|
|
901
|
+
// Also cache the footer Y position, which we use to determine if the
|
|
902
|
+
// sheet has been moved below the footer. When that happens, we need to swap
|
|
903
|
+
// the position back so it will collapse correctly.
|
|
904
|
+
cachedFooterYPosition = cachedFooterEl.getBoundingClientRect().top + window.scrollY;
|
|
905
|
+
document.body.appendChild(cachedFooterEl);
|
|
1009
906
|
}
|
|
1010
|
-
footerToHide.style.setProperty('display', 'none');
|
|
1011
|
-
footerToHide.setAttribute('aria-hidden', 'true');
|
|
1012
907
|
};
|
|
1013
908
|
/**
|
|
1014
909
|
* After the entering animation completes,
|
|
@@ -1102,12 +997,11 @@ const createSheetGesture = (baseEl, backdropEl, wrapperEl, initialBreakpoint, ba
|
|
|
1102
997
|
}
|
|
1103
998
|
/**
|
|
1104
999
|
* 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.
|
|
1000
|
+
* the footer position to moving so that it doesn't shake
|
|
1001
|
+
* while the sheet is being dragged.
|
|
1108
1002
|
*/
|
|
1109
1003
|
if (!expandToScroll) {
|
|
1110
|
-
|
|
1004
|
+
swapFooterPosition('moving');
|
|
1111
1005
|
}
|
|
1112
1006
|
/**
|
|
1113
1007
|
* If we are pulling down, then it is possible we are pulling on the content.
|
|
@@ -1126,6 +1020,21 @@ const createSheetGesture = (baseEl, backdropEl, wrapperEl, initialBreakpoint, ba
|
|
|
1126
1020
|
animation.progressStart(true, 1 - currentBreakpoint);
|
|
1127
1021
|
};
|
|
1128
1022
|
const onMove = (detail) => {
|
|
1023
|
+
/**
|
|
1024
|
+
* If `expandToScroll` is disabled, we need to see if we're currently below
|
|
1025
|
+
* the footer element and the footer is in a stationary position. If so,
|
|
1026
|
+
* we need to make the stationary the original position so that the footer
|
|
1027
|
+
* collapses with the sheet.
|
|
1028
|
+
*/
|
|
1029
|
+
if (!expandToScroll && cachedFooterYPosition !== null && currentFooterState !== null) {
|
|
1030
|
+
// Check if we need to swap the footer position
|
|
1031
|
+
if (detail.currentY >= cachedFooterYPosition && currentFooterState === 'moving') {
|
|
1032
|
+
swapFooterPosition('stationary');
|
|
1033
|
+
}
|
|
1034
|
+
else if (detail.currentY < cachedFooterYPosition && currentFooterState === 'stationary') {
|
|
1035
|
+
swapFooterPosition('moving');
|
|
1036
|
+
}
|
|
1037
|
+
}
|
|
1129
1038
|
/**
|
|
1130
1039
|
* If `expandToScroll` is disabled, and an upwards swipe gesture is done within
|
|
1131
1040
|
* the scrollable content, we should not allow the swipe gesture to continue.
|
|
@@ -1259,14 +1168,6 @@ const createSheetGesture = (baseEl, backdropEl, wrapperEl, initialBreakpoint, ba
|
|
|
1259
1168
|
* snapping animation completes.
|
|
1260
1169
|
*/
|
|
1261
1170
|
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
1171
|
if (shouldPreventDismiss) {
|
|
1271
1172
|
handleCanDismiss(baseEl, animation);
|
|
1272
1173
|
}
|
|
@@ -1287,6 +1188,14 @@ const createSheetGesture = (baseEl, backdropEl, wrapperEl, initialBreakpoint, ba
|
|
|
1287
1188
|
animation
|
|
1288
1189
|
.onFinish(() => {
|
|
1289
1190
|
if (shouldRemainOpen) {
|
|
1191
|
+
/**
|
|
1192
|
+
* If expandToScroll is disabled, we need to swap
|
|
1193
|
+
* the footer position to stationary so that it
|
|
1194
|
+
* will act as it would by default
|
|
1195
|
+
*/
|
|
1196
|
+
if (!expandToScroll) {
|
|
1197
|
+
swapFooterPosition('stationary');
|
|
1198
|
+
}
|
|
1290
1199
|
/**
|
|
1291
1200
|
* Once the snapping animation completes,
|
|
1292
1201
|
* 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
|
}
|
|
@@ -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;
|
|
@@ -33,47 +33,7 @@ export const mdEnterAnimation = (baseEl, opts) => {
|
|
|
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
|
};
|
|
@@ -35,6 +35,9 @@ export const createSheetGesture = (baseEl, backdropEl, wrapperEl, initialBreakpo
|
|
|
35
35
|
let offset = 0;
|
|
36
36
|
let canDismissBlocksGesture = false;
|
|
37
37
|
let cachedScrollEl = null;
|
|
38
|
+
let cachedFooterEl = null;
|
|
39
|
+
let cachedFooterYPosition = null;
|
|
40
|
+
let currentFooterState = null;
|
|
38
41
|
const canDismissMaxStep = 0.95;
|
|
39
42
|
const maxBreakpoint = breakpoints[breakpoints.length - 1];
|
|
40
43
|
const minBreakpoint = breakpoints[0];
|
|
@@ -64,29 +67,45 @@ export const createSheetGesture = (baseEl, backdropEl, wrapperEl, initialBreakpo
|
|
|
64
67
|
baseEl.classList.add(FOCUS_TRAP_DISABLE_CLASS);
|
|
65
68
|
};
|
|
66
69
|
/**
|
|
67
|
-
* Toggles the
|
|
68
|
-
*
|
|
70
|
+
* Toggles the footer to an absolute position while moving to prevent
|
|
71
|
+
* it from shaking while the sheet is being dragged.
|
|
72
|
+
* @param footer Whether the footer is in a moving or stationary position.
|
|
69
73
|
*/
|
|
70
|
-
const
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
+
const swapFooterPosition = (newPosition) => {
|
|
75
|
+
if (!cachedFooterEl) {
|
|
76
|
+
cachedFooterEl = baseEl.querySelector('ion-footer');
|
|
77
|
+
if (!cachedFooterEl) {
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
74
80
|
}
|
|
75
|
-
const clonedFooter = wrapperEl.nextElementSibling;
|
|
76
|
-
const footerToHide = footer === 'original' ? clonedFooter : originalFooter;
|
|
77
|
-
const footerToShow = footer === 'original' ? originalFooter : clonedFooter;
|
|
78
|
-
footerToShow.style.removeProperty('display');
|
|
79
|
-
footerToShow.removeAttribute('aria-hidden');
|
|
80
81
|
const page = baseEl.querySelector('.ion-page');
|
|
81
|
-
|
|
82
|
-
|
|
82
|
+
currentFooterState = newPosition;
|
|
83
|
+
if (newPosition === 'stationary') {
|
|
84
|
+
// Reset positioning styles to allow normal document flow
|
|
85
|
+
cachedFooterEl.classList.remove('modal-footer-moving');
|
|
86
|
+
cachedFooterEl.style.removeProperty('position');
|
|
87
|
+
cachedFooterEl.style.removeProperty('bottom');
|
|
88
|
+
page === null || page === void 0 ? void 0 : page.style.removeProperty('padding-bottom');
|
|
89
|
+
// Move to page
|
|
90
|
+
page === null || page === void 0 ? void 0 : page.appendChild(cachedFooterEl);
|
|
83
91
|
}
|
|
84
92
|
else {
|
|
85
|
-
|
|
86
|
-
|
|
93
|
+
// Add padding to the parent element to prevent content from being hidden
|
|
94
|
+
// when the footer is positioned absolutely. This has to be done before we
|
|
95
|
+
// make the footer absolutely positioned or we may accidentally cause the
|
|
96
|
+
// sheet to scroll.
|
|
97
|
+
const footerHeight = cachedFooterEl.clientHeight;
|
|
98
|
+
page === null || page === void 0 ? void 0 : page.style.setProperty('padding-bottom', `${footerHeight}px`);
|
|
99
|
+
// Apply positioning styles to keep footer at bottom
|
|
100
|
+
cachedFooterEl.classList.add('modal-footer-moving');
|
|
101
|
+
cachedFooterEl.style.setProperty('position', 'absolute');
|
|
102
|
+
cachedFooterEl.style.setProperty('bottom', '0');
|
|
103
|
+
// Also cache the footer Y position, which we use to determine if the
|
|
104
|
+
// sheet has been moved below the footer. When that happens, we need to swap
|
|
105
|
+
// the position back so it will collapse correctly.
|
|
106
|
+
cachedFooterYPosition = cachedFooterEl.getBoundingClientRect().top + window.scrollY;
|
|
107
|
+
document.body.appendChild(cachedFooterEl);
|
|
87
108
|
}
|
|
88
|
-
footerToHide.style.setProperty('display', 'none');
|
|
89
|
-
footerToHide.setAttribute('aria-hidden', 'true');
|
|
90
109
|
};
|
|
91
110
|
/**
|
|
92
111
|
* After the entering animation completes,
|
|
@@ -180,12 +199,11 @@ export const createSheetGesture = (baseEl, backdropEl, wrapperEl, initialBreakpo
|
|
|
180
199
|
}
|
|
181
200
|
/**
|
|
182
201
|
* If expandToScroll is disabled, we need to swap
|
|
183
|
-
* the footer
|
|
184
|
-
*
|
|
185
|
-
* and doesn't stay on the screen after the modal is gone.
|
|
202
|
+
* the footer position to moving so that it doesn't shake
|
|
203
|
+
* while the sheet is being dragged.
|
|
186
204
|
*/
|
|
187
205
|
if (!expandToScroll) {
|
|
188
|
-
|
|
206
|
+
swapFooterPosition('moving');
|
|
189
207
|
}
|
|
190
208
|
/**
|
|
191
209
|
* If we are pulling down, then it is possible we are pulling on the content.
|
|
@@ -204,6 +222,21 @@ export const createSheetGesture = (baseEl, backdropEl, wrapperEl, initialBreakpo
|
|
|
204
222
|
animation.progressStart(true, 1 - currentBreakpoint);
|
|
205
223
|
};
|
|
206
224
|
const onMove = (detail) => {
|
|
225
|
+
/**
|
|
226
|
+
* If `expandToScroll` is disabled, we need to see if we're currently below
|
|
227
|
+
* the footer element and the footer is in a stationary position. If so,
|
|
228
|
+
* we need to make the stationary the original position so that the footer
|
|
229
|
+
* collapses with the sheet.
|
|
230
|
+
*/
|
|
231
|
+
if (!expandToScroll && cachedFooterYPosition !== null && currentFooterState !== null) {
|
|
232
|
+
// Check if we need to swap the footer position
|
|
233
|
+
if (detail.currentY >= cachedFooterYPosition && currentFooterState === 'moving') {
|
|
234
|
+
swapFooterPosition('stationary');
|
|
235
|
+
}
|
|
236
|
+
else if (detail.currentY < cachedFooterYPosition && currentFooterState === 'stationary') {
|
|
237
|
+
swapFooterPosition('moving');
|
|
238
|
+
}
|
|
239
|
+
}
|
|
207
240
|
/**
|
|
208
241
|
* If `expandToScroll` is disabled, and an upwards swipe gesture is done within
|
|
209
242
|
* the scrollable content, we should not allow the swipe gesture to continue.
|
|
@@ -337,14 +370,6 @@ export const createSheetGesture = (baseEl, backdropEl, wrapperEl, initialBreakpo
|
|
|
337
370
|
* snapping animation completes.
|
|
338
371
|
*/
|
|
339
372
|
gesture.enable(false);
|
|
340
|
-
/**
|
|
341
|
-
* If expandToScroll is disabled, we need to swap
|
|
342
|
-
* the footer visibility to the cloned one so the footer
|
|
343
|
-
* doesn't flicker when the sheet's height is animated.
|
|
344
|
-
*/
|
|
345
|
-
if (!expandToScroll && shouldRemainOpen) {
|
|
346
|
-
swapFooterVisibility('cloned');
|
|
347
|
-
}
|
|
348
373
|
if (shouldPreventDismiss) {
|
|
349
374
|
handleCanDismiss(baseEl, animation);
|
|
350
375
|
}
|
|
@@ -365,6 +390,14 @@ export const createSheetGesture = (baseEl, backdropEl, wrapperEl, initialBreakpo
|
|
|
365
390
|
animation
|
|
366
391
|
.onFinish(() => {
|
|
367
392
|
if (shouldRemainOpen) {
|
|
393
|
+
/**
|
|
394
|
+
* If expandToScroll is disabled, we need to swap
|
|
395
|
+
* the footer position to stationary so that it
|
|
396
|
+
* will act as it would by default
|
|
397
|
+
*/
|
|
398
|
+
if (!expandToScroll) {
|
|
399
|
+
swapFooterPosition('stationary');
|
|
400
|
+
}
|
|
368
401
|
/**
|
|
369
402
|
* Once the snapping animation completes,
|
|
370
403
|
* we need to reset the animation to go
|
package/dist/docs.json
CHANGED