@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/hydrate/index.js CHANGED
@@ -19214,47 +19214,7 @@ const iosEnterAnimation$3 = (baseEl, opts) => {
19214
19214
  .addElement(baseEl)
19215
19215
  .easing('cubic-bezier(0.32,0.72,0,1)')
19216
19216
  .duration(500)
19217
- .addAnimation([wrapperAnimation])
19218
- .beforeAddWrite(() => {
19219
- if (expandToScroll) {
19220
- // Scroll can only be done when the modal is fully expanded.
19221
- return;
19222
- }
19223
- /**
19224
- * There are some browsers that causes flickering when
19225
- * dragging the content when scroll is enabled at every
19226
- * breakpoint. This is due to the wrapper element being
19227
- * transformed off the screen and having a snap animation.
19228
- *
19229
- * A workaround is to clone the footer element and append
19230
- * it outside of the wrapper element. This way, the footer
19231
- * is still visible and the drag can be done without
19232
- * flickering. The original footer is hidden until the modal
19233
- * is dismissed. This maintains the animation of the footer
19234
- * when the modal is dismissed.
19235
- *
19236
- * The workaround needs to be done before the animation starts
19237
- * so there are no flickering issues.
19238
- */
19239
- const ionFooter = baseEl.querySelector('ion-footer');
19240
- /**
19241
- * This check is needed to prevent more than one footer
19242
- * from being appended to the shadow root.
19243
- * Otherwise, iOS and MD enter animations would append
19244
- * the footer twice.
19245
- */
19246
- const ionFooterAlreadyAppended = baseEl.shadowRoot.querySelector('ion-footer');
19247
- if (ionFooter && !ionFooterAlreadyAppended) {
19248
- const footerHeight = ionFooter.clientHeight;
19249
- const clonedFooter = ionFooter.cloneNode(true);
19250
- baseEl.shadowRoot.appendChild(clonedFooter);
19251
- ionFooter.style.setProperty('display', 'none');
19252
- ionFooter.setAttribute('aria-hidden', 'true');
19253
- // Padding is added to prevent some content from being hidden.
19254
- const page = baseEl.querySelector('.ion-page');
19255
- page.style.setProperty('padding-bottom', `${footerHeight}px`);
19256
- }
19257
- });
19217
+ .addAnimation([wrapperAnimation]);
19258
19218
  if (contentAnimation) {
19259
19219
  baseAnimation.addAnimation(contentAnimation);
19260
19220
  }
@@ -19335,7 +19295,7 @@ const createLeaveAnimation$1 = () => {
19335
19295
  * iOS Modal Leave Animation
19336
19296
  */
19337
19297
  const iosLeaveAnimation$3 = (baseEl, opts, duration = 500) => {
19338
- const { presentingEl, currentBreakpoint, expandToScroll } = opts;
19298
+ const { presentingEl, currentBreakpoint } = opts;
19339
19299
  const root = getElementRoot(baseEl);
19340
19300
  const { wrapperAnimation, backdropAnimation } = currentBreakpoint !== undefined ? createSheetLeaveAnimation(opts) : createLeaveAnimation$1();
19341
19301
  backdropAnimation.addElement(root.querySelector('ion-backdrop'));
@@ -19344,29 +19304,7 @@ const iosLeaveAnimation$3 = (baseEl, opts, duration = 500) => {
19344
19304
  .addElement(baseEl)
19345
19305
  .easing('cubic-bezier(0.32,0.72,0,1)')
19346
19306
  .duration(duration)
19347
- .addAnimation(wrapperAnimation)
19348
- .beforeAddWrite(() => {
19349
- if (expandToScroll) {
19350
- // Scroll can only be done when the modal is fully expanded.
19351
- return;
19352
- }
19353
- /**
19354
- * If expandToScroll is disabled, we need to swap
19355
- * the visibility to the original, so the footer
19356
- * dismisses with the modal and doesn't stay
19357
- * until the modal is removed from the DOM.
19358
- */
19359
- const ionFooter = baseEl.querySelector('ion-footer');
19360
- if (ionFooter) {
19361
- const clonedFooter = baseEl.shadowRoot.querySelector('ion-footer');
19362
- ionFooter.style.removeProperty('display');
19363
- ionFooter.removeAttribute('aria-hidden');
19364
- clonedFooter.style.setProperty('display', 'none');
19365
- clonedFooter.setAttribute('aria-hidden', 'true');
19366
- const page = baseEl.querySelector('.ion-page');
19367
- page.style.removeProperty('padding-bottom');
19368
- }
19369
- });
19307
+ .addAnimation(wrapperAnimation);
19370
19308
  if (presentingEl) {
19371
19309
  const isMobile = window.innerWidth < 768;
19372
19310
  const hasCardModal = presentingEl.tagName === 'ION-MODAL' && presentingEl.presentingElement !== undefined;
@@ -19462,47 +19400,7 @@ const mdEnterAnimation$2 = (baseEl, opts) => {
19462
19400
  .addElement(baseEl)
19463
19401
  .easing('cubic-bezier(0.36,0.66,0.04,1)')
19464
19402
  .duration(280)
19465
- .addAnimation([backdropAnimation, wrapperAnimation])
19466
- .beforeAddWrite(() => {
19467
- if (expandToScroll) {
19468
- // Scroll can only be done when the modal is fully expanded.
19469
- return;
19470
- }
19471
- /**
19472
- * There are some browsers that causes flickering when
19473
- * dragging the content when scroll is enabled at every
19474
- * breakpoint. This is due to the wrapper element being
19475
- * transformed off the screen and having a snap animation.
19476
- *
19477
- * A workaround is to clone the footer element and append
19478
- * it outside of the wrapper element. This way, the footer
19479
- * is still visible and the drag can be done without
19480
- * flickering. The original footer is hidden until the modal
19481
- * is dismissed. This maintains the animation of the footer
19482
- * when the modal is dismissed.
19483
- *
19484
- * The workaround needs to be done before the animation starts
19485
- * so there are no flickering issues.
19486
- */
19487
- const ionFooter = baseEl.querySelector('ion-footer');
19488
- /**
19489
- * This check is needed to prevent more than one footer
19490
- * from being appended to the shadow root.
19491
- * Otherwise, iOS and MD enter animations would append
19492
- * the footer twice.
19493
- */
19494
- const ionFooterAlreadyAppended = baseEl.shadowRoot.querySelector('ion-footer');
19495
- if (ionFooter && !ionFooterAlreadyAppended) {
19496
- const footerHeight = ionFooter.clientHeight;
19497
- const clonedFooter = ionFooter.cloneNode(true);
19498
- baseEl.shadowRoot.appendChild(clonedFooter);
19499
- ionFooter.style.setProperty('display', 'none');
19500
- ionFooter.setAttribute('aria-hidden', 'true');
19501
- // Padding is added to prevent some content from being hidden.
19502
- const page = baseEl.querySelector('.ion-page');
19503
- page.style.setProperty('padding-bottom', `${footerHeight}px`);
19504
- }
19505
- });
19403
+ .addAnimation([backdropAnimation, wrapperAnimation]);
19506
19404
  if (contentAnimation) {
19507
19405
  baseAnimation.addAnimation(contentAnimation);
19508
19406
  }
@@ -19521,7 +19419,7 @@ const createLeaveAnimation = () => {
19521
19419
  * Md Modal Leave Animation
19522
19420
  */
19523
19421
  const mdLeaveAnimation$2 = (baseEl, opts) => {
19524
- const { currentBreakpoint, expandToScroll } = opts;
19422
+ const { currentBreakpoint } = opts;
19525
19423
  const root = getElementRoot(baseEl);
19526
19424
  const { wrapperAnimation, backdropAnimation } = currentBreakpoint !== undefined ? createSheetLeaveAnimation(opts) : createLeaveAnimation();
19527
19425
  backdropAnimation.addElement(root.querySelector('ion-backdrop'));
@@ -19529,29 +19427,7 @@ const mdLeaveAnimation$2 = (baseEl, opts) => {
19529
19427
  const baseAnimation = createAnimation()
19530
19428
  .easing('cubic-bezier(0.47,0,0.745,0.715)')
19531
19429
  .duration(200)
19532
- .addAnimation([backdropAnimation, wrapperAnimation])
19533
- .beforeAddWrite(() => {
19534
- if (expandToScroll) {
19535
- // Scroll can only be done when the modal is fully expanded.
19536
- return;
19537
- }
19538
- /**
19539
- * If expandToScroll is disabled, we need to swap
19540
- * the visibility to the original, so the footer
19541
- * dismisses with the modal and doesn't stay
19542
- * until the modal is removed from the DOM.
19543
- */
19544
- const ionFooter = baseEl.querySelector('ion-footer');
19545
- if (ionFooter) {
19546
- const clonedFooter = baseEl.shadowRoot.querySelector('ion-footer');
19547
- ionFooter.style.removeProperty('display');
19548
- ionFooter.removeAttribute('aria-hidden');
19549
- clonedFooter.style.setProperty('display', 'none');
19550
- clonedFooter.setAttribute('aria-hidden', 'true');
19551
- const page = baseEl.querySelector('.ion-page');
19552
- page.style.removeProperty('padding-bottom');
19553
- }
19554
- });
19430
+ .addAnimation([backdropAnimation, wrapperAnimation]);
19555
19431
  return baseAnimation;
19556
19432
  };
19557
19433
 
@@ -19583,6 +19459,9 @@ const createSheetGesture = (baseEl, backdropEl, wrapperEl, initialBreakpoint, ba
19583
19459
  let offset = 0;
19584
19460
  let canDismissBlocksGesture = false;
19585
19461
  let cachedScrollEl = null;
19462
+ let cachedFooterEl = null;
19463
+ let cachedFooterYPosition = null;
19464
+ let currentFooterState = null;
19586
19465
  const canDismissMaxStep = 0.95;
19587
19466
  const maxBreakpoint = breakpoints[breakpoints.length - 1];
19588
19467
  const minBreakpoint = breakpoints[0];
@@ -19612,29 +19491,45 @@ const createSheetGesture = (baseEl, backdropEl, wrapperEl, initialBreakpoint, ba
19612
19491
  baseEl.classList.add(FOCUS_TRAP_DISABLE_CLASS);
19613
19492
  };
19614
19493
  /**
19615
- * Toggles the visible modal footer when `expandToScroll` is disabled.
19616
- * @param footer The footer to show.
19494
+ * Toggles the footer to an absolute position while moving to prevent
19495
+ * it from shaking while the sheet is being dragged.
19496
+ * @param footer Whether the footer is in a moving or stationary position.
19617
19497
  */
19618
- const swapFooterVisibility = (footer) => {
19619
- const originalFooter = baseEl.querySelector('ion-footer');
19620
- if (!originalFooter) {
19621
- return;
19498
+ const swapFooterPosition = (newPosition) => {
19499
+ if (!cachedFooterEl) {
19500
+ cachedFooterEl = baseEl.querySelector('ion-footer');
19501
+ if (!cachedFooterEl) {
19502
+ return;
19503
+ }
19622
19504
  }
19623
- const clonedFooter = wrapperEl.nextElementSibling;
19624
- const footerToHide = footer === 'original' ? clonedFooter : originalFooter;
19625
- const footerToShow = footer === 'original' ? originalFooter : clonedFooter;
19626
- footerToShow.style.removeProperty('display');
19627
- footerToShow.removeAttribute('aria-hidden');
19628
19505
  const page = baseEl.querySelector('.ion-page');
19629
- if (footer === 'original') {
19630
- page.style.removeProperty('padding-bottom');
19506
+ currentFooterState = newPosition;
19507
+ if (newPosition === 'stationary') {
19508
+ // Reset positioning styles to allow normal document flow
19509
+ cachedFooterEl.classList.remove('modal-footer-moving');
19510
+ cachedFooterEl.style.removeProperty('position');
19511
+ cachedFooterEl.style.removeProperty('bottom');
19512
+ page === null || page === void 0 ? void 0 : page.style.removeProperty('padding-bottom');
19513
+ // Move to page
19514
+ page === null || page === void 0 ? void 0 : page.appendChild(cachedFooterEl);
19631
19515
  }
19632
19516
  else {
19633
- const pagePadding = footerToShow.clientHeight;
19634
- page.style.setProperty('padding-bottom', `${pagePadding}px`);
19517
+ // Add padding to the parent element to prevent content from being hidden
19518
+ // when the footer is positioned absolutely. This has to be done before we
19519
+ // make the footer absolutely positioned or we may accidentally cause the
19520
+ // sheet to scroll.
19521
+ const footerHeight = cachedFooterEl.clientHeight;
19522
+ page === null || page === void 0 ? void 0 : page.style.setProperty('padding-bottom', `${footerHeight}px`);
19523
+ // Apply positioning styles to keep footer at bottom
19524
+ cachedFooterEl.classList.add('modal-footer-moving');
19525
+ cachedFooterEl.style.setProperty('position', 'absolute');
19526
+ cachedFooterEl.style.setProperty('bottom', '0');
19527
+ // Also cache the footer Y position, which we use to determine if the
19528
+ // sheet has been moved below the footer. When that happens, we need to swap
19529
+ // the position back so it will collapse correctly.
19530
+ cachedFooterYPosition = cachedFooterEl.getBoundingClientRect().top + window.scrollY;
19531
+ document.body.appendChild(cachedFooterEl);
19635
19532
  }
19636
- footerToHide.style.setProperty('display', 'none');
19637
- footerToHide.setAttribute('aria-hidden', 'true');
19638
19533
  };
19639
19534
  /**
19640
19535
  * After the entering animation completes,
@@ -19728,12 +19623,11 @@ const createSheetGesture = (baseEl, backdropEl, wrapperEl, initialBreakpoint, ba
19728
19623
  }
19729
19624
  /**
19730
19625
  * If expandToScroll is disabled, we need to swap
19731
- * the footer visibility to the original, so if the modal
19732
- * is dismissed, the footer dismisses with the modal
19733
- * and doesn't stay on the screen after the modal is gone.
19626
+ * the footer position to moving so that it doesn't shake
19627
+ * while the sheet is being dragged.
19734
19628
  */
19735
19629
  if (!expandToScroll) {
19736
- swapFooterVisibility('original');
19630
+ swapFooterPosition('moving');
19737
19631
  }
19738
19632
  /**
19739
19633
  * If we are pulling down, then it is possible we are pulling on the content.
@@ -19752,6 +19646,21 @@ const createSheetGesture = (baseEl, backdropEl, wrapperEl, initialBreakpoint, ba
19752
19646
  animation.progressStart(true, 1 - currentBreakpoint);
19753
19647
  };
19754
19648
  const onMove = (detail) => {
19649
+ /**
19650
+ * If `expandToScroll` is disabled, we need to see if we're currently below
19651
+ * the footer element and the footer is in a stationary position. If so,
19652
+ * we need to make the stationary the original position so that the footer
19653
+ * collapses with the sheet.
19654
+ */
19655
+ if (!expandToScroll && cachedFooterYPosition !== null && currentFooterState !== null) {
19656
+ // Check if we need to swap the footer position
19657
+ if (detail.currentY >= cachedFooterYPosition && currentFooterState === 'moving') {
19658
+ swapFooterPosition('stationary');
19659
+ }
19660
+ else if (detail.currentY < cachedFooterYPosition && currentFooterState === 'stationary') {
19661
+ swapFooterPosition('moving');
19662
+ }
19663
+ }
19755
19664
  /**
19756
19665
  * If `expandToScroll` is disabled, and an upwards swipe gesture is done within
19757
19666
  * the scrollable content, we should not allow the swipe gesture to continue.
@@ -19885,14 +19794,6 @@ const createSheetGesture = (baseEl, backdropEl, wrapperEl, initialBreakpoint, ba
19885
19794
  * snapping animation completes.
19886
19795
  */
19887
19796
  gesture.enable(false);
19888
- /**
19889
- * If expandToScroll is disabled, we need to swap
19890
- * the footer visibility to the cloned one so the footer
19891
- * doesn't flicker when the sheet's height is animated.
19892
- */
19893
- if (!expandToScroll && shouldRemainOpen) {
19894
- swapFooterVisibility('cloned');
19895
- }
19896
19797
  if (shouldPreventDismiss) {
19897
19798
  handleCanDismiss(baseEl, animation);
19898
19799
  }
@@ -19913,6 +19814,14 @@ const createSheetGesture = (baseEl, backdropEl, wrapperEl, initialBreakpoint, ba
19913
19814
  animation
19914
19815
  .onFinish(() => {
19915
19816
  if (shouldRemainOpen) {
19817
+ /**
19818
+ * If expandToScroll is disabled, we need to swap
19819
+ * the footer position to stationary so that it
19820
+ * will act as it would by default
19821
+ */
19822
+ if (!expandToScroll) {
19823
+ swapFooterPosition('stationary');
19824
+ }
19916
19825
  /**
19917
19826
  * Once the snapping animation completes,
19918
19827
  * we need to reset the animation to go
package/hydrate/index.mjs CHANGED
@@ -19210,47 +19210,7 @@ const iosEnterAnimation$3 = (baseEl, opts) => {
19210
19210
  .addElement(baseEl)
19211
19211
  .easing('cubic-bezier(0.32,0.72,0,1)')
19212
19212
  .duration(500)
19213
- .addAnimation([wrapperAnimation])
19214
- .beforeAddWrite(() => {
19215
- if (expandToScroll) {
19216
- // Scroll can only be done when the modal is fully expanded.
19217
- return;
19218
- }
19219
- /**
19220
- * There are some browsers that causes flickering when
19221
- * dragging the content when scroll is enabled at every
19222
- * breakpoint. This is due to the wrapper element being
19223
- * transformed off the screen and having a snap animation.
19224
- *
19225
- * A workaround is to clone the footer element and append
19226
- * it outside of the wrapper element. This way, the footer
19227
- * is still visible and the drag can be done without
19228
- * flickering. The original footer is hidden until the modal
19229
- * is dismissed. This maintains the animation of the footer
19230
- * when the modal is dismissed.
19231
- *
19232
- * The workaround needs to be done before the animation starts
19233
- * so there are no flickering issues.
19234
- */
19235
- const ionFooter = baseEl.querySelector('ion-footer');
19236
- /**
19237
- * This check is needed to prevent more than one footer
19238
- * from being appended to the shadow root.
19239
- * Otherwise, iOS and MD enter animations would append
19240
- * the footer twice.
19241
- */
19242
- const ionFooterAlreadyAppended = baseEl.shadowRoot.querySelector('ion-footer');
19243
- if (ionFooter && !ionFooterAlreadyAppended) {
19244
- const footerHeight = ionFooter.clientHeight;
19245
- const clonedFooter = ionFooter.cloneNode(true);
19246
- baseEl.shadowRoot.appendChild(clonedFooter);
19247
- ionFooter.style.setProperty('display', 'none');
19248
- ionFooter.setAttribute('aria-hidden', 'true');
19249
- // Padding is added to prevent some content from being hidden.
19250
- const page = baseEl.querySelector('.ion-page');
19251
- page.style.setProperty('padding-bottom', `${footerHeight}px`);
19252
- }
19253
- });
19213
+ .addAnimation([wrapperAnimation]);
19254
19214
  if (contentAnimation) {
19255
19215
  baseAnimation.addAnimation(contentAnimation);
19256
19216
  }
@@ -19331,7 +19291,7 @@ const createLeaveAnimation$1 = () => {
19331
19291
  * iOS Modal Leave Animation
19332
19292
  */
19333
19293
  const iosLeaveAnimation$3 = (baseEl, opts, duration = 500) => {
19334
- const { presentingEl, currentBreakpoint, expandToScroll } = opts;
19294
+ const { presentingEl, currentBreakpoint } = opts;
19335
19295
  const root = getElementRoot(baseEl);
19336
19296
  const { wrapperAnimation, backdropAnimation } = currentBreakpoint !== undefined ? createSheetLeaveAnimation(opts) : createLeaveAnimation$1();
19337
19297
  backdropAnimation.addElement(root.querySelector('ion-backdrop'));
@@ -19340,29 +19300,7 @@ const iosLeaveAnimation$3 = (baseEl, opts, duration = 500) => {
19340
19300
  .addElement(baseEl)
19341
19301
  .easing('cubic-bezier(0.32,0.72,0,1)')
19342
19302
  .duration(duration)
19343
- .addAnimation(wrapperAnimation)
19344
- .beforeAddWrite(() => {
19345
- if (expandToScroll) {
19346
- // Scroll can only be done when the modal is fully expanded.
19347
- return;
19348
- }
19349
- /**
19350
- * If expandToScroll is disabled, we need to swap
19351
- * the visibility to the original, so the footer
19352
- * dismisses with the modal and doesn't stay
19353
- * until the modal is removed from the DOM.
19354
- */
19355
- const ionFooter = baseEl.querySelector('ion-footer');
19356
- if (ionFooter) {
19357
- const clonedFooter = baseEl.shadowRoot.querySelector('ion-footer');
19358
- ionFooter.style.removeProperty('display');
19359
- ionFooter.removeAttribute('aria-hidden');
19360
- clonedFooter.style.setProperty('display', 'none');
19361
- clonedFooter.setAttribute('aria-hidden', 'true');
19362
- const page = baseEl.querySelector('.ion-page');
19363
- page.style.removeProperty('padding-bottom');
19364
- }
19365
- });
19303
+ .addAnimation(wrapperAnimation);
19366
19304
  if (presentingEl) {
19367
19305
  const isMobile = window.innerWidth < 768;
19368
19306
  const hasCardModal = presentingEl.tagName === 'ION-MODAL' && presentingEl.presentingElement !== undefined;
@@ -19458,47 +19396,7 @@ const mdEnterAnimation$2 = (baseEl, opts) => {
19458
19396
  .addElement(baseEl)
19459
19397
  .easing('cubic-bezier(0.36,0.66,0.04,1)')
19460
19398
  .duration(280)
19461
- .addAnimation([backdropAnimation, wrapperAnimation])
19462
- .beforeAddWrite(() => {
19463
- if (expandToScroll) {
19464
- // Scroll can only be done when the modal is fully expanded.
19465
- return;
19466
- }
19467
- /**
19468
- * There are some browsers that causes flickering when
19469
- * dragging the content when scroll is enabled at every
19470
- * breakpoint. This is due to the wrapper element being
19471
- * transformed off the screen and having a snap animation.
19472
- *
19473
- * A workaround is to clone the footer element and append
19474
- * it outside of the wrapper element. This way, the footer
19475
- * is still visible and the drag can be done without
19476
- * flickering. The original footer is hidden until the modal
19477
- * is dismissed. This maintains the animation of the footer
19478
- * when the modal is dismissed.
19479
- *
19480
- * The workaround needs to be done before the animation starts
19481
- * so there are no flickering issues.
19482
- */
19483
- const ionFooter = baseEl.querySelector('ion-footer');
19484
- /**
19485
- * This check is needed to prevent more than one footer
19486
- * from being appended to the shadow root.
19487
- * Otherwise, iOS and MD enter animations would append
19488
- * the footer twice.
19489
- */
19490
- const ionFooterAlreadyAppended = baseEl.shadowRoot.querySelector('ion-footer');
19491
- if (ionFooter && !ionFooterAlreadyAppended) {
19492
- const footerHeight = ionFooter.clientHeight;
19493
- const clonedFooter = ionFooter.cloneNode(true);
19494
- baseEl.shadowRoot.appendChild(clonedFooter);
19495
- ionFooter.style.setProperty('display', 'none');
19496
- ionFooter.setAttribute('aria-hidden', 'true');
19497
- // Padding is added to prevent some content from being hidden.
19498
- const page = baseEl.querySelector('.ion-page');
19499
- page.style.setProperty('padding-bottom', `${footerHeight}px`);
19500
- }
19501
- });
19399
+ .addAnimation([backdropAnimation, wrapperAnimation]);
19502
19400
  if (contentAnimation) {
19503
19401
  baseAnimation.addAnimation(contentAnimation);
19504
19402
  }
@@ -19517,7 +19415,7 @@ const createLeaveAnimation = () => {
19517
19415
  * Md Modal Leave Animation
19518
19416
  */
19519
19417
  const mdLeaveAnimation$2 = (baseEl, opts) => {
19520
- const { currentBreakpoint, expandToScroll } = opts;
19418
+ const { currentBreakpoint } = opts;
19521
19419
  const root = getElementRoot(baseEl);
19522
19420
  const { wrapperAnimation, backdropAnimation } = currentBreakpoint !== undefined ? createSheetLeaveAnimation(opts) : createLeaveAnimation();
19523
19421
  backdropAnimation.addElement(root.querySelector('ion-backdrop'));
@@ -19525,29 +19423,7 @@ const mdLeaveAnimation$2 = (baseEl, opts) => {
19525
19423
  const baseAnimation = createAnimation()
19526
19424
  .easing('cubic-bezier(0.47,0,0.745,0.715)')
19527
19425
  .duration(200)
19528
- .addAnimation([backdropAnimation, wrapperAnimation])
19529
- .beforeAddWrite(() => {
19530
- if (expandToScroll) {
19531
- // Scroll can only be done when the modal is fully expanded.
19532
- return;
19533
- }
19534
- /**
19535
- * If expandToScroll is disabled, we need to swap
19536
- * the visibility to the original, so the footer
19537
- * dismisses with the modal and doesn't stay
19538
- * until the modal is removed from the DOM.
19539
- */
19540
- const ionFooter = baseEl.querySelector('ion-footer');
19541
- if (ionFooter) {
19542
- const clonedFooter = baseEl.shadowRoot.querySelector('ion-footer');
19543
- ionFooter.style.removeProperty('display');
19544
- ionFooter.removeAttribute('aria-hidden');
19545
- clonedFooter.style.setProperty('display', 'none');
19546
- clonedFooter.setAttribute('aria-hidden', 'true');
19547
- const page = baseEl.querySelector('.ion-page');
19548
- page.style.removeProperty('padding-bottom');
19549
- }
19550
- });
19426
+ .addAnimation([backdropAnimation, wrapperAnimation]);
19551
19427
  return baseAnimation;
19552
19428
  };
19553
19429
 
@@ -19579,6 +19455,9 @@ const createSheetGesture = (baseEl, backdropEl, wrapperEl, initialBreakpoint, ba
19579
19455
  let offset = 0;
19580
19456
  let canDismissBlocksGesture = false;
19581
19457
  let cachedScrollEl = null;
19458
+ let cachedFooterEl = null;
19459
+ let cachedFooterYPosition = null;
19460
+ let currentFooterState = null;
19582
19461
  const canDismissMaxStep = 0.95;
19583
19462
  const maxBreakpoint = breakpoints[breakpoints.length - 1];
19584
19463
  const minBreakpoint = breakpoints[0];
@@ -19608,29 +19487,45 @@ const createSheetGesture = (baseEl, backdropEl, wrapperEl, initialBreakpoint, ba
19608
19487
  baseEl.classList.add(FOCUS_TRAP_DISABLE_CLASS);
19609
19488
  };
19610
19489
  /**
19611
- * Toggles the visible modal footer when `expandToScroll` is disabled.
19612
- * @param footer The footer to show.
19490
+ * Toggles the footer to an absolute position while moving to prevent
19491
+ * it from shaking while the sheet is being dragged.
19492
+ * @param footer Whether the footer is in a moving or stationary position.
19613
19493
  */
19614
- const swapFooterVisibility = (footer) => {
19615
- const originalFooter = baseEl.querySelector('ion-footer');
19616
- if (!originalFooter) {
19617
- return;
19494
+ const swapFooterPosition = (newPosition) => {
19495
+ if (!cachedFooterEl) {
19496
+ cachedFooterEl = baseEl.querySelector('ion-footer');
19497
+ if (!cachedFooterEl) {
19498
+ return;
19499
+ }
19618
19500
  }
19619
- const clonedFooter = wrapperEl.nextElementSibling;
19620
- const footerToHide = footer === 'original' ? clonedFooter : originalFooter;
19621
- const footerToShow = footer === 'original' ? originalFooter : clonedFooter;
19622
- footerToShow.style.removeProperty('display');
19623
- footerToShow.removeAttribute('aria-hidden');
19624
19501
  const page = baseEl.querySelector('.ion-page');
19625
- if (footer === 'original') {
19626
- page.style.removeProperty('padding-bottom');
19502
+ currentFooterState = newPosition;
19503
+ if (newPosition === 'stationary') {
19504
+ // Reset positioning styles to allow normal document flow
19505
+ cachedFooterEl.classList.remove('modal-footer-moving');
19506
+ cachedFooterEl.style.removeProperty('position');
19507
+ cachedFooterEl.style.removeProperty('bottom');
19508
+ page === null || page === void 0 ? void 0 : page.style.removeProperty('padding-bottom');
19509
+ // Move to page
19510
+ page === null || page === void 0 ? void 0 : page.appendChild(cachedFooterEl);
19627
19511
  }
19628
19512
  else {
19629
- const pagePadding = footerToShow.clientHeight;
19630
- page.style.setProperty('padding-bottom', `${pagePadding}px`);
19513
+ // Add padding to the parent element to prevent content from being hidden
19514
+ // when the footer is positioned absolutely. This has to be done before we
19515
+ // make the footer absolutely positioned or we may accidentally cause the
19516
+ // sheet to scroll.
19517
+ const footerHeight = cachedFooterEl.clientHeight;
19518
+ page === null || page === void 0 ? void 0 : page.style.setProperty('padding-bottom', `${footerHeight}px`);
19519
+ // Apply positioning styles to keep footer at bottom
19520
+ cachedFooterEl.classList.add('modal-footer-moving');
19521
+ cachedFooterEl.style.setProperty('position', 'absolute');
19522
+ cachedFooterEl.style.setProperty('bottom', '0');
19523
+ // Also cache the footer Y position, which we use to determine if the
19524
+ // sheet has been moved below the footer. When that happens, we need to swap
19525
+ // the position back so it will collapse correctly.
19526
+ cachedFooterYPosition = cachedFooterEl.getBoundingClientRect().top + window.scrollY;
19527
+ document.body.appendChild(cachedFooterEl);
19631
19528
  }
19632
- footerToHide.style.setProperty('display', 'none');
19633
- footerToHide.setAttribute('aria-hidden', 'true');
19634
19529
  };
19635
19530
  /**
19636
19531
  * After the entering animation completes,
@@ -19724,12 +19619,11 @@ const createSheetGesture = (baseEl, backdropEl, wrapperEl, initialBreakpoint, ba
19724
19619
  }
19725
19620
  /**
19726
19621
  * If expandToScroll is disabled, we need to swap
19727
- * the footer visibility to the original, so if the modal
19728
- * is dismissed, the footer dismisses with the modal
19729
- * and doesn't stay on the screen after the modal is gone.
19622
+ * the footer position to moving so that it doesn't shake
19623
+ * while the sheet is being dragged.
19730
19624
  */
19731
19625
  if (!expandToScroll) {
19732
- swapFooterVisibility('original');
19626
+ swapFooterPosition('moving');
19733
19627
  }
19734
19628
  /**
19735
19629
  * If we are pulling down, then it is possible we are pulling on the content.
@@ -19748,6 +19642,21 @@ const createSheetGesture = (baseEl, backdropEl, wrapperEl, initialBreakpoint, ba
19748
19642
  animation.progressStart(true, 1 - currentBreakpoint);
19749
19643
  };
19750
19644
  const onMove = (detail) => {
19645
+ /**
19646
+ * If `expandToScroll` is disabled, we need to see if we're currently below
19647
+ * the footer element and the footer is in a stationary position. If so,
19648
+ * we need to make the stationary the original position so that the footer
19649
+ * collapses with the sheet.
19650
+ */
19651
+ if (!expandToScroll && cachedFooterYPosition !== null && currentFooterState !== null) {
19652
+ // Check if we need to swap the footer position
19653
+ if (detail.currentY >= cachedFooterYPosition && currentFooterState === 'moving') {
19654
+ swapFooterPosition('stationary');
19655
+ }
19656
+ else if (detail.currentY < cachedFooterYPosition && currentFooterState === 'stationary') {
19657
+ swapFooterPosition('moving');
19658
+ }
19659
+ }
19751
19660
  /**
19752
19661
  * If `expandToScroll` is disabled, and an upwards swipe gesture is done within
19753
19662
  * the scrollable content, we should not allow the swipe gesture to continue.
@@ -19881,14 +19790,6 @@ const createSheetGesture = (baseEl, backdropEl, wrapperEl, initialBreakpoint, ba
19881
19790
  * snapping animation completes.
19882
19791
  */
19883
19792
  gesture.enable(false);
19884
- /**
19885
- * If expandToScroll is disabled, we need to swap
19886
- * the footer visibility to the cloned one so the footer
19887
- * doesn't flicker when the sheet's height is animated.
19888
- */
19889
- if (!expandToScroll && shouldRemainOpen) {
19890
- swapFooterVisibility('cloned');
19891
- }
19892
19793
  if (shouldPreventDismiss) {
19893
19794
  handleCanDismiss(baseEl, animation);
19894
19795
  }
@@ -19909,6 +19810,14 @@ const createSheetGesture = (baseEl, backdropEl, wrapperEl, initialBreakpoint, ba
19909
19810
  animation
19910
19811
  .onFinish(() => {
19911
19812
  if (shouldRemainOpen) {
19813
+ /**
19814
+ * If expandToScroll is disabled, we need to swap
19815
+ * the footer position to stationary so that it
19816
+ * will act as it would by default
19817
+ */
19818
+ if (!expandToScroll) {
19819
+ swapFooterPosition('stationary');
19820
+ }
19912
19821
  /**
19913
19822
  * Once the snapping animation completes,
19914
19823
  * we need to reset the animation to go
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ionic/core",
3
- "version": "8.5.7",
3
+ "version": "8.5.8-dev.11748374591.17686118",
4
4
  "description": "Base components for Ionic",
5
5
  "keywords": [
6
6
  "ionic",