@ionic/core 8.7.17-dev.11767636336.113b441d → 8.7.17-dev.11767639327.19c404a6
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-tab-bar.js +3 -17
- package/components/modal.js +127 -11
- package/components/popover.js +60 -10
- package/dist/cjs/ion-modal.cjs.entry.js +127 -11
- package/dist/cjs/ion-popover.cjs.entry.js +60 -10
- package/dist/cjs/ion-tab-bar_2.cjs.entry.js +3 -17
- package/dist/collection/components/modal/gestures/sheet.js +3 -1
- package/dist/collection/components/modal/gestures/swipe-to-close.js +3 -1
- package/dist/collection/components/modal/modal.ios.css +0 -4
- package/dist/collection/components/modal/modal.js +119 -7
- package/dist/collection/components/modal/modal.md.css +0 -4
- package/dist/collection/components/popover/animations/ios.enter.js +21 -5
- package/dist/collection/components/popover/animations/md.enter.js +20 -4
- package/dist/collection/components/popover/utils.js +19 -1
- package/dist/collection/components/tab-bar/tab-bar.js +3 -17
- package/dist/docs.json +1 -1
- package/dist/esm/ion-modal.entry.js +127 -11
- package/dist/esm/ion-popover.entry.js +60 -10
- package/dist/esm/ion-tab-bar_2.entry.js +3 -17
- package/dist/ionic/ionic.esm.js +1 -1
- package/dist/ionic/p-301ad219.entry.js +4 -0
- package/dist/ionic/p-71fa7adc.entry.js +4 -0
- package/dist/ionic/p-7268efa5.entry.js +4 -0
- 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 +24 -0
- package/dist/types/components/popover/utils.d.ts +2 -0
- package/dist/types/components/tab-bar/tab-bar.d.ts +0 -1
- package/hydrate/index.js +190 -38
- package/hydrate/index.mjs +190 -38
- package/package.json +1 -1
- package/dist/ionic/p-0d0eb444.entry.js +0 -4
- package/dist/ionic/p-91840a80.entry.js +0 -4
- package/dist/ionic/p-f9061316.entry.js +0 -4
package/hydrate/index.js
CHANGED
|
@@ -21533,7 +21533,7 @@ const calculateSpringStep = (t) => {
|
|
|
21533
21533
|
const SwipeToCloseDefaults = {
|
|
21534
21534
|
MIN_PRESENTING_SCALE: 0.915,
|
|
21535
21535
|
};
|
|
21536
|
-
const createSwipeToCloseGesture = (el, animation, statusBarStyle, onDismiss) => {
|
|
21536
|
+
const createSwipeToCloseGesture = (el, animation, statusBarStyle, onDismiss, onGestureMove) => {
|
|
21537
21537
|
/**
|
|
21538
21538
|
* The step value at which a card modal
|
|
21539
21539
|
* is eligible for dismissing via gesture.
|
|
@@ -21690,6 +21690,8 @@ const createSwipeToCloseGesture = (el, animation, statusBarStyle, onDismiss) =>
|
|
|
21690
21690
|
const processedStep = isAttemptingDismissWithCanDismiss ? calculateSpringStep(step / maxStep) : step;
|
|
21691
21691
|
const clampedStep = clamp(0.0001, processedStep, maxStep);
|
|
21692
21692
|
animation.progressStep(clampedStep);
|
|
21693
|
+
// Notify modal of position change for safe-area updates
|
|
21694
|
+
onGestureMove === null || onGestureMove === void 0 ? void 0 : onGestureMove();
|
|
21693
21695
|
/**
|
|
21694
21696
|
* When swiping down half way, the status bar style
|
|
21695
21697
|
* should be reset to its default value.
|
|
@@ -22233,7 +22235,7 @@ const mdLeaveAnimation$2 = (baseEl, opts) => {
|
|
|
22233
22235
|
return baseAnimation;
|
|
22234
22236
|
};
|
|
22235
22237
|
|
|
22236
|
-
const createSheetGesture = (baseEl, backdropEl, wrapperEl, initialBreakpoint, backdropBreakpoint, animation, breakpoints = [], expandToScroll, getCurrentBreakpoint, onDismiss, onBreakpointChange) => {
|
|
22238
|
+
const createSheetGesture = (baseEl, backdropEl, wrapperEl, initialBreakpoint, backdropBreakpoint, animation, breakpoints = [], expandToScroll, getCurrentBreakpoint, onDismiss, onBreakpointChange, onGestureMove) => {
|
|
22237
22239
|
// Defaults for the sheet swipe animation
|
|
22238
22240
|
const defaultBackdrop = [
|
|
22239
22241
|
{ offset: 0, opacity: 'var(--backdrop-opacity)' },
|
|
@@ -22564,6 +22566,8 @@ const createSheetGesture = (baseEl, backdropEl, wrapperEl, initialBreakpoint, ba
|
|
|
22564
22566
|
: step;
|
|
22565
22567
|
offset = clamp(0.0001, processedStep, maxStep);
|
|
22566
22568
|
animation.progressStep(offset);
|
|
22569
|
+
// Notify modal of position change for safe-area updates
|
|
22570
|
+
onGestureMove === null || onGestureMove === void 0 ? void 0 : onGestureMove();
|
|
22567
22571
|
};
|
|
22568
22572
|
const onEnd = (detail) => {
|
|
22569
22573
|
/**
|
|
@@ -22758,9 +22762,9 @@ const createSheetGesture = (baseEl, backdropEl, wrapperEl, initialBreakpoint, ba
|
|
|
22758
22762
|
};
|
|
22759
22763
|
};
|
|
22760
22764
|
|
|
22761
|
-
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
|
|
22765
|
+
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}";
|
|
22762
22766
|
|
|
22763
|
-
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
|
|
22767
|
+
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}";
|
|
22764
22768
|
|
|
22765
22769
|
// TODO(FW-2832): types
|
|
22766
22770
|
/**
|
|
@@ -22793,6 +22797,8 @@ class Modal {
|
|
|
22793
22797
|
this.inline = false;
|
|
22794
22798
|
// Whether or not modal is being dismissed via gesture
|
|
22795
22799
|
this.gestureAnimationDismissing = false;
|
|
22800
|
+
// Whether to skip coordinate-based safe-area detection (for fullscreen phone modals)
|
|
22801
|
+
this.skipSafeAreaCoordinateDetection = false;
|
|
22796
22802
|
this.presented = false;
|
|
22797
22803
|
/** @internal */
|
|
22798
22804
|
this.hasController = false;
|
|
@@ -22983,7 +22989,9 @@ class Modal {
|
|
|
22983
22989
|
}
|
|
22984
22990
|
}
|
|
22985
22991
|
onWindowResize() {
|
|
22986
|
-
//
|
|
22992
|
+
// Update safe-area overrides for all modal types on resize
|
|
22993
|
+
this.updateSafeAreaOverrides();
|
|
22994
|
+
// Only handle view transition for iOS card modals when no custom animations are provided
|
|
22987
22995
|
if (getIonMode$1(this) !== 'ios' || !this.presentingElement || this.enterAnimation || this.leaveAnimation) {
|
|
22988
22996
|
return;
|
|
22989
22997
|
}
|
|
@@ -23165,6 +23173,8 @@ class Modal {
|
|
|
23165
23173
|
else if (!this.keepContentsMounted) {
|
|
23166
23174
|
await waitForMount();
|
|
23167
23175
|
}
|
|
23176
|
+
// Predict safe-area needs based on modal configuration to avoid visual snap
|
|
23177
|
+
this.setInitialSafeAreaOverrides(presentingElement);
|
|
23168
23178
|
writeTask(() => this.el.classList.add('show-modal'));
|
|
23169
23179
|
const hasCardModal = presentingElement !== undefined;
|
|
23170
23180
|
/**
|
|
@@ -23226,6 +23236,8 @@ class Modal {
|
|
|
23226
23236
|
else if (hasCardModal) {
|
|
23227
23237
|
this.initSwipeToClose();
|
|
23228
23238
|
}
|
|
23239
|
+
// Now that animation is complete, update safe-area based on actual position
|
|
23240
|
+
this.updateSafeAreaOverrides();
|
|
23229
23241
|
// Initialize view transition listener for iOS card modals
|
|
23230
23242
|
this.initViewTransitionListener();
|
|
23231
23243
|
// Initialize parent removal observer
|
|
@@ -23277,7 +23289,7 @@ class Modal {
|
|
|
23277
23289
|
await this.dismiss(undefined, GESTURE);
|
|
23278
23290
|
this.gestureAnimationDismissing = false;
|
|
23279
23291
|
});
|
|
23280
|
-
});
|
|
23292
|
+
}, () => this.updateSafeAreaOverrides());
|
|
23281
23293
|
this.gesture.enable(true);
|
|
23282
23294
|
}
|
|
23283
23295
|
initSheetGesture() {
|
|
@@ -23298,7 +23310,8 @@ class Modal {
|
|
|
23298
23310
|
this.currentBreakpoint = breakpoint;
|
|
23299
23311
|
this.ionBreakpointDidChange.emit({ breakpoint });
|
|
23300
23312
|
}
|
|
23301
|
-
|
|
23313
|
+
this.updateSafeAreaOverrides();
|
|
23314
|
+
}, () => this.updateSafeAreaOverrides());
|
|
23302
23315
|
this.gesture = gesture;
|
|
23303
23316
|
this.moveSheetToBreakpoint = moveSheetToBreakpoint;
|
|
23304
23317
|
this.gesture.enable(true);
|
|
@@ -23376,6 +23389,107 @@ class Modal {
|
|
|
23376
23389
|
// Clear the cached reference
|
|
23377
23390
|
this.cachedPageParent = undefined;
|
|
23378
23391
|
}
|
|
23392
|
+
/**
|
|
23393
|
+
* Sets initial safe-area overrides based on modal configuration before
|
|
23394
|
+
* the modal becomes visible. This predicts whether the modal will touch
|
|
23395
|
+
* screen edges to avoid a visual snap after animation completes.
|
|
23396
|
+
*/
|
|
23397
|
+
setInitialSafeAreaOverrides(presentingElement) {
|
|
23398
|
+
const style = this.el.style;
|
|
23399
|
+
const isSheetModal = this.breakpoints !== undefined && this.initialBreakpoint !== undefined;
|
|
23400
|
+
const isCardModal = presentingElement !== undefined;
|
|
23401
|
+
const isTablet = window.innerWidth >= 768;
|
|
23402
|
+
// Sheet modals always touch bottom edge, never top/left/right
|
|
23403
|
+
if (isSheetModal) {
|
|
23404
|
+
style.setProperty('--ion-safe-area-top', '0px');
|
|
23405
|
+
style.setProperty('--ion-safe-area-left', '0px');
|
|
23406
|
+
style.setProperty('--ion-safe-area-right', '0px');
|
|
23407
|
+
return;
|
|
23408
|
+
}
|
|
23409
|
+
// Card modals have rounded top corners
|
|
23410
|
+
if (isCardModal) {
|
|
23411
|
+
style.setProperty('--ion-safe-area-top', '0px');
|
|
23412
|
+
if (isTablet) {
|
|
23413
|
+
// On tablets, card modals are inset from all edges
|
|
23414
|
+
this.zeroAllSafeAreas();
|
|
23415
|
+
}
|
|
23416
|
+
else {
|
|
23417
|
+
// On phones, card modals still extend to the bottom edge
|
|
23418
|
+
style.setProperty('--ion-safe-area-left', '0px');
|
|
23419
|
+
style.setProperty('--ion-safe-area-right', '0px');
|
|
23420
|
+
this.applyFullscreenSafeArea();
|
|
23421
|
+
}
|
|
23422
|
+
return;
|
|
23423
|
+
}
|
|
23424
|
+
// Phone-sized fullscreen modals inherit safe areas and use wrapper padding
|
|
23425
|
+
if (!isTablet) {
|
|
23426
|
+
this.applyFullscreenSafeArea();
|
|
23427
|
+
return;
|
|
23428
|
+
}
|
|
23429
|
+
// Check if tablet modal is fullscreen via CSS custom properties
|
|
23430
|
+
const computedStyle = getComputedStyle(this.el);
|
|
23431
|
+
const width = computedStyle.getPropertyValue('--width').trim();
|
|
23432
|
+
const height = computedStyle.getPropertyValue('--height').trim();
|
|
23433
|
+
const isFullscreen = width === '100%' && height === '100%';
|
|
23434
|
+
if (isFullscreen) {
|
|
23435
|
+
this.applyFullscreenSafeArea();
|
|
23436
|
+
}
|
|
23437
|
+
else {
|
|
23438
|
+
// Centered dialog doesn't touch edges
|
|
23439
|
+
this.zeroAllSafeAreas();
|
|
23440
|
+
}
|
|
23441
|
+
}
|
|
23442
|
+
/**
|
|
23443
|
+
* Applies safe-area handling for fullscreen modals.
|
|
23444
|
+
* Adds wrapper padding when no footer is present to prevent
|
|
23445
|
+
* content from overlapping system navigation areas.
|
|
23446
|
+
*/
|
|
23447
|
+
applyFullscreenSafeArea() {
|
|
23448
|
+
this.skipSafeAreaCoordinateDetection = true;
|
|
23449
|
+
const hasFooter = this.el.querySelector('ion-footer') !== null;
|
|
23450
|
+
if (!hasFooter && this.wrapperEl) {
|
|
23451
|
+
this.wrapperEl.style.setProperty('padding-bottom', 'var(--ion-safe-area-bottom, 0px)');
|
|
23452
|
+
this.wrapperEl.style.setProperty('box-sizing', 'border-box');
|
|
23453
|
+
}
|
|
23454
|
+
}
|
|
23455
|
+
/**
|
|
23456
|
+
* Sets all safe-area CSS variables to 0px for modals that
|
|
23457
|
+
* don't touch screen edges.
|
|
23458
|
+
*/
|
|
23459
|
+
zeroAllSafeAreas() {
|
|
23460
|
+
const style = this.el.style;
|
|
23461
|
+
style.setProperty('--ion-safe-area-top', '0px');
|
|
23462
|
+
style.setProperty('--ion-safe-area-bottom', '0px');
|
|
23463
|
+
style.setProperty('--ion-safe-area-left', '0px');
|
|
23464
|
+
style.setProperty('--ion-safe-area-right', '0px');
|
|
23465
|
+
}
|
|
23466
|
+
/**
|
|
23467
|
+
* Updates safe-area CSS variable overrides based on whether the modal
|
|
23468
|
+
* is touching each edge of the viewport. Called after animation
|
|
23469
|
+
* and during gestures to handle dynamic position changes.
|
|
23470
|
+
*/
|
|
23471
|
+
updateSafeAreaOverrides() {
|
|
23472
|
+
if (this.skipSafeAreaCoordinateDetection) {
|
|
23473
|
+
return;
|
|
23474
|
+
}
|
|
23475
|
+
const wrapper = this.wrapperEl;
|
|
23476
|
+
if (!wrapper) {
|
|
23477
|
+
return;
|
|
23478
|
+
}
|
|
23479
|
+
const rect = wrapper.getBoundingClientRect();
|
|
23480
|
+
const threshold = 2;
|
|
23481
|
+
const touchingTop = rect.top <= threshold;
|
|
23482
|
+
const touchingBottom = rect.bottom >= window.innerHeight - threshold;
|
|
23483
|
+
const touchingLeft = rect.left <= threshold;
|
|
23484
|
+
const touchingRight = rect.right >= window.innerWidth - threshold;
|
|
23485
|
+
const style = this.el.style;
|
|
23486
|
+
touchingTop ? style.removeProperty('--ion-safe-area-top') : style.setProperty('--ion-safe-area-top', '0px');
|
|
23487
|
+
touchingBottom
|
|
23488
|
+
? style.removeProperty('--ion-safe-area-bottom')
|
|
23489
|
+
: style.setProperty('--ion-safe-area-bottom', '0px');
|
|
23490
|
+
touchingLeft ? style.removeProperty('--ion-safe-area-left') : style.setProperty('--ion-safe-area-left', '0px');
|
|
23491
|
+
touchingRight ? style.removeProperty('--ion-safe-area-right') : style.setProperty('--ion-safe-area-right', '0px');
|
|
23492
|
+
}
|
|
23379
23493
|
sheetOnDismiss() {
|
|
23380
23494
|
/**
|
|
23381
23495
|
* While the gesture animation is finishing
|
|
@@ -23468,6 +23582,8 @@ class Modal {
|
|
|
23468
23582
|
}
|
|
23469
23583
|
this.currentBreakpoint = undefined;
|
|
23470
23584
|
this.animation = undefined;
|
|
23585
|
+
// Reset safe-area detection flag for potential re-presentation
|
|
23586
|
+
this.skipSafeAreaCoordinateDetection = false;
|
|
23471
23587
|
unlock();
|
|
23472
23588
|
return dismissed;
|
|
23473
23589
|
}
|
|
@@ -23717,20 +23833,20 @@ class Modal {
|
|
|
23717
23833
|
const isCardModal = presentingElement !== undefined && mode === 'ios';
|
|
23718
23834
|
const isHandleCycle = handleBehavior === 'cycle';
|
|
23719
23835
|
const isSheetModalWithHandle = isSheetModal && showHandle;
|
|
23720
|
-
return (hAsync(Host, Object.assign({ key: '
|
|
23836
|
+
return (hAsync(Host, Object.assign({ key: '6642b8a32dad449f26ac4ed60814d69afc97bf30', "no-router": true,
|
|
23721
23837
|
// Allow the modal to be navigable when the handle is focusable
|
|
23722
23838
|
tabIndex: isHandleCycle && isSheetModalWithHandle ? 0 : -1 }, htmlAttributes, { style: {
|
|
23723
23839
|
zIndex: `${20000 + this.overlayIndex}`,
|
|
23724
|
-
}, class: Object.assign({ [mode]: true, ['modal-default']: !isCardModal && !isSheetModal, [`modal-card`]: isCardModal, [`modal-sheet`]: isSheetModal, [`modal-no-expand-scroll`]: isSheetModal && !expandToScroll, 'overlay-hidden': true, [FOCUS_TRAP_DISABLE_CLASS]: focusTrap === false }, getClassMap(this.cssClass)), onIonBackdropTap: this.onBackdropTap, onIonModalDidPresent: this.onLifecycle, onIonModalWillPresent: this.onLifecycle, onIonModalWillDismiss: this.onLifecycle, onIonModalDidDismiss: this.onLifecycle, onFocus: this.onModalFocus }), hAsync("ion-backdrop", { key: '
|
|
23840
|
+
}, class: Object.assign({ [mode]: true, ['modal-default']: !isCardModal && !isSheetModal, [`modal-card`]: isCardModal, [`modal-sheet`]: isSheetModal, [`modal-no-expand-scroll`]: isSheetModal && !expandToScroll, 'overlay-hidden': true, [FOCUS_TRAP_DISABLE_CLASS]: focusTrap === false }, getClassMap(this.cssClass)), onIonBackdropTap: this.onBackdropTap, onIonModalDidPresent: this.onLifecycle, onIonModalWillPresent: this.onLifecycle, onIonModalWillDismiss: this.onLifecycle, onIonModalDidDismiss: this.onLifecycle, onFocus: this.onModalFocus }), hAsync("ion-backdrop", { key: '8adf79ea72c0f622190ff366980621067c35795b', ref: (el) => (this.backdropEl = el), visible: this.showBackdrop, tappable: this.backdropDismiss, part: "backdrop" }), mode === 'ios' && hAsync("div", { key: '34f14fcd4970c04aee3b7a5305f9f220ff377f37', class: "modal-shadow" }), hAsync("div", Object.assign({ key: 'a3a8e3df6a1cfe061bbd99503655015ca8cd416d',
|
|
23725
23841
|
/*
|
|
23726
23842
|
role and aria-modal must be used on the
|
|
23727
23843
|
same element. They must also be set inside the
|
|
23728
23844
|
shadow DOM otherwise ion-button will not be highlighted
|
|
23729
23845
|
when using VoiceOver: https://bugs.webkit.org/show_bug.cgi?id=247134
|
|
23730
23846
|
*/
|
|
23731
|
-
role: "dialog" }, inheritedAttributes, { "aria-modal": "true", class: "modal-wrapper ion-overlay-wrapper", part: "content", ref: (el) => (this.wrapperEl = el) }), showHandle && (hAsync("button", { key: '
|
|
23847
|
+
role: "dialog" }, inheritedAttributes, { "aria-modal": "true", class: "modal-wrapper ion-overlay-wrapper", part: "content", ref: (el) => (this.wrapperEl = el) }), showHandle && (hAsync("button", { key: 'a4ad2f6def8c20a36a9731553dfa5a98392151ef', class: "modal-handle",
|
|
23732
23848
|
// Prevents the handle from receiving keyboard focus when it does not cycle
|
|
23733
|
-
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) })), hAsync("slot", { key: '
|
|
23849
|
+
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) })), hAsync("slot", { key: '46fb6d94814dae4a9bcdf99387d57a17c6a6a95c', onSlotchange: this.onSlotChange }))));
|
|
23734
23850
|
}
|
|
23735
23851
|
get el() { return getElement(this); }
|
|
23736
23852
|
static get watchers() { return {
|
|
@@ -27308,6 +27424,8 @@ const calculateWindowAdjustment = (side, coordTop, coordLeft, bodyPadding, bodyW
|
|
|
27308
27424
|
let bottom;
|
|
27309
27425
|
let originX = contentOriginX;
|
|
27310
27426
|
let originY = contentOriginY;
|
|
27427
|
+
let checkSafeAreaTop = false;
|
|
27428
|
+
let checkSafeAreaBottom = false;
|
|
27311
27429
|
let checkSafeAreaLeft = false;
|
|
27312
27430
|
let checkSafeAreaRight = false;
|
|
27313
27431
|
const triggerTop = triggerCoordinates
|
|
@@ -27352,10 +27470,18 @@ const calculateWindowAdjustment = (side, coordTop, coordLeft, bodyPadding, bodyW
|
|
|
27352
27470
|
* We chose 12 here so that the popover position looks a bit nicer as
|
|
27353
27471
|
* it is not right up against the edge of the screen.
|
|
27354
27472
|
*/
|
|
27355
|
-
top = Math.max(
|
|
27473
|
+
top = Math.max(bodyPadding, triggerTop - contentHeight - triggerHeight - (arrowHeight - 1));
|
|
27356
27474
|
arrowTop = top + contentHeight;
|
|
27357
27475
|
originY = 'bottom';
|
|
27358
27476
|
addPopoverBottomClass = true;
|
|
27477
|
+
/**
|
|
27478
|
+
* If the popover is positioned near the top edge, account for safe area.
|
|
27479
|
+
* This ensures the popover doesn't overlap with status bars or notches.
|
|
27480
|
+
*/
|
|
27481
|
+
if (top <= bodyPadding + safeAreaMargin) {
|
|
27482
|
+
checkSafeAreaTop = true;
|
|
27483
|
+
top = bodyPadding;
|
|
27484
|
+
}
|
|
27359
27485
|
/**
|
|
27360
27486
|
* If not enough room for popover to appear
|
|
27361
27487
|
* above trigger, then cut it off.
|
|
@@ -27363,6 +27489,12 @@ const calculateWindowAdjustment = (side, coordTop, coordLeft, bodyPadding, bodyW
|
|
|
27363
27489
|
}
|
|
27364
27490
|
else {
|
|
27365
27491
|
bottom = bodyPadding;
|
|
27492
|
+
/**
|
|
27493
|
+
* When the popover is pinned to the bottom, account for safe area.
|
|
27494
|
+
* This ensures the popover doesn't overlap with home indicators
|
|
27495
|
+
* or navigation bars (e.g., Android API 36+ edge-to-edge).
|
|
27496
|
+
*/
|
|
27497
|
+
checkSafeAreaBottom = true;
|
|
27366
27498
|
}
|
|
27367
27499
|
}
|
|
27368
27500
|
return {
|
|
@@ -27371,6 +27503,8 @@ const calculateWindowAdjustment = (side, coordTop, coordLeft, bodyPadding, bodyW
|
|
|
27371
27503
|
bottom,
|
|
27372
27504
|
originX,
|
|
27373
27505
|
originY,
|
|
27506
|
+
checkSafeAreaTop,
|
|
27507
|
+
checkSafeAreaBottom,
|
|
27374
27508
|
checkSafeAreaLeft,
|
|
27375
27509
|
checkSafeAreaRight,
|
|
27376
27510
|
arrowTop,
|
|
@@ -27431,7 +27565,7 @@ const iosEnterAnimation$1 = (baseEl, opts) => {
|
|
|
27431
27565
|
const results = getPopoverPosition(isRTL, contentWidth, contentHeight, arrowWidth, arrowHeight, reference, side, align, defaultPosition, trigger, ev);
|
|
27432
27566
|
const padding = size === 'cover' ? 0 : POPOVER_IOS_BODY_PADDING;
|
|
27433
27567
|
const margin = size === 'cover' ? 0 : 25;
|
|
27434
|
-
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);
|
|
27568
|
+
const { originX, originY, top, left, bottom, checkSafeAreaTop, checkSafeAreaBottom, 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);
|
|
27435
27569
|
const baseAnimation = createAnimation();
|
|
27436
27570
|
const backdropAnimation = createAnimation();
|
|
27437
27571
|
const contentAnimation = createAnimation();
|
|
@@ -27461,19 +27595,35 @@ const iosEnterAnimation$1 = (baseEl, opts) => {
|
|
|
27461
27595
|
if (addPopoverBottomClass) {
|
|
27462
27596
|
baseEl.classList.add('popover-bottom');
|
|
27463
27597
|
}
|
|
27464
|
-
|
|
27465
|
-
|
|
27466
|
-
|
|
27598
|
+
/**
|
|
27599
|
+
* Safe area CSS variable adjustments.
|
|
27600
|
+
* When the popover is positioned near an edge, we add the corresponding
|
|
27601
|
+
* safe-area inset to ensure the popover doesn't overlap with system UI
|
|
27602
|
+
* (status bars, home indicators, navigation bars on Android API 36+, etc.)
|
|
27603
|
+
*/
|
|
27604
|
+
const safeAreaTop = ' + var(--ion-safe-area-top, 0)';
|
|
27605
|
+
const safeAreaBottom = ' + var(--ion-safe-area-bottom, 0)';
|
|
27467
27606
|
const safeAreaLeft = ' + var(--ion-safe-area-left, 0)';
|
|
27468
27607
|
const safeAreaRight = ' - var(--ion-safe-area-right, 0)';
|
|
27608
|
+
let topValue = `${top}px`;
|
|
27609
|
+
let bottomValue = bottom !== undefined ? `${bottom}px` : undefined;
|
|
27469
27610
|
let leftValue = `${left}px`;
|
|
27611
|
+
if (checkSafeAreaTop) {
|
|
27612
|
+
topValue = `${top}px${safeAreaTop}`;
|
|
27613
|
+
}
|
|
27614
|
+
if (checkSafeAreaBottom && bottomValue !== undefined) {
|
|
27615
|
+
bottomValue = `${bottom}px${safeAreaBottom}`;
|
|
27616
|
+
}
|
|
27470
27617
|
if (checkSafeAreaLeft) {
|
|
27471
27618
|
leftValue = `${left}px${safeAreaLeft}`;
|
|
27472
27619
|
}
|
|
27473
27620
|
if (checkSafeAreaRight) {
|
|
27474
27621
|
leftValue = `${left}px${safeAreaRight}`;
|
|
27475
27622
|
}
|
|
27476
|
-
|
|
27623
|
+
if (bottomValue !== undefined) {
|
|
27624
|
+
contentEl.style.setProperty('bottom', `calc(${bottomValue})`);
|
|
27625
|
+
}
|
|
27626
|
+
contentEl.style.setProperty('top', `calc(${topValue} + var(--offset-y, 0))`);
|
|
27477
27627
|
contentEl.style.setProperty('left', `calc(${leftValue} + var(--offset-x, 0))`);
|
|
27478
27628
|
contentEl.style.setProperty('transform-origin', `${originY} ${originX}`);
|
|
27479
27629
|
if (arrowEl !== null) {
|
|
@@ -27549,7 +27699,23 @@ const mdEnterAnimation$1 = (baseEl, opts) => {
|
|
|
27549
27699
|
};
|
|
27550
27700
|
const results = getPopoverPosition(isRTL, contentWidth, contentHeight, 0, 0, reference, side, align, defaultPosition, trigger, ev);
|
|
27551
27701
|
const padding = size === 'cover' ? 0 : POPOVER_MD_BODY_PADDING;
|
|
27552
|
-
const { originX, originY, top, left, bottom } = calculateWindowAdjustment(side, results.top, results.left, padding, bodyWidth, bodyHeight, contentWidth, contentHeight, 0, results.originX, results.originY, results.referenceCoordinates);
|
|
27702
|
+
const { originX, originY, top, left, bottom, checkSafeAreaTop, checkSafeAreaBottom } = calculateWindowAdjustment(side, results.top, results.left, padding, bodyWidth, bodyHeight, contentWidth, contentHeight, 0, results.originX, results.originY, results.referenceCoordinates);
|
|
27703
|
+
/**
|
|
27704
|
+
* Safe area CSS variable adjustments.
|
|
27705
|
+
* When the popover is positioned near an edge, we add the corresponding
|
|
27706
|
+
* safe-area inset to ensure the popover doesn't overlap with system UI
|
|
27707
|
+
* (status bars, home indicators, navigation bars on Android API 36+, etc.)
|
|
27708
|
+
*/
|
|
27709
|
+
const safeAreaTop = ' + var(--ion-safe-area-top, 0)';
|
|
27710
|
+
const safeAreaBottom = ' + var(--ion-safe-area-bottom, 0)';
|
|
27711
|
+
let topValue = `${top}px`;
|
|
27712
|
+
let bottomValue = bottom !== undefined ? `${bottom}px` : undefined;
|
|
27713
|
+
if (checkSafeAreaTop) {
|
|
27714
|
+
topValue = `${top}px${safeAreaTop}`;
|
|
27715
|
+
}
|
|
27716
|
+
if (checkSafeAreaBottom && bottomValue !== undefined) {
|
|
27717
|
+
bottomValue = `${bottom}px${safeAreaBottom}`;
|
|
27718
|
+
}
|
|
27553
27719
|
const baseAnimation = createAnimation();
|
|
27554
27720
|
const backdropAnimation = createAnimation();
|
|
27555
27721
|
const wrapperAnimation = createAnimation();
|
|
@@ -27566,13 +27732,13 @@ const mdEnterAnimation$1 = (baseEl, opts) => {
|
|
|
27566
27732
|
contentAnimation
|
|
27567
27733
|
.addElement(contentEl)
|
|
27568
27734
|
.beforeStyles({
|
|
27569
|
-
top: `calc(${
|
|
27735
|
+
top: `calc(${topValue} + var(--offset-y, 0px))`,
|
|
27570
27736
|
left: `calc(${left}px + var(--offset-x, 0px))`,
|
|
27571
27737
|
'transform-origin': `${originY} ${originX}`,
|
|
27572
27738
|
})
|
|
27573
27739
|
.beforeAddWrite(() => {
|
|
27574
|
-
if (
|
|
27575
|
-
contentEl.style.setProperty('bottom',
|
|
27740
|
+
if (bottomValue !== undefined) {
|
|
27741
|
+
contentEl.style.setProperty('bottom', `calc(${bottomValue})`);
|
|
27576
27742
|
}
|
|
27577
27743
|
})
|
|
27578
27744
|
.fromTo('transform', 'scale(0.8)', 'scale(1)');
|
|
@@ -34991,7 +35157,6 @@ class TabBar {
|
|
|
34991
35157
|
this.ionTabBarLoaded = createEvent(this, "ionTabBarLoaded", 7);
|
|
34992
35158
|
this.keyboardCtrl = null;
|
|
34993
35159
|
this.didLoad = false;
|
|
34994
|
-
this.isComponentConnected = false;
|
|
34995
35160
|
this.keyboardVisible = false;
|
|
34996
35161
|
/**
|
|
34997
35162
|
* If `true`, the tab bar will be translucent.
|
|
@@ -35026,8 +35191,7 @@ class TabBar {
|
|
|
35026
35191
|
}
|
|
35027
35192
|
}
|
|
35028
35193
|
async connectedCallback() {
|
|
35029
|
-
this.
|
|
35030
|
-
const keyboardCtrl = await createKeyboardController(async (keyboardOpen, waitForResize) => {
|
|
35194
|
+
this.keyboardCtrl = await createKeyboardController(async (keyboardOpen, waitForResize) => {
|
|
35031
35195
|
/**
|
|
35032
35196
|
* If the keyboard is hiding, then we need to wait
|
|
35033
35197
|
* for the webview to resize. Otherwise, the tab bar
|
|
@@ -35038,33 +35202,21 @@ class TabBar {
|
|
|
35038
35202
|
}
|
|
35039
35203
|
this.keyboardVisible = keyboardOpen; // trigger re-render by updating state
|
|
35040
35204
|
});
|
|
35041
|
-
/**
|
|
35042
|
-
* Destroy the keyboard controller if the component was
|
|
35043
|
-
* disconnected during async initialization to prevent memory leaks.
|
|
35044
|
-
*/
|
|
35045
|
-
if (this.isComponentConnected) {
|
|
35046
|
-
this.keyboardCtrl = keyboardCtrl;
|
|
35047
|
-
}
|
|
35048
|
-
else {
|
|
35049
|
-
keyboardCtrl.destroy();
|
|
35050
|
-
}
|
|
35051
35205
|
}
|
|
35052
35206
|
disconnectedCallback() {
|
|
35053
|
-
this.isComponentConnected = false;
|
|
35054
35207
|
if (this.keyboardCtrl) {
|
|
35055
35208
|
this.keyboardCtrl.destroy();
|
|
35056
|
-
this.keyboardCtrl = null;
|
|
35057
35209
|
}
|
|
35058
35210
|
}
|
|
35059
35211
|
render() {
|
|
35060
35212
|
const { color, translucent, keyboardVisible } = this;
|
|
35061
35213
|
const mode = getIonMode$1(this);
|
|
35062
35214
|
const shouldHide = keyboardVisible && this.el.getAttribute('slot') !== 'top';
|
|
35063
|
-
return (hAsync(Host, { key: '
|
|
35215
|
+
return (hAsync(Host, { key: '388ec37ce308035bab78d6c9a016bb616e9517a9', role: "tablist", "aria-hidden": shouldHide ? 'true' : null, class: createColorClasses$1(color, {
|
|
35064
35216
|
[mode]: true,
|
|
35065
35217
|
'tab-bar-translucent': translucent,
|
|
35066
35218
|
'tab-bar-hidden': shouldHide,
|
|
35067
|
-
}) }, hAsync("slot", { key: '
|
|
35219
|
+
}) }, hAsync("slot", { key: 'ce10ade2b86725e24f3254516483eeedd8ecb16a' })));
|
|
35068
35220
|
}
|
|
35069
35221
|
get el() { return getElement(this); }
|
|
35070
35222
|
static get watchers() { return {
|