@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.
@@ -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, expandToScroll } = opts;
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, expandToScroll } = opts;
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 visible modal footer when `expandToScroll` is disabled.
990
- * @param footer The footer to show.
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 swapFooterVisibility = (footer) => {
993
- const originalFooter = baseEl.querySelector('ion-footer');
994
- if (!originalFooter) {
995
- return;
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
- if (footer === 'original') {
1004
- page.style.removeProperty('padding-bottom');
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
- const pagePadding = footerToShow.clientHeight;
1008
- page.style.setProperty('padding-bottom', `${pagePadding}px`);
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 visibility to the original, so if the modal
1106
- * is dismissed, the footer dismisses with the modal
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
- swapFooterVisibility('original');
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}:host(.modal-sheet.modal-no-expand-scroll) ion-footer ion-toolbar:first-of-type{padding-top:6px}";
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, expandToScroll } = opts;
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, expandToScroll } = opts;
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
  };