@ionic/core 8.5.7 → 8.5.8-dev.11748364689.107665ad

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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;
@@ -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, 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
  };
@@ -35,6 +35,8 @@ export const createSheetGesture = (baseEl, backdropEl, wrapperEl, initialBreakpo
35
35
  let offset = 0;
36
36
  let canDismissBlocksGesture = false;
37
37
  let cachedScrollEl = null;
38
+ let cachedFooterYPosition = null;
39
+ let currentFooterState = null;
38
40
  const canDismissMaxStep = 0.95;
39
41
  const maxBreakpoint = breakpoints[breakpoints.length - 1];
40
42
  const minBreakpoint = breakpoints[0];
@@ -64,29 +66,38 @@ export const createSheetGesture = (baseEl, backdropEl, wrapperEl, initialBreakpo
64
66
  baseEl.classList.add(FOCUS_TRAP_DISABLE_CLASS);
65
67
  };
66
68
  /**
67
- * Toggles the visible modal footer when `expandToScroll` is disabled.
68
- * @param footer The footer to show.
69
+ * Toggles the footer to an absolute position while moving to prevent
70
+ * it from shaking while the sheet is being dragged.
71
+ * @param footer Whether the footer is in a moving or stationary position.
69
72
  */
70
- const swapFooterVisibility = (footer) => {
73
+ const swapFooterPosition = (newPosition) => {
74
+ var _a, _b;
71
75
  const originalFooter = baseEl.querySelector('ion-footer');
72
76
  if (!originalFooter) {
73
77
  return;
74
78
  }
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
- const page = baseEl.querySelector('.ion-page');
81
- if (footer === 'original') {
82
- page.style.removeProperty('padding-bottom');
79
+ currentFooterState = newPosition;
80
+ if (newPosition === 'stationary') {
81
+ // Reset positioning styles to allow normal document flow
82
+ originalFooter.style.removeProperty('position');
83
+ originalFooter.style.removeProperty('bottom');
84
+ (_a = originalFooter.parentElement) === null || _a === void 0 ? void 0 : _a.style.removeProperty('padding-bottom');
83
85
  }
84
86
  else {
85
- const pagePadding = footerToShow.clientHeight;
86
- page.style.setProperty('padding-bottom', `${pagePadding}px`);
87
+ // Add padding to the parent element to prevent content from being hidden
88
+ // when the footer is positioned absolutely. This has to be done before we
89
+ // make the footer absolutely positioned or we may accidentally cause the
90
+ // sheet to scroll.
91
+ const footerHeight = originalFooter.clientHeight;
92
+ (_b = originalFooter.parentElement) === null || _b === void 0 ? void 0 : _b.style.setProperty('padding-bottom', `${footerHeight}px`);
93
+ // Apply positioning styles to keep footer at bottom
94
+ originalFooter.style.setProperty('position', 'absolute');
95
+ originalFooter.style.setProperty('bottom', '0');
96
+ // Also cache the footer Y position, which we use to determine if the
97
+ // sheet has been moved below the footer. When that happens, we need to swap
98
+ // the position back so it will collapse correctly.
99
+ cachedFooterYPosition = originalFooter.getBoundingClientRect().top + window.scrollY;
87
100
  }
88
- footerToHide.style.setProperty('display', 'none');
89
- footerToHide.setAttribute('aria-hidden', 'true');
90
101
  };
91
102
  /**
92
103
  * After the entering animation completes,
@@ -180,12 +191,11 @@ export const createSheetGesture = (baseEl, backdropEl, wrapperEl, initialBreakpo
180
191
  }
181
192
  /**
182
193
  * If expandToScroll is disabled, we need to swap
183
- * the footer visibility to the original, so if the modal
184
- * is dismissed, the footer dismisses with the modal
185
- * and doesn't stay on the screen after the modal is gone.
194
+ * the footer position to moving so that it doesn't shake
195
+ * while the sheet is being dragged.
186
196
  */
187
197
  if (!expandToScroll) {
188
- swapFooterVisibility('original');
198
+ swapFooterPosition('moving');
189
199
  }
190
200
  /**
191
201
  * If we are pulling down, then it is possible we are pulling on the content.
@@ -204,6 +214,21 @@ export const createSheetGesture = (baseEl, backdropEl, wrapperEl, initialBreakpo
204
214
  animation.progressStart(true, 1 - currentBreakpoint);
205
215
  };
206
216
  const onMove = (detail) => {
217
+ /**
218
+ * If `expandToScroll` is disabled, we need to see if we're currently below
219
+ * the footer element and the footer is in a stationary position. If so,
220
+ * we need to make the stationary the original position so that the footer
221
+ * collapses with the sheet.
222
+ */
223
+ if (!expandToScroll && cachedFooterYPosition !== null && currentFooterState !== null) {
224
+ // Check if we need to swap the footer position
225
+ if (detail.currentY >= cachedFooterYPosition && currentFooterState === 'moving') {
226
+ swapFooterPosition('stationary');
227
+ }
228
+ else if (detail.currentY < cachedFooterYPosition && currentFooterState === 'stationary') {
229
+ swapFooterPosition('moving');
230
+ }
231
+ }
207
232
  /**
208
233
  * If `expandToScroll` is disabled, and an upwards swipe gesture is done within
209
234
  * the scrollable content, we should not allow the swipe gesture to continue.
@@ -337,14 +362,6 @@ export const createSheetGesture = (baseEl, backdropEl, wrapperEl, initialBreakpo
337
362
  * snapping animation completes.
338
363
  */
339
364
  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
365
  if (shouldPreventDismiss) {
349
366
  handleCanDismiss(baseEl, animation);
350
367
  }
@@ -365,6 +382,14 @@ export const createSheetGesture = (baseEl, backdropEl, wrapperEl, initialBreakpo
365
382
  animation
366
383
  .onFinish(() => {
367
384
  if (shouldRemainOpen) {
385
+ /**
386
+ * If expandToScroll is disabled, we need to swap
387
+ * the footer position to stationary so that it
388
+ * will act as it would by default
389
+ */
390
+ if (!expandToScroll) {
391
+ swapFooterPosition('stationary');
392
+ }
368
393
  /**
369
394
  * Once the snapping animation completes,
370
395
  * we need to reset the animation to go
package/dist/docs.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "timestamp": "2025-05-07T20:08:46",
2
+ "timestamp": "2025-05-27T16:53:19",
3
3
  "compiler": {
4
4
  "name": "@stencil/core",
5
5
  "version": "4.20.0",
@@ -584,47 +584,7 @@ const iosEnterAnimation = (baseEl, opts) => {
584
584
  .addElement(baseEl)
585
585
  .easing('cubic-bezier(0.32,0.72,0,1)')
586
586
  .duration(500)
587
- .addAnimation([wrapperAnimation])
588
- .beforeAddWrite(() => {
589
- if (expandToScroll) {
590
- // Scroll can only be done when the modal is fully expanded.
591
- return;
592
- }
593
- /**
594
- * There are some browsers that causes flickering when
595
- * dragging the content when scroll is enabled at every
596
- * breakpoint. This is due to the wrapper element being
597
- * transformed off the screen and having a snap animation.
598
- *
599
- * A workaround is to clone the footer element and append
600
- * it outside of the wrapper element. This way, the footer
601
- * is still visible and the drag can be done without
602
- * flickering. The original footer is hidden until the modal
603
- * is dismissed. This maintains the animation of the footer
604
- * when the modal is dismissed.
605
- *
606
- * The workaround needs to be done before the animation starts
607
- * so there are no flickering issues.
608
- */
609
- const ionFooter = baseEl.querySelector('ion-footer');
610
- /**
611
- * This check is needed to prevent more than one footer
612
- * from being appended to the shadow root.
613
- * Otherwise, iOS and MD enter animations would append
614
- * the footer twice.
615
- */
616
- const ionFooterAlreadyAppended = baseEl.shadowRoot.querySelector('ion-footer');
617
- if (ionFooter && !ionFooterAlreadyAppended) {
618
- const footerHeight = ionFooter.clientHeight;
619
- const clonedFooter = ionFooter.cloneNode(true);
620
- baseEl.shadowRoot.appendChild(clonedFooter);
621
- ionFooter.style.setProperty('display', 'none');
622
- ionFooter.setAttribute('aria-hidden', 'true');
623
- // Padding is added to prevent some content from being hidden.
624
- const page = baseEl.querySelector('.ion-page');
625
- page.style.setProperty('padding-bottom', `${footerHeight}px`);
626
- }
627
- });
587
+ .addAnimation([wrapperAnimation]);
628
588
  if (contentAnimation) {
629
589
  baseAnimation.addAnimation(contentAnimation);
630
590
  }
@@ -705,7 +665,7 @@ const createLeaveAnimation$1 = () => {
705
665
  * iOS Modal Leave Animation
706
666
  */
707
667
  const iosLeaveAnimation = (baseEl, opts, duration = 500) => {
708
- const { presentingEl, currentBreakpoint, expandToScroll } = opts;
668
+ const { presentingEl, currentBreakpoint } = opts;
709
669
  const root = getElementRoot(baseEl);
710
670
  const { wrapperAnimation, backdropAnimation } = currentBreakpoint !== undefined ? createSheetLeaveAnimation(opts) : createLeaveAnimation$1();
711
671
  backdropAnimation.addElement(root.querySelector('ion-backdrop'));
@@ -714,29 +674,7 @@ const iosLeaveAnimation = (baseEl, opts, duration = 500) => {
714
674
  .addElement(baseEl)
715
675
  .easing('cubic-bezier(0.32,0.72,0,1)')
716
676
  .duration(duration)
717
- .addAnimation(wrapperAnimation)
718
- .beforeAddWrite(() => {
719
- if (expandToScroll) {
720
- // Scroll can only be done when the modal is fully expanded.
721
- return;
722
- }
723
- /**
724
- * If expandToScroll is disabled, we need to swap
725
- * the visibility to the original, so the footer
726
- * dismisses with the modal and doesn't stay
727
- * until the modal is removed from the DOM.
728
- */
729
- const ionFooter = baseEl.querySelector('ion-footer');
730
- if (ionFooter) {
731
- const clonedFooter = baseEl.shadowRoot.querySelector('ion-footer');
732
- ionFooter.style.removeProperty('display');
733
- ionFooter.removeAttribute('aria-hidden');
734
- clonedFooter.style.setProperty('display', 'none');
735
- clonedFooter.setAttribute('aria-hidden', 'true');
736
- const page = baseEl.querySelector('.ion-page');
737
- page.style.removeProperty('padding-bottom');
738
- }
739
- });
677
+ .addAnimation(wrapperAnimation);
740
678
  if (presentingEl) {
741
679
  const isMobile = window.innerWidth < 768;
742
680
  const hasCardModal = presentingEl.tagName === 'ION-MODAL' && presentingEl.presentingElement !== undefined;
@@ -832,47 +770,7 @@ const mdEnterAnimation = (baseEl, opts) => {
832
770
  .addElement(baseEl)
833
771
  .easing('cubic-bezier(0.36,0.66,0.04,1)')
834
772
  .duration(280)
835
- .addAnimation([backdropAnimation, wrapperAnimation])
836
- .beforeAddWrite(() => {
837
- if (expandToScroll) {
838
- // Scroll can only be done when the modal is fully expanded.
839
- return;
840
- }
841
- /**
842
- * There are some browsers that causes flickering when
843
- * dragging the content when scroll is enabled at every
844
- * breakpoint. This is due to the wrapper element being
845
- * transformed off the screen and having a snap animation.
846
- *
847
- * A workaround is to clone the footer element and append
848
- * it outside of the wrapper element. This way, the footer
849
- * is still visible and the drag can be done without
850
- * flickering. The original footer is hidden until the modal
851
- * is dismissed. This maintains the animation of the footer
852
- * when the modal is dismissed.
853
- *
854
- * The workaround needs to be done before the animation starts
855
- * so there are no flickering issues.
856
- */
857
- const ionFooter = baseEl.querySelector('ion-footer');
858
- /**
859
- * This check is needed to prevent more than one footer
860
- * from being appended to the shadow root.
861
- * Otherwise, iOS and MD enter animations would append
862
- * the footer twice.
863
- */
864
- const ionFooterAlreadyAppended = baseEl.shadowRoot.querySelector('ion-footer');
865
- if (ionFooter && !ionFooterAlreadyAppended) {
866
- const footerHeight = ionFooter.clientHeight;
867
- const clonedFooter = ionFooter.cloneNode(true);
868
- baseEl.shadowRoot.appendChild(clonedFooter);
869
- ionFooter.style.setProperty('display', 'none');
870
- ionFooter.setAttribute('aria-hidden', 'true');
871
- // Padding is added to prevent some content from being hidden.
872
- const page = baseEl.querySelector('.ion-page');
873
- page.style.setProperty('padding-bottom', `${footerHeight}px`);
874
- }
875
- });
773
+ .addAnimation([backdropAnimation, wrapperAnimation]);
876
774
  if (contentAnimation) {
877
775
  baseAnimation.addAnimation(contentAnimation);
878
776
  }
@@ -891,7 +789,7 @@ const createLeaveAnimation = () => {
891
789
  * Md Modal Leave Animation
892
790
  */
893
791
  const mdLeaveAnimation = (baseEl, opts) => {
894
- const { currentBreakpoint, expandToScroll } = opts;
792
+ const { currentBreakpoint } = opts;
895
793
  const root = getElementRoot(baseEl);
896
794
  const { wrapperAnimation, backdropAnimation } = currentBreakpoint !== undefined ? createSheetLeaveAnimation(opts) : createLeaveAnimation();
897
795
  backdropAnimation.addElement(root.querySelector('ion-backdrop'));
@@ -899,29 +797,7 @@ const mdLeaveAnimation = (baseEl, opts) => {
899
797
  const baseAnimation = createAnimation()
900
798
  .easing('cubic-bezier(0.47,0,0.745,0.715)')
901
799
  .duration(200)
902
- .addAnimation([backdropAnimation, wrapperAnimation])
903
- .beforeAddWrite(() => {
904
- if (expandToScroll) {
905
- // Scroll can only be done when the modal is fully expanded.
906
- return;
907
- }
908
- /**
909
- * If expandToScroll is disabled, we need to swap
910
- * the visibility to the original, so the footer
911
- * dismisses with the modal and doesn't stay
912
- * until the modal is removed from the DOM.
913
- */
914
- const ionFooter = baseEl.querySelector('ion-footer');
915
- if (ionFooter) {
916
- const clonedFooter = baseEl.shadowRoot.querySelector('ion-footer');
917
- ionFooter.style.removeProperty('display');
918
- ionFooter.removeAttribute('aria-hidden');
919
- clonedFooter.style.setProperty('display', 'none');
920
- clonedFooter.setAttribute('aria-hidden', 'true');
921
- const page = baseEl.querySelector('.ion-page');
922
- page.style.removeProperty('padding-bottom');
923
- }
924
- });
800
+ .addAnimation([backdropAnimation, wrapperAnimation]);
925
801
  return baseAnimation;
926
802
  };
927
803
 
@@ -953,6 +829,8 @@ const createSheetGesture = (baseEl, backdropEl, wrapperEl, initialBreakpoint, ba
953
829
  let offset = 0;
954
830
  let canDismissBlocksGesture = false;
955
831
  let cachedScrollEl = null;
832
+ let cachedFooterYPosition = null;
833
+ let currentFooterState = null;
956
834
  const canDismissMaxStep = 0.95;
957
835
  const maxBreakpoint = breakpoints[breakpoints.length - 1];
958
836
  const minBreakpoint = breakpoints[0];
@@ -982,29 +860,38 @@ const createSheetGesture = (baseEl, backdropEl, wrapperEl, initialBreakpoint, ba
982
860
  baseEl.classList.add(FOCUS_TRAP_DISABLE_CLASS);
983
861
  };
984
862
  /**
985
- * Toggles the visible modal footer when `expandToScroll` is disabled.
986
- * @param footer The footer to show.
863
+ * Toggles the footer to an absolute position while moving to prevent
864
+ * it from shaking while the sheet is being dragged.
865
+ * @param footer Whether the footer is in a moving or stationary position.
987
866
  */
988
- const swapFooterVisibility = (footer) => {
867
+ const swapFooterPosition = (newPosition) => {
868
+ var _a, _b;
989
869
  const originalFooter = baseEl.querySelector('ion-footer');
990
870
  if (!originalFooter) {
991
871
  return;
992
872
  }
993
- const clonedFooter = wrapperEl.nextElementSibling;
994
- const footerToHide = footer === 'original' ? clonedFooter : originalFooter;
995
- const footerToShow = footer === 'original' ? originalFooter : clonedFooter;
996
- footerToShow.style.removeProperty('display');
997
- footerToShow.removeAttribute('aria-hidden');
998
- const page = baseEl.querySelector('.ion-page');
999
- if (footer === 'original') {
1000
- page.style.removeProperty('padding-bottom');
873
+ currentFooterState = newPosition;
874
+ if (newPosition === 'stationary') {
875
+ // Reset positioning styles to allow normal document flow
876
+ originalFooter.style.removeProperty('position');
877
+ originalFooter.style.removeProperty('bottom');
878
+ (_a = originalFooter.parentElement) === null || _a === void 0 ? void 0 : _a.style.removeProperty('padding-bottom');
1001
879
  }
1002
880
  else {
1003
- const pagePadding = footerToShow.clientHeight;
1004
- page.style.setProperty('padding-bottom', `${pagePadding}px`);
881
+ // Add padding to the parent element to prevent content from being hidden
882
+ // when the footer is positioned absolutely. This has to be done before we
883
+ // make the footer absolutely positioned or we may accidentally cause the
884
+ // sheet to scroll.
885
+ const footerHeight = originalFooter.clientHeight;
886
+ (_b = originalFooter.parentElement) === null || _b === void 0 ? void 0 : _b.style.setProperty('padding-bottom', `${footerHeight}px`);
887
+ // Apply positioning styles to keep footer at bottom
888
+ originalFooter.style.setProperty('position', 'absolute');
889
+ originalFooter.style.setProperty('bottom', '0');
890
+ // Also cache the footer Y position, which we use to determine if the
891
+ // sheet has been moved below the footer. When that happens, we need to swap
892
+ // the position back so it will collapse correctly.
893
+ cachedFooterYPosition = originalFooter.getBoundingClientRect().top + window.scrollY;
1005
894
  }
1006
- footerToHide.style.setProperty('display', 'none');
1007
- footerToHide.setAttribute('aria-hidden', 'true');
1008
895
  };
1009
896
  /**
1010
897
  * After the entering animation completes,
@@ -1098,12 +985,11 @@ const createSheetGesture = (baseEl, backdropEl, wrapperEl, initialBreakpoint, ba
1098
985
  }
1099
986
  /**
1100
987
  * If expandToScroll is disabled, we need to swap
1101
- * the footer visibility to the original, so if the modal
1102
- * is dismissed, the footer dismisses with the modal
1103
- * and doesn't stay on the screen after the modal is gone.
988
+ * the footer position to moving so that it doesn't shake
989
+ * while the sheet is being dragged.
1104
990
  */
1105
991
  if (!expandToScroll) {
1106
- swapFooterVisibility('original');
992
+ swapFooterPosition('moving');
1107
993
  }
1108
994
  /**
1109
995
  * If we are pulling down, then it is possible we are pulling on the content.
@@ -1122,6 +1008,21 @@ const createSheetGesture = (baseEl, backdropEl, wrapperEl, initialBreakpoint, ba
1122
1008
  animation.progressStart(true, 1 - currentBreakpoint);
1123
1009
  };
1124
1010
  const onMove = (detail) => {
1011
+ /**
1012
+ * If `expandToScroll` is disabled, we need to see if we're currently below
1013
+ * the footer element and the footer is in a stationary position. If so,
1014
+ * we need to make the stationary the original position so that the footer
1015
+ * collapses with the sheet.
1016
+ */
1017
+ if (!expandToScroll && cachedFooterYPosition !== null && currentFooterState !== null) {
1018
+ // Check if we need to swap the footer position
1019
+ if (detail.currentY >= cachedFooterYPosition && currentFooterState === 'moving') {
1020
+ swapFooterPosition('stationary');
1021
+ }
1022
+ else if (detail.currentY < cachedFooterYPosition && currentFooterState === 'stationary') {
1023
+ swapFooterPosition('moving');
1024
+ }
1025
+ }
1125
1026
  /**
1126
1027
  * If `expandToScroll` is disabled, and an upwards swipe gesture is done within
1127
1028
  * the scrollable content, we should not allow the swipe gesture to continue.
@@ -1255,14 +1156,6 @@ const createSheetGesture = (baseEl, backdropEl, wrapperEl, initialBreakpoint, ba
1255
1156
  * snapping animation completes.
1256
1157
  */
1257
1158
  gesture.enable(false);
1258
- /**
1259
- * If expandToScroll is disabled, we need to swap
1260
- * the footer visibility to the cloned one so the footer
1261
- * doesn't flicker when the sheet's height is animated.
1262
- */
1263
- if (!expandToScroll && shouldRemainOpen) {
1264
- swapFooterVisibility('cloned');
1265
- }
1266
1159
  if (shouldPreventDismiss) {
1267
1160
  handleCanDismiss(baseEl, animation);
1268
1161
  }
@@ -1283,6 +1176,14 @@ const createSheetGesture = (baseEl, backdropEl, wrapperEl, initialBreakpoint, ba
1283
1176
  animation
1284
1177
  .onFinish(() => {
1285
1178
  if (shouldRemainOpen) {
1179
+ /**
1180
+ * If expandToScroll is disabled, we need to swap
1181
+ * the footer position to stationary so that it
1182
+ * will act as it would by default
1183
+ */
1184
+ if (!expandToScroll) {
1185
+ swapFooterPosition('stationary');
1186
+ }
1286
1187
  /**
1287
1188
  * Once the snapping animation completes,
1288
1189
  * we need to reset the animation to go