@ionic/core 8.7.17-dev.11767796972.148e4bc4 → 8.7.17-dev.11767895575.16ea7cef
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/content.js +6 -79
- package/components/ion-tab-bar.js +23 -3
- package/components/modal.js +12 -200
- package/components/popover.js +10 -73
- package/dist/cjs/ion-app_8.cjs.entry.js +5 -78
- package/dist/cjs/ion-modal.cjs.entry.js +12 -200
- package/dist/cjs/ion-popover.cjs.entry.js +10 -73
- package/dist/cjs/ion-tab-bar_2.cjs.entry.js +23 -3
- package/dist/collection/components/content/content.css +0 -10
- package/dist/collection/components/content/content.js +4 -77
- package/dist/collection/components/modal/gestures/sheet.js +1 -3
- package/dist/collection/components/modal/gestures/swipe-to-close.js +1 -3
- package/dist/collection/components/modal/modal.ios.css +4 -0
- package/dist/collection/components/modal/modal.js +8 -192
- package/dist/collection/components/modal/modal.md.css +4 -0
- package/dist/collection/components/popover/animations/ios.enter.js +5 -21
- package/dist/collection/components/popover/animations/md.enter.js +4 -20
- package/dist/collection/components/popover/utils.js +1 -32
- package/dist/collection/components/tab-bar/tab-bar.js +23 -3
- package/dist/docs.json +1 -1
- package/dist/esm/ion-app_8.entry.js +6 -79
- package/dist/esm/ion-modal.entry.js +12 -200
- package/dist/esm/ion-popover.entry.js +10 -73
- package/dist/esm/ion-tab-bar_2.entry.js +23 -3
- package/dist/ionic/ionic.esm.js +1 -1
- package/dist/ionic/p-172a579f.entry.js +4 -0
- package/dist/ionic/p-732b2fd6.entry.js +4 -0
- package/dist/ionic/p-91840a80.entry.js +4 -0
- package/dist/ionic/p-f9061316.entry.js +4 -0
- package/dist/types/components/content/content.d.ts +0 -24
- package/dist/types/components/modal/gestures/sheet.d.ts +1 -1
- package/dist/types/components/modal/gestures/swipe-to-close.d.ts +1 -1
- package/dist/types/components/modal/modal.d.ts +0 -39
- package/dist/types/components/popover/utils.d.ts +0 -2
- package/dist/types/components/tab-bar/tab-bar.d.ts +1 -0
- package/hydrate/index.js +50 -353
- package/hydrate/index.mjs +50 -353
- package/package.json +1 -1
- package/dist/ionic/p-3830217a.entry.js +0 -4
- package/dist/ionic/p-7268efa5.entry.js +0 -4
- package/dist/ionic/p-a4827773.entry.js +0 -4
- package/dist/ionic/p-cecd141b.entry.js +0 -4
package/components/popover.js
CHANGED
|
@@ -657,8 +657,6 @@ const calculateWindowAdjustment = (side, coordTop, coordLeft, bodyPadding, bodyW
|
|
|
657
657
|
let bottom;
|
|
658
658
|
let originX = contentOriginX;
|
|
659
659
|
let originY = contentOriginY;
|
|
660
|
-
let checkSafeAreaTop = false;
|
|
661
|
-
let checkSafeAreaBottom = false;
|
|
662
660
|
let checkSafeAreaLeft = false;
|
|
663
661
|
let checkSafeAreaRight = false;
|
|
664
662
|
const triggerTop = triggerCoordinates
|
|
@@ -703,18 +701,10 @@ const calculateWindowAdjustment = (side, coordTop, coordLeft, bodyPadding, bodyW
|
|
|
703
701
|
* We chose 12 here so that the popover position looks a bit nicer as
|
|
704
702
|
* it is not right up against the edge of the screen.
|
|
705
703
|
*/
|
|
706
|
-
top = Math.max(
|
|
704
|
+
top = Math.max(12, triggerTop - contentHeight - triggerHeight - (arrowHeight - 1));
|
|
707
705
|
arrowTop = top + contentHeight;
|
|
708
706
|
originY = 'bottom';
|
|
709
707
|
addPopoverBottomClass = true;
|
|
710
|
-
/**
|
|
711
|
-
* If the popover is positioned near the top edge, account for safe area.
|
|
712
|
-
* This ensures the popover doesn't overlap with status bars or notches.
|
|
713
|
-
*/
|
|
714
|
-
if (top <= bodyPadding + safeAreaMargin) {
|
|
715
|
-
checkSafeAreaTop = true;
|
|
716
|
-
top = bodyPadding;
|
|
717
|
-
}
|
|
718
708
|
/**
|
|
719
709
|
* If not enough room for popover to appear
|
|
720
710
|
* above trigger, then cut it off.
|
|
@@ -722,35 +712,14 @@ const calculateWindowAdjustment = (side, coordTop, coordLeft, bodyPadding, bodyW
|
|
|
722
712
|
}
|
|
723
713
|
else {
|
|
724
714
|
bottom = bodyPadding;
|
|
725
|
-
/**
|
|
726
|
-
* When the popover is pinned to the bottom, account for safe area.
|
|
727
|
-
* This ensures the popover doesn't overlap with home indicators
|
|
728
|
-
* or navigation bars (e.g., Android API 36+ edge-to-edge).
|
|
729
|
-
*/
|
|
730
|
-
checkSafeAreaBottom = true;
|
|
731
715
|
}
|
|
732
716
|
}
|
|
733
|
-
/**
|
|
734
|
-
* Final check: If the popover extends into any safe-area region,
|
|
735
|
-
* ensure the corresponding flag is set regardless of side.
|
|
736
|
-
* This handles cases where a side-positioned popover (left/right)
|
|
737
|
-
* still needs bottom safe-area padding because it extends into that region.
|
|
738
|
-
*/
|
|
739
|
-
const popoverBottom = bottom !== undefined ? bodyHeight - bottom : top + contentHeight;
|
|
740
|
-
if (popoverBottom + safeAreaMargin > bodyHeight) {
|
|
741
|
-
checkSafeAreaBottom = true;
|
|
742
|
-
}
|
|
743
|
-
if (top < safeAreaMargin) {
|
|
744
|
-
checkSafeAreaTop = true;
|
|
745
|
-
}
|
|
746
717
|
return {
|
|
747
718
|
top,
|
|
748
719
|
left,
|
|
749
720
|
bottom,
|
|
750
721
|
originX,
|
|
751
722
|
originY,
|
|
752
|
-
checkSafeAreaTop,
|
|
753
|
-
checkSafeAreaBottom,
|
|
754
723
|
checkSafeAreaLeft,
|
|
755
724
|
checkSafeAreaRight,
|
|
756
725
|
arrowTop,
|
|
@@ -811,7 +780,7 @@ const iosEnterAnimation = (baseEl, opts) => {
|
|
|
811
780
|
const results = getPopoverPosition(isRTL, contentWidth, contentHeight, arrowWidth, arrowHeight, reference, side, align, defaultPosition, trigger, ev);
|
|
812
781
|
const padding = size === 'cover' ? 0 : POPOVER_IOS_BODY_PADDING;
|
|
813
782
|
const margin = size === 'cover' ? 0 : 25;
|
|
814
|
-
const { originX, originY, top, left, bottom,
|
|
783
|
+
const { originX, originY, top, left, bottom, checkSafeAreaLeft, checkSafeAreaRight, arrowTop, arrowLeft, addPopoverBottomClass, } = calculateWindowAdjustment(side, results.top, results.left, padding, bodyWidth, bodyHeight, contentWidth, contentHeight, margin, results.originX, results.originY, results.referenceCoordinates, results.arrowTop, results.arrowLeft, arrowHeight);
|
|
815
784
|
const baseAnimation = createAnimation();
|
|
816
785
|
const backdropAnimation = createAnimation();
|
|
817
786
|
const contentAnimation = createAnimation();
|
|
@@ -841,35 +810,19 @@ const iosEnterAnimation = (baseEl, opts) => {
|
|
|
841
810
|
if (addPopoverBottomClass) {
|
|
842
811
|
baseEl.classList.add('popover-bottom');
|
|
843
812
|
}
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
* safe-area inset to ensure the popover doesn't overlap with system UI
|
|
848
|
-
* (status bars, home indicators, navigation bars on Android API 36+, etc.)
|
|
849
|
-
*/
|
|
850
|
-
const safeAreaTop = ' + var(--ion-safe-area-top, 0)';
|
|
851
|
-
const safeAreaBottom = ' + var(--ion-safe-area-bottom, 0)';
|
|
813
|
+
if (bottom !== undefined) {
|
|
814
|
+
contentEl.style.setProperty('bottom', `${bottom}px`);
|
|
815
|
+
}
|
|
852
816
|
const safeAreaLeft = ' + var(--ion-safe-area-left, 0)';
|
|
853
817
|
const safeAreaRight = ' - var(--ion-safe-area-right, 0)';
|
|
854
|
-
let topValue = `${top}px`;
|
|
855
|
-
let bottomValue = bottom !== undefined ? `${bottom}px` : undefined;
|
|
856
818
|
let leftValue = `${left}px`;
|
|
857
|
-
if (checkSafeAreaTop) {
|
|
858
|
-
topValue = `${top}px${safeAreaTop}`;
|
|
859
|
-
}
|
|
860
|
-
if (checkSafeAreaBottom && bottomValue !== undefined) {
|
|
861
|
-
bottomValue = `${bottom}px${safeAreaBottom}`;
|
|
862
|
-
}
|
|
863
819
|
if (checkSafeAreaLeft) {
|
|
864
820
|
leftValue = `${left}px${safeAreaLeft}`;
|
|
865
821
|
}
|
|
866
822
|
if (checkSafeAreaRight) {
|
|
867
823
|
leftValue = `${left}px${safeAreaRight}`;
|
|
868
824
|
}
|
|
869
|
-
|
|
870
|
-
contentEl.style.setProperty('bottom', `calc(${bottomValue})`);
|
|
871
|
-
}
|
|
872
|
-
contentEl.style.setProperty('top', `calc(${topValue} + var(--offset-y, 0))`);
|
|
825
|
+
contentEl.style.setProperty('top', `calc(${top}px + var(--offset-y, 0))`);
|
|
873
826
|
contentEl.style.setProperty('left', `calc(${leftValue} + var(--offset-x, 0))`);
|
|
874
827
|
contentEl.style.setProperty('transform-origin', `${originY} ${originX}`);
|
|
875
828
|
if (arrowEl !== null) {
|
|
@@ -945,23 +898,7 @@ const mdEnterAnimation = (baseEl, opts) => {
|
|
|
945
898
|
};
|
|
946
899
|
const results = getPopoverPosition(isRTL, contentWidth, contentHeight, 0, 0, reference, side, align, defaultPosition, trigger, ev);
|
|
947
900
|
const padding = size === 'cover' ? 0 : POPOVER_MD_BODY_PADDING;
|
|
948
|
-
const { originX, originY, top, left, bottom
|
|
949
|
-
/**
|
|
950
|
-
* Safe area CSS variable adjustments.
|
|
951
|
-
* When the popover is positioned near an edge, we add the corresponding
|
|
952
|
-
* safe-area inset to ensure the popover doesn't overlap with system UI
|
|
953
|
-
* (status bars, home indicators, navigation bars on Android API 36+, etc.)
|
|
954
|
-
*/
|
|
955
|
-
const safeAreaTop = ' + var(--ion-safe-area-top, 0)';
|
|
956
|
-
const safeAreaBottom = ' + var(--ion-safe-area-bottom, 0)';
|
|
957
|
-
let topValue = `${top}px`;
|
|
958
|
-
let bottomValue = bottom !== undefined ? `${bottom}px` : undefined;
|
|
959
|
-
if (checkSafeAreaTop) {
|
|
960
|
-
topValue = `${top}px${safeAreaTop}`;
|
|
961
|
-
}
|
|
962
|
-
if (checkSafeAreaBottom && bottomValue !== undefined) {
|
|
963
|
-
bottomValue = `${bottom}px${safeAreaBottom}`;
|
|
964
|
-
}
|
|
901
|
+
const { originX, originY, top, left, bottom } = calculateWindowAdjustment(side, results.top, results.left, padding, bodyWidth, bodyHeight, contentWidth, contentHeight, 0, results.originX, results.originY, results.referenceCoordinates);
|
|
965
902
|
const baseAnimation = createAnimation();
|
|
966
903
|
const backdropAnimation = createAnimation();
|
|
967
904
|
const wrapperAnimation = createAnimation();
|
|
@@ -978,13 +915,13 @@ const mdEnterAnimation = (baseEl, opts) => {
|
|
|
978
915
|
contentAnimation
|
|
979
916
|
.addElement(contentEl)
|
|
980
917
|
.beforeStyles({
|
|
981
|
-
top: `calc(${
|
|
918
|
+
top: `calc(${top}px + var(--offset-y, 0px))`,
|
|
982
919
|
left: `calc(${left}px + var(--offset-x, 0px))`,
|
|
983
920
|
'transform-origin': `${originY} ${originX}`,
|
|
984
921
|
})
|
|
985
922
|
.beforeAddWrite(() => {
|
|
986
|
-
if (
|
|
987
|
-
contentEl.style.setProperty('bottom',
|
|
923
|
+
if (bottom !== undefined) {
|
|
924
|
+
contentEl.style.setProperty('bottom', `${bottom}px`);
|
|
988
925
|
}
|
|
989
926
|
})
|
|
990
927
|
.fromTo('transform', 'scale(0.8)', 'scale(1)');
|
|
@@ -154,7 +154,7 @@ Buttons.style = {
|
|
|
154
154
|
md: buttonsMdCss
|
|
155
155
|
};
|
|
156
156
|
|
|
157
|
-
const contentCss = ":host{--background:var(--ion-background-color, #fff);--color:var(--ion-text-color, #000);--padding-top:0px;--padding-bottom:0px;--padding-start:0px;--padding-end:0px;--keyboard-offset:0px;--offset-top:0px;--offset-bottom:0px;--overflow:auto;display:block;position:relative;-ms-flex:1;flex:1;width:100%;height:100%;margin:0 !important;padding:0 !important;font-family:var(--ion-font-family, inherit);contain:size style}:host(.ion-color) .inner-scroll{background:var(--ion-color-base);color:var(--ion-color-contrast)}#background-content{left:0px;right:0px;top:calc(var(--offset-top) * -1);bottom:calc(var(--offset-bottom) * -1);position:absolute;background:var(--background)}.inner-scroll{left:0px;right:0px;top:calc(var(--offset-top) * -1);bottom:calc(var(--offset-bottom) * -1);-webkit-padding-start:var(--padding-start);padding-inline-start:var(--padding-start);-webkit-padding-end:var(--padding-end);padding-inline-end:var(--padding-end);padding-top:calc(var(--padding-top) + var(--offset-top));padding-bottom:calc(var(--padding-bottom) + var(--keyboard-offset) + var(--offset-bottom));position:absolute;color:var(--color);-webkit-box-sizing:border-box;box-sizing:border-box;overflow:hidden;-ms-touch-action:pan-x pan-y pinch-zoom;touch-action:pan-x pan-y pinch-zoom}.scroll-y,.scroll-x{-webkit-overflow-scrolling:touch;z-index:0;will-change:scroll-position}.scroll-y{overflow-y:var(--overflow);overscroll-behavior-y:contain}.scroll-x{overflow-x:var(--overflow);overscroll-behavior-x:contain}.overscroll::before,.overscroll::after{position:absolute;width:1px;height:1px;content:\"\"}.overscroll::before{bottom:-1px}.overscroll::after{top:-1px}:host(.content-sizing){display:-ms-flexbox;display:flex;-ms-flex-direction:column;flex-direction:column;min-height:0;contain:none}:host(.content-sizing) .inner-scroll{position:relative;top:0;bottom:0;margin-top:calc(var(--offset-top) * -1);margin-bottom:calc(var(--offset-bottom) * -1)}.transition-effect{display:none;position:absolute;width:100%;height:100vh;opacity:0;pointer-events:none}:host(.content-ltr) .transition-effect{left:-100%;}:host(.content-rtl) .transition-effect{right:-100%;}.transition-cover{position:absolute;right:0;width:100%;height:100%;background:black;opacity:0.1}.transition-shadow{display:block;position:absolute;width:100%;height:100%;-webkit-box-shadow:inset -9px 0 9px 0 rgba(0, 0, 100, 0.03);box-shadow:inset -9px 0 9px 0 rgba(0, 0, 100, 0.03)}:host(.content-ltr) .transition-shadow{right:0;}:host(.content-rtl) .transition-shadow{left:0;-webkit-transform:scaleX(-1);transform:scaleX(-1)}
|
|
157
|
+
const contentCss = ":host{--background:var(--ion-background-color, #fff);--color:var(--ion-text-color, #000);--padding-top:0px;--padding-bottom:0px;--padding-start:0px;--padding-end:0px;--keyboard-offset:0px;--offset-top:0px;--offset-bottom:0px;--overflow:auto;display:block;position:relative;-ms-flex:1;flex:1;width:100%;height:100%;margin:0 !important;padding:0 !important;font-family:var(--ion-font-family, inherit);contain:size style}:host(.ion-color) .inner-scroll{background:var(--ion-color-base);color:var(--ion-color-contrast)}#background-content{left:0px;right:0px;top:calc(var(--offset-top) * -1);bottom:calc(var(--offset-bottom) * -1);position:absolute;background:var(--background)}.inner-scroll{left:0px;right:0px;top:calc(var(--offset-top) * -1);bottom:calc(var(--offset-bottom) * -1);-webkit-padding-start:var(--padding-start);padding-inline-start:var(--padding-start);-webkit-padding-end:var(--padding-end);padding-inline-end:var(--padding-end);padding-top:calc(var(--padding-top) + var(--offset-top));padding-bottom:calc(var(--padding-bottom) + var(--keyboard-offset) + var(--offset-bottom));position:absolute;color:var(--color);-webkit-box-sizing:border-box;box-sizing:border-box;overflow:hidden;-ms-touch-action:pan-x pan-y pinch-zoom;touch-action:pan-x pan-y pinch-zoom}.scroll-y,.scroll-x{-webkit-overflow-scrolling:touch;z-index:0;will-change:scroll-position}.scroll-y{overflow-y:var(--overflow);overscroll-behavior-y:contain}.scroll-x{overflow-x:var(--overflow);overscroll-behavior-x:contain}.overscroll::before,.overscroll::after{position:absolute;width:1px;height:1px;content:\"\"}.overscroll::before{bottom:-1px}.overscroll::after{top:-1px}:host(.content-sizing){display:-ms-flexbox;display:flex;-ms-flex-direction:column;flex-direction:column;min-height:0;contain:none}:host(.content-sizing) .inner-scroll{position:relative;top:0;bottom:0;margin-top:calc(var(--offset-top) * -1);margin-bottom:calc(var(--offset-bottom) * -1)}.transition-effect{display:none;position:absolute;width:100%;height:100vh;opacity:0;pointer-events:none}:host(.content-ltr) .transition-effect{left:-100%;}:host(.content-rtl) .transition-effect{right:-100%;}.transition-cover{position:absolute;right:0;width:100%;height:100%;background:black;opacity:0.1}.transition-shadow{display:block;position:absolute;width:100%;height:100%;-webkit-box-shadow:inset -9px 0 9px 0 rgba(0, 0, 100, 0.03);box-shadow:inset -9px 0 9px 0 rgba(0, 0, 100, 0.03)}:host(.content-ltr) .transition-shadow{right:0;}:host(.content-rtl) .transition-shadow{left:0;-webkit-transform:scaleX(-1);transform:scaleX(-1)}::slotted([slot=fixed]){position:absolute;-webkit-transform:translateZ(0);transform:translateZ(0)}";
|
|
158
158
|
|
|
159
159
|
const Content = class {
|
|
160
160
|
constructor(hostRef) {
|
|
@@ -171,12 +171,6 @@ const Content = class {
|
|
|
171
171
|
this.isMainContent = true;
|
|
172
172
|
this.resizeTimeout = null;
|
|
173
173
|
this.inheritedAttributes = {};
|
|
174
|
-
/**
|
|
175
|
-
* Track whether this content has sibling header/footer elements.
|
|
176
|
-
* When absent, we need to apply safe-area padding directly.
|
|
177
|
-
*/
|
|
178
|
-
this.hasHeader = false;
|
|
179
|
-
this.hasFooter = false;
|
|
180
174
|
this.tabsElement = null;
|
|
181
175
|
// Detail is used in a hot loop in the scroll event, by allocating it here
|
|
182
176
|
// V8 will be able to inline any read/write to it since it's a monomorphic class.
|
|
@@ -232,8 +226,6 @@ const Content = class {
|
|
|
232
226
|
}
|
|
233
227
|
connectedCallback() {
|
|
234
228
|
this.isMainContent = this.el.closest('ion-menu, ion-popover, ion-modal') === null;
|
|
235
|
-
// Detect sibling header/footer for safe-area handling
|
|
236
|
-
this.detectSiblingElements();
|
|
237
229
|
/**
|
|
238
230
|
* The fullscreen content offsets need to be
|
|
239
231
|
* computed after the tab bar has loaded. Since
|
|
@@ -269,71 +261,8 @@ const Content = class {
|
|
|
269
261
|
}
|
|
270
262
|
}
|
|
271
263
|
}
|
|
272
|
-
/**
|
|
273
|
-
* Detects sibling ion-header and ion-footer elements and sets up
|
|
274
|
-
* a mutation observer to handle dynamic changes (e.g., conditional rendering).
|
|
275
|
-
*/
|
|
276
|
-
detectSiblingElements() {
|
|
277
|
-
this.updateSiblingDetection();
|
|
278
|
-
// Watch for dynamic header/footer changes (common in React conditional rendering)
|
|
279
|
-
const parent = this.el.parentElement;
|
|
280
|
-
if (parent && !this.parentMutationObserver) {
|
|
281
|
-
this.parentMutationObserver = new MutationObserver(() => {
|
|
282
|
-
this.updateSiblingDetection();
|
|
283
|
-
index.forceUpdate(this);
|
|
284
|
-
});
|
|
285
|
-
this.parentMutationObserver.observe(parent, { childList: true });
|
|
286
|
-
}
|
|
287
|
-
}
|
|
288
|
-
/**
|
|
289
|
-
* Updates hasHeader/hasFooter based on current DOM state.
|
|
290
|
-
* Checks both direct siblings and elements wrapped in custom components
|
|
291
|
-
* (e.g., <my-header><ion-header>...</ion-header></my-header>).
|
|
292
|
-
*/
|
|
293
|
-
updateSiblingDetection() {
|
|
294
|
-
const parent = this.el.parentElement;
|
|
295
|
-
if (parent) {
|
|
296
|
-
// First check for direct ion-header/ion-footer siblings
|
|
297
|
-
this.hasHeader = parent.querySelector(':scope > ion-header') !== null;
|
|
298
|
-
this.hasFooter = parent.querySelector(':scope > ion-footer') !== null;
|
|
299
|
-
// If not found, check if any sibling contains them (wrapped components)
|
|
300
|
-
if (!this.hasHeader) {
|
|
301
|
-
this.hasHeader = this.siblingContainsElement(parent, 'ion-header');
|
|
302
|
-
}
|
|
303
|
-
if (!this.hasFooter) {
|
|
304
|
-
this.hasFooter = this.siblingContainsElement(parent, 'ion-footer');
|
|
305
|
-
}
|
|
306
|
-
}
|
|
307
|
-
// If no footer found, check if we're inside ion-tabs which has ion-tab-bar
|
|
308
|
-
if (!this.hasFooter) {
|
|
309
|
-
const tabs = this.el.closest('ion-tabs');
|
|
310
|
-
if (tabs) {
|
|
311
|
-
this.hasFooter = tabs.querySelector(':scope > ion-tab-bar') !== null;
|
|
312
|
-
}
|
|
313
|
-
}
|
|
314
|
-
}
|
|
315
|
-
/**
|
|
316
|
-
* Checks if any sibling element of ion-content contains the specified element.
|
|
317
|
-
* Only searches one level deep to avoid finding elements in nested pages.
|
|
318
|
-
*/
|
|
319
|
-
siblingContainsElement(parent, tagName) {
|
|
320
|
-
for (const sibling of parent.children) {
|
|
321
|
-
// Skip ion-content itself
|
|
322
|
-
if (sibling === this.el)
|
|
323
|
-
continue;
|
|
324
|
-
// Check if this sibling contains the target element as an immediate child
|
|
325
|
-
if (sibling.querySelector(`:scope > ${tagName}`) !== null) {
|
|
326
|
-
return true;
|
|
327
|
-
}
|
|
328
|
-
}
|
|
329
|
-
return false;
|
|
330
|
-
}
|
|
331
264
|
disconnectedCallback() {
|
|
332
|
-
var _a;
|
|
333
265
|
this.onScrollEnd();
|
|
334
|
-
// Clean up mutation observer to prevent memory leaks
|
|
335
|
-
(_a = this.parentMutationObserver) === null || _a === void 0 ? void 0 : _a.disconnect();
|
|
336
|
-
this.parentMutationObserver = undefined;
|
|
337
266
|
if (helpers.hasLazyBuild(this.el)) {
|
|
338
267
|
/**
|
|
339
268
|
* The event listener and tabs caches need to
|
|
@@ -580,28 +509,26 @@ const Content = class {
|
|
|
580
509
|
}
|
|
581
510
|
}
|
|
582
511
|
render() {
|
|
583
|
-
const { fixedSlotPlacement,
|
|
512
|
+
const { fixedSlotPlacement, inheritedAttributes, isMainContent, scrollX, scrollY, el } = this;
|
|
584
513
|
const rtl = dir.isRTL(el) ? 'rtl' : 'ltr';
|
|
585
514
|
const mode = ionicGlobal.getIonMode(this);
|
|
586
515
|
const forceOverscroll = this.shouldForceOverscroll();
|
|
587
516
|
const transitionShadow = mode === 'ios';
|
|
588
517
|
this.resize();
|
|
589
|
-
return (index.h(index.Host, Object.assign({ key: '
|
|
518
|
+
return (index.h(index.Host, Object.assign({ key: 'cd8781f848d8dc926fe66f43d43c49564425a507', role: isMainContent ? 'main' : undefined, class: theme.createColorClasses(this.color, {
|
|
590
519
|
[mode]: true,
|
|
591
520
|
'content-sizing': theme.hostContext('ion-popover', this.el),
|
|
592
521
|
overscroll: forceOverscroll,
|
|
593
522
|
[`content-${rtl}`]: true,
|
|
594
|
-
'safe-area-top': isMainContent && !hasHeader,
|
|
595
|
-
'safe-area-bottom': isMainContent && !hasFooter,
|
|
596
523
|
}), style: {
|
|
597
524
|
'--offset-top': `${this.cTop}px`,
|
|
598
525
|
'--offset-bottom': `${this.cBottom}px`,
|
|
599
|
-
} }, inheritedAttributes), index.h("div", { key: '
|
|
526
|
+
} }, inheritedAttributes), index.h("div", { key: '95b112d7cae30f22ef778ceffb88edb4d941c170', ref: (el) => (this.backgroundContentEl = el), id: "background-content", part: "background" }), fixedSlotPlacement === 'before' ? index.h("slot", { name: "fixed" }) : null, index.h("div", { key: '2fdfcbc39fb66f11b6191911f2941c660f4c12e5', class: {
|
|
600
527
|
'inner-scroll': true,
|
|
601
528
|
'scroll-x': scrollX,
|
|
602
529
|
'scroll-y': scrollY,
|
|
603
530
|
overscroll: (scrollX || scrollY) && forceOverscroll,
|
|
604
|
-
}, ref: (scrollEl) => (this.scrollEl = scrollEl), onScroll: this.scrollEvents ? (ev) => this.onScroll(ev) : undefined, part: "scroll" }, index.h("slot", { key: '
|
|
531
|
+
}, ref: (scrollEl) => (this.scrollEl = scrollEl), onScroll: this.scrollEvents ? (ev) => this.onScroll(ev) : undefined, part: "scroll" }, index.h("slot", { key: '6bc77e0054ec8e21635a7f2abfe0ca46e0962e03' })), transitionShadow ? (index.h("div", { class: "transition-effect" }, index.h("div", { class: "transition-cover" }), index.h("div", { class: "transition-shadow" }))) : null, fixedSlotPlacement === 'after' ? index.h("slot", { name: "fixed" }) : null));
|
|
605
532
|
}
|
|
606
533
|
get el() { return index.getElement(this); }
|
|
607
534
|
};
|
|
@@ -249,7 +249,7 @@ const calculateSpringStep = (t) => {
|
|
|
249
249
|
const SwipeToCloseDefaults = {
|
|
250
250
|
MIN_PRESENTING_SCALE: 0.915,
|
|
251
251
|
};
|
|
252
|
-
const createSwipeToCloseGesture = (el, animation, statusBarStyle, onDismiss
|
|
252
|
+
const createSwipeToCloseGesture = (el, animation, statusBarStyle, onDismiss) => {
|
|
253
253
|
/**
|
|
254
254
|
* The step value at which a card modal
|
|
255
255
|
* is eligible for dismissing via gesture.
|
|
@@ -406,8 +406,6 @@ const createSwipeToCloseGesture = (el, animation, statusBarStyle, onDismiss, onG
|
|
|
406
406
|
const processedStep = isAttemptingDismissWithCanDismiss ? calculateSpringStep(step / maxStep) : step;
|
|
407
407
|
const clampedStep = helpers.clamp(0.0001, processedStep, maxStep);
|
|
408
408
|
animation.progressStep(clampedStep);
|
|
409
|
-
// Notify modal of position change for safe-area updates
|
|
410
|
-
onGestureMove === null || onGestureMove === void 0 ? void 0 : onGestureMove();
|
|
411
409
|
/**
|
|
412
410
|
* When swiping down half way, the status bar style
|
|
413
411
|
* should be reset to its default value.
|
|
@@ -951,7 +949,7 @@ const mdLeaveAnimation = (baseEl, opts) => {
|
|
|
951
949
|
return baseAnimation;
|
|
952
950
|
};
|
|
953
951
|
|
|
954
|
-
const createSheetGesture = (baseEl, backdropEl, wrapperEl, initialBreakpoint, backdropBreakpoint, animation, breakpoints = [], expandToScroll, getCurrentBreakpoint, onDismiss, onBreakpointChange
|
|
952
|
+
const createSheetGesture = (baseEl, backdropEl, wrapperEl, initialBreakpoint, backdropBreakpoint, animation, breakpoints = [], expandToScroll, getCurrentBreakpoint, onDismiss, onBreakpointChange) => {
|
|
955
953
|
// Defaults for the sheet swipe animation
|
|
956
954
|
const defaultBackdrop = [
|
|
957
955
|
{ offset: 0, opacity: 'var(--backdrop-opacity)' },
|
|
@@ -1282,8 +1280,6 @@ const createSheetGesture = (baseEl, backdropEl, wrapperEl, initialBreakpoint, ba
|
|
|
1282
1280
|
: step;
|
|
1283
1281
|
offset = helpers.clamp(0.0001, processedStep, maxStep);
|
|
1284
1282
|
animation.progressStep(offset);
|
|
1285
|
-
// Notify modal of position change for safe-area updates
|
|
1286
|
-
onGestureMove === null || onGestureMove === void 0 ? void 0 : onGestureMove();
|
|
1287
1283
|
};
|
|
1288
1284
|
const onEnd = (detail) => {
|
|
1289
1285
|
/**
|
|
@@ -1478,9 +1474,9 @@ const createSheetGesture = (baseEl, backdropEl, wrapperEl, initialBreakpoint, ba
|
|
|
1478
1474
|
};
|
|
1479
1475
|
};
|
|
1480
1476
|
|
|
1481
|
-
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}}@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}";
|
|
1477
|
+
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}";
|
|
1482
1478
|
|
|
1483
|
-
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}}@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}";
|
|
1479
|
+
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}";
|
|
1484
1480
|
|
|
1485
1481
|
const Modal = class {
|
|
1486
1482
|
constructor(hostRef) {
|
|
@@ -1503,10 +1499,6 @@ const Modal = class {
|
|
|
1503
1499
|
this.inline = false;
|
|
1504
1500
|
// Whether or not modal is being dismissed via gesture
|
|
1505
1501
|
this.gestureAnimationDismissing = false;
|
|
1506
|
-
// Whether to skip coordinate-based safe-area detection (for fullscreen phone modals)
|
|
1507
|
-
this.skipSafeAreaCoordinateDetection = false;
|
|
1508
|
-
// Track previous safe-area state to avoid redundant DOM writes
|
|
1509
|
-
this.prevSafeAreaState = { top: false, bottom: false, left: false, right: false };
|
|
1510
1502
|
this.presented = false;
|
|
1511
1503
|
/** @internal */
|
|
1512
1504
|
this.hasController = false;
|
|
@@ -1697,10 +1689,7 @@ const Modal = class {
|
|
|
1697
1689
|
}
|
|
1698
1690
|
}
|
|
1699
1691
|
onWindowResize() {
|
|
1700
|
-
//
|
|
1701
|
-
this.cachedSafeAreas = undefined;
|
|
1702
|
-
this.updateSafeAreaOverrides();
|
|
1703
|
-
// Only handle view transition for iOS card modals when no custom animations are provided
|
|
1692
|
+
// Only handle resize for iOS card modals when no custom animations are provided
|
|
1704
1693
|
if (ionicGlobal.getIonMode(this) !== 'ios' || !this.presentingElement || this.enterAnimation || this.leaveAnimation) {
|
|
1705
1694
|
return;
|
|
1706
1695
|
}
|
|
@@ -1882,8 +1871,6 @@ const Modal = class {
|
|
|
1882
1871
|
else if (!this.keepContentsMounted) {
|
|
1883
1872
|
await index$4.waitForMount();
|
|
1884
1873
|
}
|
|
1885
|
-
// Predict safe-area needs based on modal configuration to avoid visual snap
|
|
1886
|
-
this.setInitialSafeAreaOverrides(presentingElement);
|
|
1887
1874
|
index$3.writeTask(() => this.el.classList.add('show-modal'));
|
|
1888
1875
|
const hasCardModal = presentingElement !== undefined;
|
|
1889
1876
|
/**
|
|
@@ -1945,8 +1932,6 @@ const Modal = class {
|
|
|
1945
1932
|
else if (hasCardModal) {
|
|
1946
1933
|
this.initSwipeToClose();
|
|
1947
1934
|
}
|
|
1948
|
-
// Now that animation is complete, update safe-area based on actual position
|
|
1949
|
-
this.updateSafeAreaOverrides();
|
|
1950
1935
|
// Initialize view transition listener for iOS card modals
|
|
1951
1936
|
this.initViewTransitionListener();
|
|
1952
1937
|
// Initialize parent removal observer
|
|
@@ -1998,7 +1983,7 @@ const Modal = class {
|
|
|
1998
1983
|
await this.dismiss(undefined, overlays.GESTURE);
|
|
1999
1984
|
this.gestureAnimationDismissing = false;
|
|
2000
1985
|
});
|
|
2001
|
-
}
|
|
1986
|
+
});
|
|
2002
1987
|
this.gesture.enable(true);
|
|
2003
1988
|
}
|
|
2004
1989
|
initSheetGesture() {
|
|
@@ -2019,8 +2004,7 @@ const Modal = class {
|
|
|
2019
2004
|
this.currentBreakpoint = breakpoint;
|
|
2020
2005
|
this.ionBreakpointDidChange.emit({ breakpoint });
|
|
2021
2006
|
}
|
|
2022
|
-
|
|
2023
|
-
}, () => this.updateSafeAreaOverrides());
|
|
2007
|
+
});
|
|
2024
2008
|
this.gesture = gesture;
|
|
2025
2009
|
this.moveSheetToBreakpoint = moveSheetToBreakpoint;
|
|
2026
2010
|
this.gesture.enable(true);
|
|
@@ -2098,161 +2082,6 @@ const Modal = class {
|
|
|
2098
2082
|
// Clear the cached reference
|
|
2099
2083
|
this.cachedPageParent = undefined;
|
|
2100
2084
|
}
|
|
2101
|
-
/**
|
|
2102
|
-
* Sets initial safe-area overrides based on modal configuration before
|
|
2103
|
-
* the modal becomes visible. This predicts whether the modal will touch
|
|
2104
|
-
* screen edges to avoid a visual snap after animation completes.
|
|
2105
|
-
*/
|
|
2106
|
-
setInitialSafeAreaOverrides(presentingElement) {
|
|
2107
|
-
const style = this.el.style;
|
|
2108
|
-
const mode = ionicGlobal.getIonMode(this);
|
|
2109
|
-
const isSheetModal = this.breakpoints !== undefined && this.initialBreakpoint !== undefined;
|
|
2110
|
-
// Card modals only exist in iOS mode - in MD mode, presentingElement is ignored
|
|
2111
|
-
const isCardModal = presentingElement !== undefined && mode === 'ios';
|
|
2112
|
-
const isTablet = window.innerWidth >= 768;
|
|
2113
|
-
// Sheet modals always touch bottom edge, never top/left/right
|
|
2114
|
-
if (isSheetModal) {
|
|
2115
|
-
style.setProperty('--ion-safe-area-top', '0px');
|
|
2116
|
-
style.setProperty('--ion-safe-area-left', '0px');
|
|
2117
|
-
style.setProperty('--ion-safe-area-right', '0px');
|
|
2118
|
-
return;
|
|
2119
|
-
}
|
|
2120
|
-
// Card modals have rounded top corners
|
|
2121
|
-
if (isCardModal) {
|
|
2122
|
-
style.setProperty('--ion-safe-area-top', '0px');
|
|
2123
|
-
if (isTablet) {
|
|
2124
|
-
// On tablets, card modals are inset from all edges
|
|
2125
|
-
this.zeroAllSafeAreas();
|
|
2126
|
-
}
|
|
2127
|
-
else {
|
|
2128
|
-
// On phones, card modals still extend to the bottom edge
|
|
2129
|
-
style.setProperty('--ion-safe-area-left', '0px');
|
|
2130
|
-
style.setProperty('--ion-safe-area-right', '0px');
|
|
2131
|
-
this.applyFullscreenSafeArea();
|
|
2132
|
-
}
|
|
2133
|
-
return;
|
|
2134
|
-
}
|
|
2135
|
-
// Phone-sized fullscreen modals inherit safe areas and use wrapper padding
|
|
2136
|
-
if (!isTablet) {
|
|
2137
|
-
this.applyFullscreenSafeArea();
|
|
2138
|
-
return;
|
|
2139
|
-
}
|
|
2140
|
-
// Check if tablet modal is fullscreen via CSS custom properties
|
|
2141
|
-
const computedStyle = getComputedStyle(this.el);
|
|
2142
|
-
const width = computedStyle.getPropertyValue('--width').trim();
|
|
2143
|
-
const height = computedStyle.getPropertyValue('--height').trim();
|
|
2144
|
-
const isFullscreen = width === '100%' && height === '100%';
|
|
2145
|
-
if (isFullscreen) {
|
|
2146
|
-
this.applyFullscreenSafeArea();
|
|
2147
|
-
}
|
|
2148
|
-
else {
|
|
2149
|
-
// Centered dialog doesn't touch edges
|
|
2150
|
-
this.zeroAllSafeAreas();
|
|
2151
|
-
}
|
|
2152
|
-
}
|
|
2153
|
-
/**
|
|
2154
|
-
* Applies safe-area handling for fullscreen modals.
|
|
2155
|
-
* Adds wrapper padding when no footer is present to prevent
|
|
2156
|
-
* content from overlapping system navigation areas.
|
|
2157
|
-
*/
|
|
2158
|
-
applyFullscreenSafeArea() {
|
|
2159
|
-
this.skipSafeAreaCoordinateDetection = true;
|
|
2160
|
-
this.updateFooterPadding();
|
|
2161
|
-
// Watch for dynamic footer additions/removals (e.g., async data loading)
|
|
2162
|
-
if (!this.footerObserver) {
|
|
2163
|
-
this.footerObserver = new MutationObserver(() => this.updateFooterPadding());
|
|
2164
|
-
this.footerObserver.observe(this.el, { childList: true, subtree: true });
|
|
2165
|
-
}
|
|
2166
|
-
}
|
|
2167
|
-
/**
|
|
2168
|
-
* Updates wrapper padding based on footer presence.
|
|
2169
|
-
* Called initially and when footer is dynamically added/removed.
|
|
2170
|
-
*/
|
|
2171
|
-
updateFooterPadding() {
|
|
2172
|
-
if (!this.wrapperEl)
|
|
2173
|
-
return;
|
|
2174
|
-
const hasFooter = this.el.querySelector('ion-footer') !== null;
|
|
2175
|
-
if (hasFooter) {
|
|
2176
|
-
this.wrapperEl.style.removeProperty('padding-bottom');
|
|
2177
|
-
this.wrapperEl.style.removeProperty('box-sizing');
|
|
2178
|
-
}
|
|
2179
|
-
else {
|
|
2180
|
-
this.wrapperEl.style.setProperty('padding-bottom', 'var(--ion-safe-area-bottom, 0px)');
|
|
2181
|
-
this.wrapperEl.style.setProperty('box-sizing', 'border-box');
|
|
2182
|
-
}
|
|
2183
|
-
}
|
|
2184
|
-
/**
|
|
2185
|
-
* Sets all safe-area CSS variables to 0px for modals that
|
|
2186
|
-
* don't touch screen edges.
|
|
2187
|
-
*/
|
|
2188
|
-
zeroAllSafeAreas() {
|
|
2189
|
-
const style = this.el.style;
|
|
2190
|
-
style.setProperty('--ion-safe-area-top', '0px');
|
|
2191
|
-
style.setProperty('--ion-safe-area-bottom', '0px');
|
|
2192
|
-
style.setProperty('--ion-safe-area-left', '0px');
|
|
2193
|
-
style.setProperty('--ion-safe-area-right', '0px');
|
|
2194
|
-
}
|
|
2195
|
-
/**
|
|
2196
|
-
* Gets the root safe-area values from the document element.
|
|
2197
|
-
* Uses cached values during gestures to avoid getComputedStyle calls.
|
|
2198
|
-
*/
|
|
2199
|
-
getSafeAreaValues() {
|
|
2200
|
-
if (!this.cachedSafeAreas) {
|
|
2201
|
-
const rootStyle = getComputedStyle(document.documentElement);
|
|
2202
|
-
this.cachedSafeAreas = {
|
|
2203
|
-
top: parseFloat(rootStyle.getPropertyValue('--ion-safe-area-top')) || 0,
|
|
2204
|
-
bottom: parseFloat(rootStyle.getPropertyValue('--ion-safe-area-bottom')) || 0,
|
|
2205
|
-
left: parseFloat(rootStyle.getPropertyValue('--ion-safe-area-left')) || 0,
|
|
2206
|
-
right: parseFloat(rootStyle.getPropertyValue('--ion-safe-area-right')) || 0,
|
|
2207
|
-
};
|
|
2208
|
-
}
|
|
2209
|
-
return this.cachedSafeAreas;
|
|
2210
|
-
}
|
|
2211
|
-
/**
|
|
2212
|
-
* Updates safe-area CSS variable overrides based on whether the modal
|
|
2213
|
-
* extends into each safe-area region. Called after animation
|
|
2214
|
-
* and during gestures to handle dynamic position changes.
|
|
2215
|
-
*
|
|
2216
|
-
* Optimized to avoid redundant DOM writes by tracking previous state.
|
|
2217
|
-
*/
|
|
2218
|
-
updateSafeAreaOverrides() {
|
|
2219
|
-
if (this.skipSafeAreaCoordinateDetection) {
|
|
2220
|
-
return;
|
|
2221
|
-
}
|
|
2222
|
-
const wrapper = this.wrapperEl;
|
|
2223
|
-
if (!wrapper) {
|
|
2224
|
-
return;
|
|
2225
|
-
}
|
|
2226
|
-
const rect = wrapper.getBoundingClientRect();
|
|
2227
|
-
const safeAreas = this.getSafeAreaValues();
|
|
2228
|
-
const extendsIntoTop = rect.top < safeAreas.top;
|
|
2229
|
-
const extendsIntoBottom = rect.bottom > window.innerHeight - safeAreas.bottom;
|
|
2230
|
-
const extendsIntoLeft = rect.left < safeAreas.left;
|
|
2231
|
-
const extendsIntoRight = rect.right > window.innerWidth - safeAreas.right;
|
|
2232
|
-
// Only update DOM when state actually changes
|
|
2233
|
-
const prev = this.prevSafeAreaState;
|
|
2234
|
-
const style = this.el.style;
|
|
2235
|
-
if (extendsIntoTop !== prev.top) {
|
|
2236
|
-
extendsIntoTop ? style.removeProperty('--ion-safe-area-top') : style.setProperty('--ion-safe-area-top', '0px');
|
|
2237
|
-
prev.top = extendsIntoTop;
|
|
2238
|
-
}
|
|
2239
|
-
if (extendsIntoBottom !== prev.bottom) {
|
|
2240
|
-
extendsIntoBottom
|
|
2241
|
-
? style.removeProperty('--ion-safe-area-bottom')
|
|
2242
|
-
: style.setProperty('--ion-safe-area-bottom', '0px');
|
|
2243
|
-
prev.bottom = extendsIntoBottom;
|
|
2244
|
-
}
|
|
2245
|
-
if (extendsIntoLeft !== prev.left) {
|
|
2246
|
-
extendsIntoLeft ? style.removeProperty('--ion-safe-area-left') : style.setProperty('--ion-safe-area-left', '0px');
|
|
2247
|
-
prev.left = extendsIntoLeft;
|
|
2248
|
-
}
|
|
2249
|
-
if (extendsIntoRight !== prev.right) {
|
|
2250
|
-
extendsIntoRight
|
|
2251
|
-
? style.removeProperty('--ion-safe-area-right')
|
|
2252
|
-
: style.setProperty('--ion-safe-area-right', '0px');
|
|
2253
|
-
prev.right = extendsIntoRight;
|
|
2254
|
-
}
|
|
2255
|
-
}
|
|
2256
2085
|
sheetOnDismiss() {
|
|
2257
2086
|
/**
|
|
2258
2087
|
* While the gesture animation is finishing
|
|
@@ -2283,7 +2112,7 @@ const Modal = class {
|
|
|
2283
2112
|
* For example, `cancel` or `backdrop`.
|
|
2284
2113
|
*/
|
|
2285
2114
|
async dismiss(data, role) {
|
|
2286
|
-
var _a
|
|
2115
|
+
var _a;
|
|
2287
2116
|
if (this.gestureAnimationDismissing && role !== overlays.GESTURE) {
|
|
2288
2117
|
return false;
|
|
2289
2118
|
}
|
|
@@ -2345,23 +2174,6 @@ const Modal = class {
|
|
|
2345
2174
|
}
|
|
2346
2175
|
this.currentBreakpoint = undefined;
|
|
2347
2176
|
this.animation = undefined;
|
|
2348
|
-
// Reset safe-area state for potential re-presentation
|
|
2349
|
-
this.skipSafeAreaCoordinateDetection = false;
|
|
2350
|
-
this.cachedSafeAreas = undefined;
|
|
2351
|
-
this.prevSafeAreaState = { top: false, bottom: false, left: false, right: false };
|
|
2352
|
-
(_b = this.footerObserver) === null || _b === void 0 ? void 0 : _b.disconnect();
|
|
2353
|
-
this.footerObserver = undefined;
|
|
2354
|
-
// Clear styles that may have been set for safe-area handling
|
|
2355
|
-
if (this.wrapperEl) {
|
|
2356
|
-
this.wrapperEl.style.removeProperty('padding-bottom');
|
|
2357
|
-
this.wrapperEl.style.removeProperty('box-sizing');
|
|
2358
|
-
}
|
|
2359
|
-
// Clear safe-area CSS variable overrides
|
|
2360
|
-
const style = this.el.style;
|
|
2361
|
-
style.removeProperty('--ion-safe-area-top');
|
|
2362
|
-
style.removeProperty('--ion-safe-area-bottom');
|
|
2363
|
-
style.removeProperty('--ion-safe-area-left');
|
|
2364
|
-
style.removeProperty('--ion-safe-area-right');
|
|
2365
2177
|
unlock();
|
|
2366
2178
|
return dismissed;
|
|
2367
2179
|
}
|
|
@@ -2611,20 +2423,20 @@ const Modal = class {
|
|
|
2611
2423
|
const isCardModal = presentingElement !== undefined && mode === 'ios';
|
|
2612
2424
|
const isHandleCycle = handleBehavior === 'cycle';
|
|
2613
2425
|
const isSheetModalWithHandle = isSheetModal && showHandle;
|
|
2614
|
-
return (index$3.h(index$3.Host, Object.assign({ key: '
|
|
2426
|
+
return (index$3.h(index$3.Host, Object.assign({ key: '87328006ea6c75ebc518ace300438492a567223e', "no-router": true,
|
|
2615
2427
|
// Allow the modal to be navigable when the handle is focusable
|
|
2616
2428
|
tabIndex: isHandleCycle && isSheetModalWithHandle ? 0 : -1 }, htmlAttributes, { style: {
|
|
2617
2429
|
zIndex: `${20000 + this.overlayIndex}`,
|
|
2618
|
-
}, class: Object.assign({ [mode]: true, ['modal-default']: !isCardModal && !isSheetModal, [`modal-card`]: isCardModal, [`modal-sheet`]: isSheetModal, [`modal-no-expand-scroll`]: isSheetModal && !expandToScroll, 'overlay-hidden': true, [overlays.FOCUS_TRAP_DISABLE_CLASS]: focusTrap === false }, theme.getClassMap(this.cssClass)), onIonBackdropTap: this.onBackdropTap, onIonModalDidPresent: this.onLifecycle, onIonModalWillPresent: this.onLifecycle, onIonModalWillDismiss: this.onLifecycle, onIonModalDidDismiss: this.onLifecycle, onFocus: this.onModalFocus }), index$3.h("ion-backdrop", { key: '
|
|
2430
|
+
}, class: Object.assign({ [mode]: true, ['modal-default']: !isCardModal && !isSheetModal, [`modal-card`]: isCardModal, [`modal-sheet`]: isSheetModal, [`modal-no-expand-scroll`]: isSheetModal && !expandToScroll, 'overlay-hidden': true, [overlays.FOCUS_TRAP_DISABLE_CLASS]: focusTrap === false }, theme.getClassMap(this.cssClass)), onIonBackdropTap: this.onBackdropTap, onIonModalDidPresent: this.onLifecycle, onIonModalWillPresent: this.onLifecycle, onIonModalWillDismiss: this.onLifecycle, onIonModalDidDismiss: this.onLifecycle, onFocus: this.onModalFocus }), index$3.h("ion-backdrop", { key: 'ee94ff8e09b691dd4ad4e4db1720f06bc3c5a469', ref: (el) => (this.backdropEl = el), visible: this.showBackdrop, tappable: this.backdropDismiss, part: "backdrop" }), mode === 'ios' && index$3.h("div", { key: 'bffd69b4635c22d9f249725bd952c1e93d5615c7', class: "modal-shadow" }), index$3.h("div", Object.assign({ key: '1d394d3c68916e464ff1fbf5242419f4a3d3cca1',
|
|
2619
2431
|
/*
|
|
2620
2432
|
role and aria-modal must be used on the
|
|
2621
2433
|
same element. They must also be set inside the
|
|
2622
2434
|
shadow DOM otherwise ion-button will not be highlighted
|
|
2623
2435
|
when using VoiceOver: https://bugs.webkit.org/show_bug.cgi?id=247134
|
|
2624
2436
|
*/
|
|
2625
|
-
role: "dialog" }, inheritedAttributes, { "aria-modal": "true", class: "modal-wrapper ion-overlay-wrapper", part: "content", ref: (el) => (this.wrapperEl = el) }), showHandle && (index$3.h("button", { key: '
|
|
2437
|
+
role: "dialog" }, inheritedAttributes, { "aria-modal": "true", class: "modal-wrapper ion-overlay-wrapper", part: "content", ref: (el) => (this.wrapperEl = el) }), showHandle && (index$3.h("button", { key: '2dcf58792018e557e0c323baad2d672bc99c0bb1', class: "modal-handle",
|
|
2626
2438
|
// Prevents the handle from receiving keyboard focus when it does not cycle
|
|
2627
|
-
tabIndex: !isHandleCycle ? -1 : 0, "aria-label": "Activate to adjust the size of the dialog overlaying the screen", onClick: isHandleCycle ? this.onHandleClick : undefined, part: "handle", ref: (el) => (this.dragHandleEl = el) })), index$3.h("slot", { key: '
|
|
2439
|
+
tabIndex: !isHandleCycle ? -1 : 0, "aria-label": "Activate to adjust the size of the dialog overlaying the screen", onClick: isHandleCycle ? this.onHandleClick : undefined, part: "handle", ref: (el) => (this.dragHandleEl = el) })), index$3.h("slot", { key: '44164b1e8710c3895400ad9f44ecd99873874ad5', onSlotchange: this.onSlotChange }))));
|
|
2628
2440
|
}
|
|
2629
2441
|
get el() { return index$3.getElement(this); }
|
|
2630
2442
|
static get watchers() { return {
|