@ionic/core 8.6.1-nightly.20250610 → 8.6.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/components/ion-item-sliding.js +3 -2
- package/components/modal.js +76 -47
- package/dist/cjs/ion-item-option_3.cjs.entry.js +3 -2
- package/dist/cjs/ion-modal.cjs.entry.js +76 -47
- package/dist/collection/components/item-sliding/item-sliding.js +3 -2
- package/dist/collection/components/modal/gestures/sheet.js +76 -47
- package/dist/docs.json +1 -1
- package/dist/esm/ion-item-option_3.entry.js +3 -2
- package/dist/esm/ion-modal.entry.js +76 -47
- package/dist/ionic/ionic.esm.js +1 -1
- package/dist/ionic/p-29759454.entry.js +4 -0
- package/dist/ionic/{p-66510682.entry.js → p-a92bfa13.entry.js} +1 -1
- package/hydrate/index.js +79 -49
- package/hydrate/index.mjs +79 -49
- package/package.json +1 -1
- package/dist/ionic/p-90f87086.entry.js +0 -4
|
@@ -185,6 +185,7 @@ const ItemSliding = /*@__PURE__*/ proxyCustomElement(class ItemSliding extends H
|
|
|
185
185
|
}
|
|
186
186
|
}
|
|
187
187
|
async updateOptions() {
|
|
188
|
+
var _a;
|
|
188
189
|
const options = this.el.querySelectorAll('ion-item-options');
|
|
189
190
|
let sides = 0;
|
|
190
191
|
// Reset left and right options in case they were removed
|
|
@@ -198,7 +199,7 @@ const ItemSliding = /*@__PURE__*/ proxyCustomElement(class ItemSliding extends H
|
|
|
198
199
|
*/
|
|
199
200
|
// eslint-disable-next-line custom-rules/no-component-on-ready-method
|
|
200
201
|
const option = item.componentOnReady !== undefined ? await item.componentOnReady() : item;
|
|
201
|
-
const side = isEndSide(option.side) ? 'end' : 'start';
|
|
202
|
+
const side = isEndSide((_a = option.side) !== null && _a !== void 0 ? _a : option.getAttribute('side')) ? 'end' : 'start';
|
|
202
203
|
if (side === 'start') {
|
|
203
204
|
this.leftOptions = option;
|
|
204
205
|
sides |= 1 /* ItemSide.Start */;
|
|
@@ -396,7 +397,7 @@ const ItemSliding = /*@__PURE__*/ proxyCustomElement(class ItemSliding extends H
|
|
|
396
397
|
}
|
|
397
398
|
render() {
|
|
398
399
|
const mode = getIonMode(this);
|
|
399
|
-
return (h(Host, { key: '
|
|
400
|
+
return (h(Host, { key: 'd812322c9fb5da4ee16e99dc38bfb24cb4590d03', class: {
|
|
400
401
|
[mode]: true,
|
|
401
402
|
'item-sliding-active-slide': this.state !== 2 /* SlidingState.Disabled */,
|
|
402
403
|
'item-sliding-active-options-end': (this.state & 8 /* SlidingState.End */) !== 0,
|
package/components/modal.js
CHANGED
|
@@ -827,7 +827,7 @@ const createSheetGesture = (baseEl, backdropEl, wrapperEl, initialBreakpoint, ba
|
|
|
827
827
|
let offset = 0;
|
|
828
828
|
let canDismissBlocksGesture = false;
|
|
829
829
|
let cachedScrollEl = null;
|
|
830
|
-
let
|
|
830
|
+
let cachedFooterEls = null;
|
|
831
831
|
let cachedFooterYPosition = null;
|
|
832
832
|
let currentFooterState = null;
|
|
833
833
|
const canDismissMaxStep = 0.95;
|
|
@@ -864,60 +864,81 @@ const createSheetGesture = (baseEl, backdropEl, wrapperEl, initialBreakpoint, ba
|
|
|
864
864
|
* @param newPosition Whether the footer is in a moving or stationary position.
|
|
865
865
|
*/
|
|
866
866
|
const swapFooterPosition = (newPosition) => {
|
|
867
|
-
if (!
|
|
868
|
-
|
|
869
|
-
if (!
|
|
867
|
+
if (!cachedFooterEls) {
|
|
868
|
+
cachedFooterEls = Array.from(baseEl.querySelectorAll('ion-footer'));
|
|
869
|
+
if (!cachedFooterEls.length) {
|
|
870
870
|
return;
|
|
871
871
|
}
|
|
872
872
|
}
|
|
873
873
|
const page = baseEl.querySelector('.ion-page');
|
|
874
874
|
currentFooterState = newPosition;
|
|
875
875
|
if (newPosition === 'stationary') {
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
876
|
+
cachedFooterEls.forEach((cachedFooterEl) => {
|
|
877
|
+
// Reset positioning styles to allow normal document flow
|
|
878
|
+
cachedFooterEl.classList.remove('modal-footer-moving');
|
|
879
|
+
cachedFooterEl.style.removeProperty('position');
|
|
880
|
+
cachedFooterEl.style.removeProperty('width');
|
|
881
|
+
cachedFooterEl.style.removeProperty('height');
|
|
882
|
+
cachedFooterEl.style.removeProperty('top');
|
|
883
|
+
cachedFooterEl.style.removeProperty('left');
|
|
884
|
+
page === null || page === void 0 ? void 0 : page.style.removeProperty('padding-bottom');
|
|
885
|
+
// Move to page
|
|
886
|
+
page === null || page === void 0 ? void 0 : page.appendChild(cachedFooterEl);
|
|
887
|
+
});
|
|
886
888
|
}
|
|
887
889
|
else {
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
}
|
|
920
|
-
|
|
890
|
+
let footerHeights = 0;
|
|
891
|
+
cachedFooterEls.forEach((cachedFooterEl, index) => {
|
|
892
|
+
// Get both the footer and document body positions
|
|
893
|
+
const cachedFooterElRect = cachedFooterEl.getBoundingClientRect();
|
|
894
|
+
const bodyRect = document.body.getBoundingClientRect();
|
|
895
|
+
// Calculate the total height of all footers
|
|
896
|
+
// so we can add padding to the page element
|
|
897
|
+
footerHeights += cachedFooterEl.clientHeight;
|
|
898
|
+
// Calculate absolute position relative to body
|
|
899
|
+
// We need to subtract the body's offsetTop to get true position within document.body
|
|
900
|
+
const absoluteTop = cachedFooterElRect.top - bodyRect.top;
|
|
901
|
+
const absoluteLeft = cachedFooterElRect.left - bodyRect.left;
|
|
902
|
+
// Capture the footer's current dimensions and store them in CSS variables for
|
|
903
|
+
// later use when applying absolute positioning.
|
|
904
|
+
cachedFooterEl.style.setProperty('--pinned-width', `${cachedFooterEl.clientWidth}px`);
|
|
905
|
+
cachedFooterEl.style.setProperty('--pinned-height', `${cachedFooterEl.clientHeight}px`);
|
|
906
|
+
cachedFooterEl.style.setProperty('--pinned-top', `${absoluteTop}px`);
|
|
907
|
+
cachedFooterEl.style.setProperty('--pinned-left', `${absoluteLeft}px`);
|
|
908
|
+
// Only cache the first footer's Y position
|
|
909
|
+
// This is used to determine if the sheet has been moved below the footer
|
|
910
|
+
// and needs to be swapped back to stationary so it collapses correctly.
|
|
911
|
+
if (index === 0) {
|
|
912
|
+
cachedFooterYPosition = absoluteTop;
|
|
913
|
+
// If there's a header, we need to combine the header height with the footer position
|
|
914
|
+
// because the header moves with the drag handle, so when it starts overlapping the footer,
|
|
915
|
+
// we need to account for that.
|
|
916
|
+
const header = baseEl.querySelector('ion-header');
|
|
917
|
+
if (header) {
|
|
918
|
+
cachedFooterYPosition -= header.clientHeight;
|
|
919
|
+
}
|
|
920
|
+
}
|
|
921
|
+
});
|
|
922
|
+
// Apply the pinning of styles after we've calculated everything
|
|
923
|
+
// so that we don't cause layouts to shift while calculating the footer positions.
|
|
924
|
+
// Otherwise, with multiple footers we'll end up capturing the wrong positions.
|
|
925
|
+
cachedFooterEls.forEach((cachedFooterEl) => {
|
|
926
|
+
// Add padding to the parent element to prevent content from being hidden
|
|
927
|
+
// when the footer is positioned absolutely. This has to be done before we
|
|
928
|
+
// make the footer absolutely positioned or we may accidentally cause the
|
|
929
|
+
// sheet to scroll.
|
|
930
|
+
page === null || page === void 0 ? void 0 : page.style.setProperty('padding-bottom', `${footerHeights}px`);
|
|
931
|
+
// Apply positioning styles to keep footer at bottom
|
|
932
|
+
cachedFooterEl.classList.add('modal-footer-moving');
|
|
933
|
+
// Apply our preserved styles to pin the footer
|
|
934
|
+
cachedFooterEl.style.setProperty('position', 'absolute');
|
|
935
|
+
cachedFooterEl.style.setProperty('width', 'var(--pinned-width)');
|
|
936
|
+
cachedFooterEl.style.setProperty('height', 'var(--pinned-height)');
|
|
937
|
+
cachedFooterEl.style.setProperty('top', 'var(--pinned-top)');
|
|
938
|
+
cachedFooterEl.style.setProperty('left', 'var(--pinned-left)');
|
|
939
|
+
// Move the element to the body when everything else is done
|
|
940
|
+
document.body.appendChild(cachedFooterEl);
|
|
941
|
+
});
|
|
921
942
|
}
|
|
922
943
|
};
|
|
923
944
|
/**
|
|
@@ -1109,6 +1130,14 @@ const createSheetGesture = (baseEl, backdropEl, wrapperEl, initialBreakpoint, ba
|
|
|
1109
1130
|
* is not scrolled to the top.
|
|
1110
1131
|
*/
|
|
1111
1132
|
if (!expandToScroll && detail.deltaY <= 0 && cachedScrollEl && cachedScrollEl.scrollTop > 0) {
|
|
1133
|
+
/**
|
|
1134
|
+
* If expand to scroll is disabled, we need to make sure we swap the footer position
|
|
1135
|
+
* back to stationary so that it will collapse correctly if the modal is dismissed without
|
|
1136
|
+
* dragging (e.g. through a dismiss button).
|
|
1137
|
+
* This can cause issues if the user has a modal with content that can be dragged, as we'll
|
|
1138
|
+
* swap to moving on drag and if we don't swap back here then the footer will get stuck.
|
|
1139
|
+
*/
|
|
1140
|
+
swapFooterPosition('stationary');
|
|
1112
1141
|
return;
|
|
1113
1142
|
}
|
|
1114
1143
|
/**
|
|
@@ -282,6 +282,7 @@ const ItemSliding = class {
|
|
|
282
282
|
}
|
|
283
283
|
}
|
|
284
284
|
async updateOptions() {
|
|
285
|
+
var _a;
|
|
285
286
|
const options = this.el.querySelectorAll('ion-item-options');
|
|
286
287
|
let sides = 0;
|
|
287
288
|
// Reset left and right options in case they were removed
|
|
@@ -295,7 +296,7 @@ const ItemSliding = class {
|
|
|
295
296
|
*/
|
|
296
297
|
// eslint-disable-next-line custom-rules/no-component-on-ready-method
|
|
297
298
|
const option = item.componentOnReady !== undefined ? await item.componentOnReady() : item;
|
|
298
|
-
const side = helpers.isEndSide(option.side) ? 'end' : 'start';
|
|
299
|
+
const side = helpers.isEndSide((_a = option.side) !== null && _a !== void 0 ? _a : option.getAttribute('side')) ? 'end' : 'start';
|
|
299
300
|
if (side === 'start') {
|
|
300
301
|
this.leftOptions = option;
|
|
301
302
|
sides |= 1 /* ItemSide.Start */;
|
|
@@ -493,7 +494,7 @@ const ItemSliding = class {
|
|
|
493
494
|
}
|
|
494
495
|
render() {
|
|
495
496
|
const mode = index.getIonMode(this);
|
|
496
|
-
return (index.h(index.Host, { key: '
|
|
497
|
+
return (index.h(index.Host, { key: 'd812322c9fb5da4ee16e99dc38bfb24cb4590d03', class: {
|
|
497
498
|
[mode]: true,
|
|
498
499
|
'item-sliding-active-slide': this.state !== 2 /* SlidingState.Disabled */,
|
|
499
500
|
'item-sliding-active-options-end': (this.state & 8 /* SlidingState.End */) !== 0,
|
|
@@ -829,7 +829,7 @@ const createSheetGesture = (baseEl, backdropEl, wrapperEl, initialBreakpoint, ba
|
|
|
829
829
|
let offset = 0;
|
|
830
830
|
let canDismissBlocksGesture = false;
|
|
831
831
|
let cachedScrollEl = null;
|
|
832
|
-
let
|
|
832
|
+
let cachedFooterEls = null;
|
|
833
833
|
let cachedFooterYPosition = null;
|
|
834
834
|
let currentFooterState = null;
|
|
835
835
|
const canDismissMaxStep = 0.95;
|
|
@@ -866,60 +866,81 @@ const createSheetGesture = (baseEl, backdropEl, wrapperEl, initialBreakpoint, ba
|
|
|
866
866
|
* @param newPosition Whether the footer is in a moving or stationary position.
|
|
867
867
|
*/
|
|
868
868
|
const swapFooterPosition = (newPosition) => {
|
|
869
|
-
if (!
|
|
870
|
-
|
|
871
|
-
if (!
|
|
869
|
+
if (!cachedFooterEls) {
|
|
870
|
+
cachedFooterEls = Array.from(baseEl.querySelectorAll('ion-footer'));
|
|
871
|
+
if (!cachedFooterEls.length) {
|
|
872
872
|
return;
|
|
873
873
|
}
|
|
874
874
|
}
|
|
875
875
|
const page = baseEl.querySelector('.ion-page');
|
|
876
876
|
currentFooterState = newPosition;
|
|
877
877
|
if (newPosition === 'stationary') {
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
878
|
+
cachedFooterEls.forEach((cachedFooterEl) => {
|
|
879
|
+
// Reset positioning styles to allow normal document flow
|
|
880
|
+
cachedFooterEl.classList.remove('modal-footer-moving');
|
|
881
|
+
cachedFooterEl.style.removeProperty('position');
|
|
882
|
+
cachedFooterEl.style.removeProperty('width');
|
|
883
|
+
cachedFooterEl.style.removeProperty('height');
|
|
884
|
+
cachedFooterEl.style.removeProperty('top');
|
|
885
|
+
cachedFooterEl.style.removeProperty('left');
|
|
886
|
+
page === null || page === void 0 ? void 0 : page.style.removeProperty('padding-bottom');
|
|
887
|
+
// Move to page
|
|
888
|
+
page === null || page === void 0 ? void 0 : page.appendChild(cachedFooterEl);
|
|
889
|
+
});
|
|
888
890
|
}
|
|
889
891
|
else {
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
}
|
|
922
|
-
|
|
892
|
+
let footerHeights = 0;
|
|
893
|
+
cachedFooterEls.forEach((cachedFooterEl, index) => {
|
|
894
|
+
// Get both the footer and document body positions
|
|
895
|
+
const cachedFooterElRect = cachedFooterEl.getBoundingClientRect();
|
|
896
|
+
const bodyRect = document.body.getBoundingClientRect();
|
|
897
|
+
// Calculate the total height of all footers
|
|
898
|
+
// so we can add padding to the page element
|
|
899
|
+
footerHeights += cachedFooterEl.clientHeight;
|
|
900
|
+
// Calculate absolute position relative to body
|
|
901
|
+
// We need to subtract the body's offsetTop to get true position within document.body
|
|
902
|
+
const absoluteTop = cachedFooterElRect.top - bodyRect.top;
|
|
903
|
+
const absoluteLeft = cachedFooterElRect.left - bodyRect.left;
|
|
904
|
+
// Capture the footer's current dimensions and store them in CSS variables for
|
|
905
|
+
// later use when applying absolute positioning.
|
|
906
|
+
cachedFooterEl.style.setProperty('--pinned-width', `${cachedFooterEl.clientWidth}px`);
|
|
907
|
+
cachedFooterEl.style.setProperty('--pinned-height', `${cachedFooterEl.clientHeight}px`);
|
|
908
|
+
cachedFooterEl.style.setProperty('--pinned-top', `${absoluteTop}px`);
|
|
909
|
+
cachedFooterEl.style.setProperty('--pinned-left', `${absoluteLeft}px`);
|
|
910
|
+
// Only cache the first footer's Y position
|
|
911
|
+
// This is used to determine if the sheet has been moved below the footer
|
|
912
|
+
// and needs to be swapped back to stationary so it collapses correctly.
|
|
913
|
+
if (index === 0) {
|
|
914
|
+
cachedFooterYPosition = absoluteTop;
|
|
915
|
+
// If there's a header, we need to combine the header height with the footer position
|
|
916
|
+
// because the header moves with the drag handle, so when it starts overlapping the footer,
|
|
917
|
+
// we need to account for that.
|
|
918
|
+
const header = baseEl.querySelector('ion-header');
|
|
919
|
+
if (header) {
|
|
920
|
+
cachedFooterYPosition -= header.clientHeight;
|
|
921
|
+
}
|
|
922
|
+
}
|
|
923
|
+
});
|
|
924
|
+
// Apply the pinning of styles after we've calculated everything
|
|
925
|
+
// so that we don't cause layouts to shift while calculating the footer positions.
|
|
926
|
+
// Otherwise, with multiple footers we'll end up capturing the wrong positions.
|
|
927
|
+
cachedFooterEls.forEach((cachedFooterEl) => {
|
|
928
|
+
// Add padding to the parent element to prevent content from being hidden
|
|
929
|
+
// when the footer is positioned absolutely. This has to be done before we
|
|
930
|
+
// make the footer absolutely positioned or we may accidentally cause the
|
|
931
|
+
// sheet to scroll.
|
|
932
|
+
page === null || page === void 0 ? void 0 : page.style.setProperty('padding-bottom', `${footerHeights}px`);
|
|
933
|
+
// Apply positioning styles to keep footer at bottom
|
|
934
|
+
cachedFooterEl.classList.add('modal-footer-moving');
|
|
935
|
+
// Apply our preserved styles to pin the footer
|
|
936
|
+
cachedFooterEl.style.setProperty('position', 'absolute');
|
|
937
|
+
cachedFooterEl.style.setProperty('width', 'var(--pinned-width)');
|
|
938
|
+
cachedFooterEl.style.setProperty('height', 'var(--pinned-height)');
|
|
939
|
+
cachedFooterEl.style.setProperty('top', 'var(--pinned-top)');
|
|
940
|
+
cachedFooterEl.style.setProperty('left', 'var(--pinned-left)');
|
|
941
|
+
// Move the element to the body when everything else is done
|
|
942
|
+
document.body.appendChild(cachedFooterEl);
|
|
943
|
+
});
|
|
923
944
|
}
|
|
924
945
|
};
|
|
925
946
|
/**
|
|
@@ -1111,6 +1132,14 @@ const createSheetGesture = (baseEl, backdropEl, wrapperEl, initialBreakpoint, ba
|
|
|
1111
1132
|
* is not scrolled to the top.
|
|
1112
1133
|
*/
|
|
1113
1134
|
if (!expandToScroll && detail.deltaY <= 0 && cachedScrollEl && cachedScrollEl.scrollTop > 0) {
|
|
1135
|
+
/**
|
|
1136
|
+
* If expand to scroll is disabled, we need to make sure we swap the footer position
|
|
1137
|
+
* back to stationary so that it will collapse correctly if the modal is dismissed without
|
|
1138
|
+
* dragging (e.g. through a dismiss button).
|
|
1139
|
+
* This can cause issues if the user has a modal with content that can be dragged, as we'll
|
|
1140
|
+
* swap to moving on drag and if we don't swap back here then the footer will get stuck.
|
|
1141
|
+
*/
|
|
1142
|
+
swapFooterPosition('stationary');
|
|
1114
1143
|
return;
|
|
1115
1144
|
}
|
|
1116
1145
|
/**
|
|
@@ -179,6 +179,7 @@ export class ItemSliding {
|
|
|
179
179
|
}
|
|
180
180
|
}
|
|
181
181
|
async updateOptions() {
|
|
182
|
+
var _a;
|
|
182
183
|
const options = this.el.querySelectorAll('ion-item-options');
|
|
183
184
|
let sides = 0;
|
|
184
185
|
// Reset left and right options in case they were removed
|
|
@@ -192,7 +193,7 @@ export class ItemSliding {
|
|
|
192
193
|
*/
|
|
193
194
|
// eslint-disable-next-line custom-rules/no-component-on-ready-method
|
|
194
195
|
const option = item.componentOnReady !== undefined ? await item.componentOnReady() : item;
|
|
195
|
-
const side = isEndSide(option.side) ? 'end' : 'start';
|
|
196
|
+
const side = isEndSide((_a = option.side) !== null && _a !== void 0 ? _a : option.getAttribute('side')) ? 'end' : 'start';
|
|
196
197
|
if (side === 'start') {
|
|
197
198
|
this.leftOptions = option;
|
|
198
199
|
sides |= 1 /* ItemSide.Start */;
|
|
@@ -390,7 +391,7 @@ export class ItemSliding {
|
|
|
390
391
|
}
|
|
391
392
|
render() {
|
|
392
393
|
const mode = getIonMode(this);
|
|
393
|
-
return (h(Host, { key: '
|
|
394
|
+
return (h(Host, { key: 'd812322c9fb5da4ee16e99dc38bfb24cb4590d03', class: {
|
|
394
395
|
[mode]: true,
|
|
395
396
|
'item-sliding-active-slide': this.state !== 2 /* SlidingState.Disabled */,
|
|
396
397
|
'item-sliding-active-options-end': (this.state & 8 /* SlidingState.End */) !== 0,
|
|
@@ -35,7 +35,7 @@ export const createSheetGesture = (baseEl, backdropEl, wrapperEl, initialBreakpo
|
|
|
35
35
|
let offset = 0;
|
|
36
36
|
let canDismissBlocksGesture = false;
|
|
37
37
|
let cachedScrollEl = null;
|
|
38
|
-
let
|
|
38
|
+
let cachedFooterEls = null;
|
|
39
39
|
let cachedFooterYPosition = null;
|
|
40
40
|
let currentFooterState = null;
|
|
41
41
|
const canDismissMaxStep = 0.95;
|
|
@@ -72,60 +72,81 @@ export const createSheetGesture = (baseEl, backdropEl, wrapperEl, initialBreakpo
|
|
|
72
72
|
* @param newPosition Whether the footer is in a moving or stationary position.
|
|
73
73
|
*/
|
|
74
74
|
const swapFooterPosition = (newPosition) => {
|
|
75
|
-
if (!
|
|
76
|
-
|
|
77
|
-
if (!
|
|
75
|
+
if (!cachedFooterEls) {
|
|
76
|
+
cachedFooterEls = Array.from(baseEl.querySelectorAll('ion-footer'));
|
|
77
|
+
if (!cachedFooterEls.length) {
|
|
78
78
|
return;
|
|
79
79
|
}
|
|
80
80
|
}
|
|
81
81
|
const page = baseEl.querySelector('.ion-page');
|
|
82
82
|
currentFooterState = newPosition;
|
|
83
83
|
if (newPosition === 'stationary') {
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
84
|
+
cachedFooterEls.forEach((cachedFooterEl) => {
|
|
85
|
+
// Reset positioning styles to allow normal document flow
|
|
86
|
+
cachedFooterEl.classList.remove('modal-footer-moving');
|
|
87
|
+
cachedFooterEl.style.removeProperty('position');
|
|
88
|
+
cachedFooterEl.style.removeProperty('width');
|
|
89
|
+
cachedFooterEl.style.removeProperty('height');
|
|
90
|
+
cachedFooterEl.style.removeProperty('top');
|
|
91
|
+
cachedFooterEl.style.removeProperty('left');
|
|
92
|
+
page === null || page === void 0 ? void 0 : page.style.removeProperty('padding-bottom');
|
|
93
|
+
// Move to page
|
|
94
|
+
page === null || page === void 0 ? void 0 : page.appendChild(cachedFooterEl);
|
|
95
|
+
});
|
|
94
96
|
}
|
|
95
97
|
else {
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
}
|
|
128
|
-
|
|
98
|
+
let footerHeights = 0;
|
|
99
|
+
cachedFooterEls.forEach((cachedFooterEl, index) => {
|
|
100
|
+
// Get both the footer and document body positions
|
|
101
|
+
const cachedFooterElRect = cachedFooterEl.getBoundingClientRect();
|
|
102
|
+
const bodyRect = document.body.getBoundingClientRect();
|
|
103
|
+
// Calculate the total height of all footers
|
|
104
|
+
// so we can add padding to the page element
|
|
105
|
+
footerHeights += cachedFooterEl.clientHeight;
|
|
106
|
+
// Calculate absolute position relative to body
|
|
107
|
+
// We need to subtract the body's offsetTop to get true position within document.body
|
|
108
|
+
const absoluteTop = cachedFooterElRect.top - bodyRect.top;
|
|
109
|
+
const absoluteLeft = cachedFooterElRect.left - bodyRect.left;
|
|
110
|
+
// Capture the footer's current dimensions and store them in CSS variables for
|
|
111
|
+
// later use when applying absolute positioning.
|
|
112
|
+
cachedFooterEl.style.setProperty('--pinned-width', `${cachedFooterEl.clientWidth}px`);
|
|
113
|
+
cachedFooterEl.style.setProperty('--pinned-height', `${cachedFooterEl.clientHeight}px`);
|
|
114
|
+
cachedFooterEl.style.setProperty('--pinned-top', `${absoluteTop}px`);
|
|
115
|
+
cachedFooterEl.style.setProperty('--pinned-left', `${absoluteLeft}px`);
|
|
116
|
+
// Only cache the first footer's Y position
|
|
117
|
+
// This is used to determine if the sheet has been moved below the footer
|
|
118
|
+
// and needs to be swapped back to stationary so it collapses correctly.
|
|
119
|
+
if (index === 0) {
|
|
120
|
+
cachedFooterYPosition = absoluteTop;
|
|
121
|
+
// If there's a header, we need to combine the header height with the footer position
|
|
122
|
+
// because the header moves with the drag handle, so when it starts overlapping the footer,
|
|
123
|
+
// we need to account for that.
|
|
124
|
+
const header = baseEl.querySelector('ion-header');
|
|
125
|
+
if (header) {
|
|
126
|
+
cachedFooterYPosition -= header.clientHeight;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
});
|
|
130
|
+
// Apply the pinning of styles after we've calculated everything
|
|
131
|
+
// so that we don't cause layouts to shift while calculating the footer positions.
|
|
132
|
+
// Otherwise, with multiple footers we'll end up capturing the wrong positions.
|
|
133
|
+
cachedFooterEls.forEach((cachedFooterEl) => {
|
|
134
|
+
// Add padding to the parent element to prevent content from being hidden
|
|
135
|
+
// when the footer is positioned absolutely. This has to be done before we
|
|
136
|
+
// make the footer absolutely positioned or we may accidentally cause the
|
|
137
|
+
// sheet to scroll.
|
|
138
|
+
page === null || page === void 0 ? void 0 : page.style.setProperty('padding-bottom', `${footerHeights}px`);
|
|
139
|
+
// Apply positioning styles to keep footer at bottom
|
|
140
|
+
cachedFooterEl.classList.add('modal-footer-moving');
|
|
141
|
+
// Apply our preserved styles to pin the footer
|
|
142
|
+
cachedFooterEl.style.setProperty('position', 'absolute');
|
|
143
|
+
cachedFooterEl.style.setProperty('width', 'var(--pinned-width)');
|
|
144
|
+
cachedFooterEl.style.setProperty('height', 'var(--pinned-height)');
|
|
145
|
+
cachedFooterEl.style.setProperty('top', 'var(--pinned-top)');
|
|
146
|
+
cachedFooterEl.style.setProperty('left', 'var(--pinned-left)');
|
|
147
|
+
// Move the element to the body when everything else is done
|
|
148
|
+
document.body.appendChild(cachedFooterEl);
|
|
149
|
+
});
|
|
129
150
|
}
|
|
130
151
|
};
|
|
131
152
|
/**
|
|
@@ -317,6 +338,14 @@ export const createSheetGesture = (baseEl, backdropEl, wrapperEl, initialBreakpo
|
|
|
317
338
|
* is not scrolled to the top.
|
|
318
339
|
*/
|
|
319
340
|
if (!expandToScroll && detail.deltaY <= 0 && cachedScrollEl && cachedScrollEl.scrollTop > 0) {
|
|
341
|
+
/**
|
|
342
|
+
* If expand to scroll is disabled, we need to make sure we swap the footer position
|
|
343
|
+
* back to stationary so that it will collapse correctly if the modal is dismissed without
|
|
344
|
+
* dragging (e.g. through a dismiss button).
|
|
345
|
+
* This can cause issues if the user has a modal with content that can be dragged, as we'll
|
|
346
|
+
* swap to moving on drag and if we don't swap back here then the footer will get stuck.
|
|
347
|
+
*/
|
|
348
|
+
swapFooterPosition('stationary');
|
|
320
349
|
return;
|
|
321
350
|
}
|
|
322
351
|
/**
|
package/dist/docs.json
CHANGED
|
@@ -280,6 +280,7 @@ const ItemSliding = class {
|
|
|
280
280
|
}
|
|
281
281
|
}
|
|
282
282
|
async updateOptions() {
|
|
283
|
+
var _a;
|
|
283
284
|
const options = this.el.querySelectorAll('ion-item-options');
|
|
284
285
|
let sides = 0;
|
|
285
286
|
// Reset left and right options in case they were removed
|
|
@@ -293,7 +294,7 @@ const ItemSliding = class {
|
|
|
293
294
|
*/
|
|
294
295
|
// eslint-disable-next-line custom-rules/no-component-on-ready-method
|
|
295
296
|
const option = item.componentOnReady !== undefined ? await item.componentOnReady() : item;
|
|
296
|
-
const side = isEndSide(option.side) ? 'end' : 'start';
|
|
297
|
+
const side = isEndSide((_a = option.side) !== null && _a !== void 0 ? _a : option.getAttribute('side')) ? 'end' : 'start';
|
|
297
298
|
if (side === 'start') {
|
|
298
299
|
this.leftOptions = option;
|
|
299
300
|
sides |= 1 /* ItemSide.Start */;
|
|
@@ -491,7 +492,7 @@ const ItemSliding = class {
|
|
|
491
492
|
}
|
|
492
493
|
render() {
|
|
493
494
|
const mode = getIonMode(this);
|
|
494
|
-
return (h(Host, { key: '
|
|
495
|
+
return (h(Host, { key: 'd812322c9fb5da4ee16e99dc38bfb24cb4590d03', class: {
|
|
495
496
|
[mode]: true,
|
|
496
497
|
'item-sliding-active-slide': this.state !== 2 /* SlidingState.Disabled */,
|
|
497
498
|
'item-sliding-active-options-end': (this.state & 8 /* SlidingState.End */) !== 0,
|