@ionic/core 8.7.18-dev.11769546281.18b0f3ba → 8.7.18-dev.11769790854.11895f8f
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/modal.js +220 -12
- package/components/popover.js +83 -11
- package/dist/cjs/ion-modal.cjs.entry.js +220 -12
- package/dist/cjs/ion-popover.cjs.entry.js +83 -11
- 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 +215 -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 +30 -5
- package/dist/collection/components/popover/utils.js +32 -1
- package/dist/docs.json +1 -1
- package/dist/esm/ion-modal.entry.js +220 -12
- package/dist/esm/ion-popover.entry.js +83 -11
- package/dist/ionic/ionic.esm.js +1 -1
- package/dist/ionic/p-ec9ca3fe.entry.js +4 -0
- package/dist/ionic/p-ef4256eb.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 +47 -0
- package/dist/types/components/popover/utils.d.ts +2 -0
- package/hydrate/index.js +302 -22
- package/hydrate/index.mjs +302 -22
- package/package.json +1 -1
- package/dist/ionic/p-91840a80.entry.js +0 -4
- package/dist/ionic/p-f9061316.entry.js +0 -4
package/components/modal.js
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
* (C) Ionic http://ionicframework.com - MIT License
|
|
3
3
|
*/
|
|
4
4
|
import { proxyCustomElement, HTMLElement, createEvent, writeTask, h, Host } from '@stencil/core/internal/client';
|
|
5
|
+
import { w as win } from './index9.js';
|
|
5
6
|
import { a as findClosestIonContent, i as isIonContent, d as disableContentScrollY, r as resetContentScrollY, f as findIonContent, p as printIonContentErrorMsg } from './index8.js';
|
|
6
7
|
import { C as CoreDelegate, a as attachComponent, d as detachComponent } from './framework-delegate.js';
|
|
7
8
|
import { f as clamp, g as getElementRoot, r as raf, d as inheritAttributes, k as hasLazyBuild } from './helpers.js';
|
|
@@ -16,7 +17,6 @@ import { KEYBOARD_DID_OPEN } from './keyboard.js';
|
|
|
16
17
|
import { c as createAnimation } from './animation.js';
|
|
17
18
|
import { g as getTimeGivenProgression } from './cubic-bezier.js';
|
|
18
19
|
import { createGesture } from './index3.js';
|
|
19
|
-
import { w as win } from './index9.js';
|
|
20
20
|
import { d as defineCustomElement$1 } from './backdrop.js';
|
|
21
21
|
|
|
22
22
|
var Style;
|
|
@@ -246,7 +246,7 @@ const calculateSpringStep = (t) => {
|
|
|
246
246
|
const SwipeToCloseDefaults = {
|
|
247
247
|
MIN_PRESENTING_SCALE: 0.915,
|
|
248
248
|
};
|
|
249
|
-
const createSwipeToCloseGesture = (el, animation, statusBarStyle, onDismiss) => {
|
|
249
|
+
const createSwipeToCloseGesture = (el, animation, statusBarStyle, onDismiss, onGestureMove) => {
|
|
250
250
|
/**
|
|
251
251
|
* The step value at which a card modal
|
|
252
252
|
* is eligible for dismissing via gesture.
|
|
@@ -403,6 +403,8 @@ const createSwipeToCloseGesture = (el, animation, statusBarStyle, onDismiss) =>
|
|
|
403
403
|
const processedStep = isAttemptingDismissWithCanDismiss ? calculateSpringStep(step / maxStep) : step;
|
|
404
404
|
const clampedStep = clamp(0.0001, processedStep, maxStep);
|
|
405
405
|
animation.progressStep(clampedStep);
|
|
406
|
+
// Notify modal of position change for safe-area updates
|
|
407
|
+
onGestureMove === null || onGestureMove === void 0 ? void 0 : onGestureMove();
|
|
406
408
|
/**
|
|
407
409
|
* When swiping down half way, the status bar style
|
|
408
410
|
* should be reset to its default value.
|
|
@@ -946,7 +948,7 @@ const mdLeaveAnimation = (baseEl, opts) => {
|
|
|
946
948
|
return baseAnimation;
|
|
947
949
|
};
|
|
948
950
|
|
|
949
|
-
const createSheetGesture = (baseEl, backdropEl, wrapperEl, initialBreakpoint, backdropBreakpoint, animation, breakpoints = [], expandToScroll, getCurrentBreakpoint, onDismiss, onBreakpointChange) => {
|
|
951
|
+
const createSheetGesture = (baseEl, backdropEl, wrapperEl, initialBreakpoint, backdropBreakpoint, animation, breakpoints = [], expandToScroll, getCurrentBreakpoint, onDismiss, onBreakpointChange, onGestureMove) => {
|
|
950
952
|
// Defaults for the sheet swipe animation
|
|
951
953
|
const defaultBackdrop = [
|
|
952
954
|
{ offset: 0, opacity: 'var(--backdrop-opacity)' },
|
|
@@ -1277,6 +1279,8 @@ const createSheetGesture = (baseEl, backdropEl, wrapperEl, initialBreakpoint, ba
|
|
|
1277
1279
|
: step;
|
|
1278
1280
|
offset = clamp(0.0001, processedStep, maxStep);
|
|
1279
1281
|
animation.progressStep(offset);
|
|
1282
|
+
// Notify modal of position change for safe-area updates
|
|
1283
|
+
onGestureMove === null || onGestureMove === void 0 ? void 0 : onGestureMove();
|
|
1280
1284
|
};
|
|
1281
1285
|
const onEnd = (detail) => {
|
|
1282
1286
|
/**
|
|
@@ -1471,9 +1475,9 @@ const createSheetGesture = (baseEl, backdropEl, wrapperEl, initialBreakpoint, ba
|
|
|
1471
1475
|
};
|
|
1472
1476
|
};
|
|
1473
1477
|
|
|
1474
|
-
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
|
|
1478
|
+
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}";
|
|
1475
1479
|
|
|
1476
|
-
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
|
|
1480
|
+
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}";
|
|
1477
1481
|
|
|
1478
1482
|
const Modal = /*@__PURE__*/ proxyCustomElement(class Modal extends HTMLElement {
|
|
1479
1483
|
constructor(registerHost) {
|
|
@@ -1500,6 +1504,10 @@ const Modal = /*@__PURE__*/ proxyCustomElement(class Modal extends HTMLElement {
|
|
|
1500
1504
|
this.inline = false;
|
|
1501
1505
|
// Whether or not modal is being dismissed via gesture
|
|
1502
1506
|
this.gestureAnimationDismissing = false;
|
|
1507
|
+
// Whether to skip coordinate-based safe-area detection (for fullscreen phone modals)
|
|
1508
|
+
this.skipSafeAreaCoordinateDetection = false;
|
|
1509
|
+
// Track previous safe-area state to avoid redundant DOM writes
|
|
1510
|
+
this.prevSafeAreaState = { top: false, bottom: false, left: false, right: false };
|
|
1503
1511
|
this.presented = false;
|
|
1504
1512
|
/** @internal */
|
|
1505
1513
|
this.hasController = false;
|
|
@@ -1690,7 +1698,10 @@ const Modal = /*@__PURE__*/ proxyCustomElement(class Modal extends HTMLElement {
|
|
|
1690
1698
|
}
|
|
1691
1699
|
}
|
|
1692
1700
|
onWindowResize() {
|
|
1693
|
-
//
|
|
1701
|
+
// Invalidate safe-area cache on resize (device rotation may change values)
|
|
1702
|
+
this.cachedSafeAreas = undefined;
|
|
1703
|
+
this.updateSafeAreaOverrides();
|
|
1704
|
+
// Only handle view transition for iOS card modals when no custom animations are provided
|
|
1694
1705
|
if (getIonMode(this) !== 'ios' || !this.presentingElement || this.enterAnimation || this.leaveAnimation) {
|
|
1695
1706
|
return;
|
|
1696
1707
|
}
|
|
@@ -1713,6 +1724,8 @@ const Modal = /*@__PURE__*/ proxyCustomElement(class Modal extends HTMLElement {
|
|
|
1713
1724
|
this.triggerController.removeClickListener();
|
|
1714
1725
|
this.cleanupViewTransitionListener();
|
|
1715
1726
|
this.cleanupParentRemovalObserver();
|
|
1727
|
+
// Reset safe-area state to handle removal without dismiss (e.g., framework unmount)
|
|
1728
|
+
this.resetSafeAreaState();
|
|
1716
1729
|
}
|
|
1717
1730
|
componentWillLoad() {
|
|
1718
1731
|
var _a;
|
|
@@ -1872,6 +1885,8 @@ const Modal = /*@__PURE__*/ proxyCustomElement(class Modal extends HTMLElement {
|
|
|
1872
1885
|
else if (!this.keepContentsMounted) {
|
|
1873
1886
|
await waitForMount();
|
|
1874
1887
|
}
|
|
1888
|
+
// Predict safe-area needs based on modal configuration to avoid visual snap
|
|
1889
|
+
this.setInitialSafeAreaOverrides(presentingElement);
|
|
1875
1890
|
writeTask(() => this.el.classList.add('show-modal'));
|
|
1876
1891
|
const hasCardModal = presentingElement !== undefined;
|
|
1877
1892
|
/**
|
|
@@ -1933,6 +1948,8 @@ const Modal = /*@__PURE__*/ proxyCustomElement(class Modal extends HTMLElement {
|
|
|
1933
1948
|
else if (hasCardModal) {
|
|
1934
1949
|
this.initSwipeToClose();
|
|
1935
1950
|
}
|
|
1951
|
+
// Now that animation is complete, update safe-area based on actual position
|
|
1952
|
+
this.updateSafeAreaOverrides();
|
|
1936
1953
|
// Initialize view transition listener for iOS card modals
|
|
1937
1954
|
this.initViewTransitionListener();
|
|
1938
1955
|
// Initialize parent removal observer
|
|
@@ -1984,7 +2001,7 @@ const Modal = /*@__PURE__*/ proxyCustomElement(class Modal extends HTMLElement {
|
|
|
1984
2001
|
await this.dismiss(undefined, GESTURE);
|
|
1985
2002
|
this.gestureAnimationDismissing = false;
|
|
1986
2003
|
});
|
|
1987
|
-
});
|
|
2004
|
+
}, () => this.updateSafeAreaOverrides());
|
|
1988
2005
|
this.gesture.enable(true);
|
|
1989
2006
|
}
|
|
1990
2007
|
initSheetGesture() {
|
|
@@ -2005,7 +2022,8 @@ const Modal = /*@__PURE__*/ proxyCustomElement(class Modal extends HTMLElement {
|
|
|
2005
2022
|
this.currentBreakpoint = breakpoint;
|
|
2006
2023
|
this.ionBreakpointDidChange.emit({ breakpoint });
|
|
2007
2024
|
}
|
|
2008
|
-
|
|
2025
|
+
this.updateSafeAreaOverrides();
|
|
2026
|
+
}, () => this.updateSafeAreaOverrides());
|
|
2009
2027
|
this.gesture = gesture;
|
|
2010
2028
|
this.moveSheetToBreakpoint = moveSheetToBreakpoint;
|
|
2011
2029
|
this.gesture.enable(true);
|
|
@@ -2083,6 +2101,194 @@ const Modal = /*@__PURE__*/ proxyCustomElement(class Modal extends HTMLElement {
|
|
|
2083
2101
|
// Clear the cached reference
|
|
2084
2102
|
this.cachedPageParent = undefined;
|
|
2085
2103
|
}
|
|
2104
|
+
/**
|
|
2105
|
+
* Sets initial safe-area overrides based on modal configuration before
|
|
2106
|
+
* the modal becomes visible. This predicts whether the modal will touch
|
|
2107
|
+
* screen edges to avoid a visual snap after animation completes.
|
|
2108
|
+
*/
|
|
2109
|
+
setInitialSafeAreaOverrides(presentingElement) {
|
|
2110
|
+
const style = this.el.style;
|
|
2111
|
+
const mode = getIonMode(this);
|
|
2112
|
+
const isSheetModal = this.breakpoints !== undefined && this.initialBreakpoint !== undefined;
|
|
2113
|
+
// Card modals only exist in iOS mode - in MD mode, presentingElement is ignored
|
|
2114
|
+
const isCardModal = presentingElement !== undefined && mode === 'ios';
|
|
2115
|
+
const isTablet = window.innerWidth >= 768;
|
|
2116
|
+
// Sheet modals always touch bottom edge, never top/left/right
|
|
2117
|
+
if (isSheetModal) {
|
|
2118
|
+
style.setProperty('--ion-safe-area-top', '0px');
|
|
2119
|
+
style.setProperty('--ion-safe-area-left', '0px');
|
|
2120
|
+
style.setProperty('--ion-safe-area-right', '0px');
|
|
2121
|
+
return;
|
|
2122
|
+
}
|
|
2123
|
+
// Card modals have rounded top corners
|
|
2124
|
+
if (isCardModal) {
|
|
2125
|
+
style.setProperty('--ion-safe-area-top', '0px');
|
|
2126
|
+
if (isTablet) {
|
|
2127
|
+
// On tablets, card modals are inset from all edges
|
|
2128
|
+
this.zeroAllSafeAreas();
|
|
2129
|
+
}
|
|
2130
|
+
else {
|
|
2131
|
+
// On phones, card modals still extend to the bottom edge
|
|
2132
|
+
style.setProperty('--ion-safe-area-left', '0px');
|
|
2133
|
+
style.setProperty('--ion-safe-area-right', '0px');
|
|
2134
|
+
this.applyFullscreenSafeArea();
|
|
2135
|
+
}
|
|
2136
|
+
return;
|
|
2137
|
+
}
|
|
2138
|
+
// Check if modal is fullscreen via CSS custom properties
|
|
2139
|
+
// This applies to both phone and tablet sizes - custom modals may have
|
|
2140
|
+
// non-fullscreen dimensions even on phones (e.g., --height: 70%)
|
|
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 if (isTablet) {
|
|
2149
|
+
// Centered dialog on tablet doesn't touch edges
|
|
2150
|
+
this.zeroAllSafeAreas();
|
|
2151
|
+
}
|
|
2152
|
+
else ;
|
|
2153
|
+
}
|
|
2154
|
+
/**
|
|
2155
|
+
* Applies safe-area handling for fullscreen modals.
|
|
2156
|
+
* Adds wrapper padding when no footer is present to prevent
|
|
2157
|
+
* content from overlapping system navigation areas.
|
|
2158
|
+
*/
|
|
2159
|
+
applyFullscreenSafeArea() {
|
|
2160
|
+
this.skipSafeAreaCoordinateDetection = true;
|
|
2161
|
+
this.updateFooterPadding();
|
|
2162
|
+
// Watch for dynamic footer additions/removals (e.g., async data loading)
|
|
2163
|
+
// Use subtree:true to support wrapped footers in framework components
|
|
2164
|
+
// (e.g., <my-footer><ion-footer>...</ion-footer></my-footer>)
|
|
2165
|
+
if (!this.footerObserver && win !== undefined && 'MutationObserver' in win) {
|
|
2166
|
+
this.footerObserver = new MutationObserver(() => this.updateFooterPadding());
|
|
2167
|
+
this.footerObserver.observe(this.el, { childList: true, subtree: true });
|
|
2168
|
+
}
|
|
2169
|
+
}
|
|
2170
|
+
/**
|
|
2171
|
+
* Updates wrapper and shadow padding based on footer presence.
|
|
2172
|
+
* Called initially and when footer is dynamically added/removed.
|
|
2173
|
+
* Both elements must be styled identically to prevent visual mismatches.
|
|
2174
|
+
*/
|
|
2175
|
+
updateFooterPadding() {
|
|
2176
|
+
if (!this.wrapperEl)
|
|
2177
|
+
return;
|
|
2178
|
+
const hasFooter = this.el.querySelector('ion-footer') !== null;
|
|
2179
|
+
// Apply to both wrapper and shadow to keep them in sync
|
|
2180
|
+
const elements = [this.wrapperEl, this.shadowEl].filter(Boolean);
|
|
2181
|
+
if (hasFooter) {
|
|
2182
|
+
elements.forEach((el) => {
|
|
2183
|
+
el.style.removeProperty('padding-bottom');
|
|
2184
|
+
el.style.removeProperty('box-sizing');
|
|
2185
|
+
});
|
|
2186
|
+
}
|
|
2187
|
+
else {
|
|
2188
|
+
elements.forEach((el) => {
|
|
2189
|
+
el.style.setProperty('padding-bottom', 'var(--ion-safe-area-bottom, 0px)');
|
|
2190
|
+
el.style.setProperty('box-sizing', 'border-box');
|
|
2191
|
+
});
|
|
2192
|
+
}
|
|
2193
|
+
}
|
|
2194
|
+
/**
|
|
2195
|
+
* Sets all safe-area CSS variables to 0px for modals that
|
|
2196
|
+
* don't touch screen edges.
|
|
2197
|
+
*/
|
|
2198
|
+
zeroAllSafeAreas() {
|
|
2199
|
+
const style = this.el.style;
|
|
2200
|
+
style.setProperty('--ion-safe-area-top', '0px');
|
|
2201
|
+
style.setProperty('--ion-safe-area-bottom', '0px');
|
|
2202
|
+
style.setProperty('--ion-safe-area-left', '0px');
|
|
2203
|
+
style.setProperty('--ion-safe-area-right', '0px');
|
|
2204
|
+
}
|
|
2205
|
+
/**
|
|
2206
|
+
* Resets all safe-area related state and styles.
|
|
2207
|
+
* Called during dismiss and disconnectedCallback to ensure clean state
|
|
2208
|
+
* for re-presentation of inline modals.
|
|
2209
|
+
*/
|
|
2210
|
+
resetSafeAreaState() {
|
|
2211
|
+
var _a;
|
|
2212
|
+
this.skipSafeAreaCoordinateDetection = false;
|
|
2213
|
+
this.cachedSafeAreas = undefined;
|
|
2214
|
+
this.prevSafeAreaState = { top: false, bottom: false, left: false, right: false };
|
|
2215
|
+
(_a = this.footerObserver) === null || _a === void 0 ? void 0 : _a.disconnect();
|
|
2216
|
+
this.footerObserver = undefined;
|
|
2217
|
+
// Clear wrapper and shadow styles that may have been set for safe-area handling
|
|
2218
|
+
[this.wrapperEl, this.shadowEl].forEach((el) => {
|
|
2219
|
+
if (el) {
|
|
2220
|
+
el.style.removeProperty('padding-bottom');
|
|
2221
|
+
el.style.removeProperty('box-sizing');
|
|
2222
|
+
}
|
|
2223
|
+
});
|
|
2224
|
+
// Clear safe-area CSS variable overrides
|
|
2225
|
+
const style = this.el.style;
|
|
2226
|
+
style.removeProperty('--ion-safe-area-top');
|
|
2227
|
+
style.removeProperty('--ion-safe-area-bottom');
|
|
2228
|
+
style.removeProperty('--ion-safe-area-left');
|
|
2229
|
+
style.removeProperty('--ion-safe-area-right');
|
|
2230
|
+
}
|
|
2231
|
+
/**
|
|
2232
|
+
* Gets the root safe-area values from the document element.
|
|
2233
|
+
* Uses cached values during gestures to avoid getComputedStyle calls.
|
|
2234
|
+
*/
|
|
2235
|
+
getSafeAreaValues() {
|
|
2236
|
+
if (!this.cachedSafeAreas) {
|
|
2237
|
+
const rootStyle = getComputedStyle(document.documentElement);
|
|
2238
|
+
this.cachedSafeAreas = {
|
|
2239
|
+
top: parseFloat(rootStyle.getPropertyValue('--ion-safe-area-top')) || 0,
|
|
2240
|
+
bottom: parseFloat(rootStyle.getPropertyValue('--ion-safe-area-bottom')) || 0,
|
|
2241
|
+
left: parseFloat(rootStyle.getPropertyValue('--ion-safe-area-left')) || 0,
|
|
2242
|
+
right: parseFloat(rootStyle.getPropertyValue('--ion-safe-area-right')) || 0,
|
|
2243
|
+
};
|
|
2244
|
+
}
|
|
2245
|
+
return this.cachedSafeAreas;
|
|
2246
|
+
}
|
|
2247
|
+
/**
|
|
2248
|
+
* Updates safe-area CSS variable overrides based on whether the modal
|
|
2249
|
+
* extends into each safe-area region. Called after animation
|
|
2250
|
+
* and during gestures to handle dynamic position changes.
|
|
2251
|
+
*
|
|
2252
|
+
* Optimized to avoid redundant DOM writes by tracking previous state.
|
|
2253
|
+
*/
|
|
2254
|
+
updateSafeAreaOverrides() {
|
|
2255
|
+
if (this.skipSafeAreaCoordinateDetection) {
|
|
2256
|
+
return;
|
|
2257
|
+
}
|
|
2258
|
+
const wrapper = this.wrapperEl;
|
|
2259
|
+
if (!wrapper) {
|
|
2260
|
+
return;
|
|
2261
|
+
}
|
|
2262
|
+
const rect = wrapper.getBoundingClientRect();
|
|
2263
|
+
const safeAreas = this.getSafeAreaValues();
|
|
2264
|
+
const extendsIntoTop = rect.top < safeAreas.top;
|
|
2265
|
+
const extendsIntoBottom = rect.bottom > window.innerHeight - safeAreas.bottom;
|
|
2266
|
+
const extendsIntoLeft = rect.left < safeAreas.left;
|
|
2267
|
+
const extendsIntoRight = rect.right > window.innerWidth - safeAreas.right;
|
|
2268
|
+
// Only update DOM when state actually changes
|
|
2269
|
+
const prev = this.prevSafeAreaState;
|
|
2270
|
+
const style = this.el.style;
|
|
2271
|
+
if (extendsIntoTop !== prev.top) {
|
|
2272
|
+
extendsIntoTop ? style.removeProperty('--ion-safe-area-top') : style.setProperty('--ion-safe-area-top', '0px');
|
|
2273
|
+
prev.top = extendsIntoTop;
|
|
2274
|
+
}
|
|
2275
|
+
if (extendsIntoBottom !== prev.bottom) {
|
|
2276
|
+
extendsIntoBottom
|
|
2277
|
+
? style.removeProperty('--ion-safe-area-bottom')
|
|
2278
|
+
: style.setProperty('--ion-safe-area-bottom', '0px');
|
|
2279
|
+
prev.bottom = extendsIntoBottom;
|
|
2280
|
+
}
|
|
2281
|
+
if (extendsIntoLeft !== prev.left) {
|
|
2282
|
+
extendsIntoLeft ? style.removeProperty('--ion-safe-area-left') : style.setProperty('--ion-safe-area-left', '0px');
|
|
2283
|
+
prev.left = extendsIntoLeft;
|
|
2284
|
+
}
|
|
2285
|
+
if (extendsIntoRight !== prev.right) {
|
|
2286
|
+
extendsIntoRight
|
|
2287
|
+
? style.removeProperty('--ion-safe-area-right')
|
|
2288
|
+
: style.setProperty('--ion-safe-area-right', '0px');
|
|
2289
|
+
prev.right = extendsIntoRight;
|
|
2290
|
+
}
|
|
2291
|
+
}
|
|
2086
2292
|
sheetOnDismiss() {
|
|
2087
2293
|
/**
|
|
2088
2294
|
* While the gesture animation is finishing
|
|
@@ -2175,6 +2381,8 @@ const Modal = /*@__PURE__*/ proxyCustomElement(class Modal extends HTMLElement {
|
|
|
2175
2381
|
}
|
|
2176
2382
|
this.currentBreakpoint = undefined;
|
|
2177
2383
|
this.animation = undefined;
|
|
2384
|
+
// Reset safe-area state for potential re-presentation
|
|
2385
|
+
this.resetSafeAreaState();
|
|
2178
2386
|
unlock();
|
|
2179
2387
|
return dismissed;
|
|
2180
2388
|
}
|
|
@@ -2424,20 +2632,20 @@ const Modal = /*@__PURE__*/ proxyCustomElement(class Modal extends HTMLElement {
|
|
|
2424
2632
|
const isCardModal = presentingElement !== undefined && mode === 'ios';
|
|
2425
2633
|
const isHandleCycle = handleBehavior === 'cycle';
|
|
2426
2634
|
const isSheetModalWithHandle = isSheetModal && showHandle;
|
|
2427
|
-
return (h(Host, Object.assign({ key: '
|
|
2635
|
+
return (h(Host, Object.assign({ key: '8f42c71ec9c9270b4218ca7eec57ca998871ac07', "no-router": true,
|
|
2428
2636
|
// Allow the modal to be navigable when the handle is focusable
|
|
2429
2637
|
tabIndex: isHandleCycle && isSheetModalWithHandle ? 0 : -1 }, htmlAttributes, { style: {
|
|
2430
2638
|
zIndex: `${20000 + this.overlayIndex}`,
|
|
2431
|
-
}, 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 }), h("ion-backdrop", { key: '
|
|
2639
|
+
}, 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 }), h("ion-backdrop", { key: '2f7b08b019c66cbfceacafa9a68b91f8da1f4084', ref: (el) => (this.backdropEl = el), visible: this.showBackdrop, tappable: this.backdropDismiss, part: "backdrop" }), mode === 'ios' && h("div", { key: '6b0d1ae90e8483332f74371be5dcbd0a7b2661ba', class: "modal-shadow", ref: (el) => (this.shadowEl = el) }), h("div", Object.assign({ key: 'c96f671fb25e5de45231ea65ac52500547b2e262',
|
|
2432
2640
|
/*
|
|
2433
2641
|
role and aria-modal must be used on the
|
|
2434
2642
|
same element. They must also be set inside the
|
|
2435
2643
|
shadow DOM otherwise ion-button will not be highlighted
|
|
2436
2644
|
when using VoiceOver: https://bugs.webkit.org/show_bug.cgi?id=247134
|
|
2437
2645
|
*/
|
|
2438
|
-
role: "dialog" }, inheritedAttributes, { "aria-modal": "true", class: "modal-wrapper ion-overlay-wrapper", part: "content", ref: (el) => (this.wrapperEl = el) }), showHandle && (h("button", { key: '
|
|
2646
|
+
role: "dialog" }, inheritedAttributes, { "aria-modal": "true", class: "modal-wrapper ion-overlay-wrapper", part: "content", ref: (el) => (this.wrapperEl = el) }), showHandle && (h("button", { key: 'e07419b01a588c0ba62ed9607c843cac7bd26337', class: "modal-handle",
|
|
2439
2647
|
// Prevents the handle from receiving keyboard focus when it does not cycle
|
|
2440
|
-
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) })), h("slot", { key: '
|
|
2648
|
+
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) })), h("slot", { key: '65f35079df8eb8b6cd262e3a08297866715ce7ea', onSlotchange: this.onSlotChange }))));
|
|
2441
2649
|
}
|
|
2442
2650
|
get el() { return this; }
|
|
2443
2651
|
static get watchers() { return {
|
package/components/popover.js
CHANGED
|
@@ -657,6 +657,8 @@ 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;
|
|
660
662
|
let checkSafeAreaLeft = false;
|
|
661
663
|
let checkSafeAreaRight = false;
|
|
662
664
|
const triggerTop = triggerCoordinates
|
|
@@ -701,10 +703,18 @@ const calculateWindowAdjustment = (side, coordTop, coordLeft, bodyPadding, bodyW
|
|
|
701
703
|
* We chose 12 here so that the popover position looks a bit nicer as
|
|
702
704
|
* it is not right up against the edge of the screen.
|
|
703
705
|
*/
|
|
704
|
-
top = Math.max(
|
|
706
|
+
top = Math.max(bodyPadding, triggerTop - contentHeight - triggerHeight - (arrowHeight - 1));
|
|
705
707
|
arrowTop = top + contentHeight;
|
|
706
708
|
originY = 'bottom';
|
|
707
709
|
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
|
+
}
|
|
708
718
|
/**
|
|
709
719
|
* If not enough room for popover to appear
|
|
710
720
|
* above trigger, then cut it off.
|
|
@@ -712,14 +722,35 @@ const calculateWindowAdjustment = (side, coordTop, coordLeft, bodyPadding, bodyW
|
|
|
712
722
|
}
|
|
713
723
|
else {
|
|
714
724
|
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;
|
|
715
731
|
}
|
|
716
732
|
}
|
|
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
|
+
}
|
|
717
746
|
return {
|
|
718
747
|
top,
|
|
719
748
|
left,
|
|
720
749
|
bottom,
|
|
721
750
|
originX,
|
|
722
751
|
originY,
|
|
752
|
+
checkSafeAreaTop,
|
|
753
|
+
checkSafeAreaBottom,
|
|
723
754
|
checkSafeAreaLeft,
|
|
724
755
|
checkSafeAreaRight,
|
|
725
756
|
arrowTop,
|
|
@@ -780,7 +811,7 @@ const iosEnterAnimation = (baseEl, opts) => {
|
|
|
780
811
|
const results = getPopoverPosition(isRTL, contentWidth, contentHeight, arrowWidth, arrowHeight, reference, side, align, defaultPosition, trigger, ev);
|
|
781
812
|
const padding = size === 'cover' ? 0 : POPOVER_IOS_BODY_PADDING;
|
|
782
813
|
const margin = size === 'cover' ? 0 : 25;
|
|
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);
|
|
814
|
+
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);
|
|
784
815
|
const baseAnimation = createAnimation();
|
|
785
816
|
const backdropAnimation = createAnimation();
|
|
786
817
|
const contentAnimation = createAnimation();
|
|
@@ -810,19 +841,35 @@ const iosEnterAnimation = (baseEl, opts) => {
|
|
|
810
841
|
if (addPopoverBottomClass) {
|
|
811
842
|
baseEl.classList.add('popover-bottom');
|
|
812
843
|
}
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
844
|
+
/**
|
|
845
|
+
* Safe area CSS variable adjustments.
|
|
846
|
+
* When the popover is positioned near an edge, we add the corresponding
|
|
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)';
|
|
816
852
|
const safeAreaLeft = ' + var(--ion-safe-area-left, 0)';
|
|
817
853
|
const safeAreaRight = ' - var(--ion-safe-area-right, 0)';
|
|
854
|
+
let topValue = `${top}px`;
|
|
855
|
+
let bottomValue = bottom !== undefined ? `${bottom}px` : undefined;
|
|
818
856
|
let leftValue = `${left}px`;
|
|
857
|
+
if (checkSafeAreaTop) {
|
|
858
|
+
topValue = `${top}px${safeAreaTop}`;
|
|
859
|
+
}
|
|
860
|
+
if (checkSafeAreaBottom && bottomValue !== undefined) {
|
|
861
|
+
bottomValue = `${bottom}px${safeAreaBottom}`;
|
|
862
|
+
}
|
|
819
863
|
if (checkSafeAreaLeft) {
|
|
820
864
|
leftValue = `${left}px${safeAreaLeft}`;
|
|
821
865
|
}
|
|
822
866
|
if (checkSafeAreaRight) {
|
|
823
867
|
leftValue = `${left}px${safeAreaRight}`;
|
|
824
868
|
}
|
|
825
|
-
|
|
869
|
+
if (bottomValue !== undefined) {
|
|
870
|
+
contentEl.style.setProperty('bottom', `calc(${bottomValue})`);
|
|
871
|
+
}
|
|
872
|
+
contentEl.style.setProperty('top', `calc(${topValue} + var(--offset-y, 0))`);
|
|
826
873
|
contentEl.style.setProperty('left', `calc(${leftValue} + var(--offset-x, 0))`);
|
|
827
874
|
contentEl.style.setProperty('transform-origin', `${originY} ${originX}`);
|
|
828
875
|
if (arrowEl !== null) {
|
|
@@ -898,7 +945,32 @@ const mdEnterAnimation = (baseEl, opts) => {
|
|
|
898
945
|
};
|
|
899
946
|
const results = getPopoverPosition(isRTL, contentWidth, contentHeight, 0, 0, reference, side, align, defaultPosition, trigger, ev);
|
|
900
947
|
const padding = size === 'cover' ? 0 : POPOVER_MD_BODY_PADDING;
|
|
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);
|
|
948
|
+
const { originX, originY, top, left, bottom, checkSafeAreaTop, checkSafeAreaBottom, checkSafeAreaLeft, checkSafeAreaRight, } = calculateWindowAdjustment(side, results.top, results.left, padding, bodyWidth, bodyHeight, contentWidth, contentHeight, 0, results.originX, results.originY, results.referenceCoordinates);
|
|
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
|
+
const safeAreaLeft = ' + var(--ion-safe-area-left, 0)';
|
|
958
|
+
const safeAreaRight = ' - var(--ion-safe-area-right, 0)';
|
|
959
|
+
let topValue = `${top}px`;
|
|
960
|
+
let bottomValue = bottom !== undefined ? `${bottom}px` : undefined;
|
|
961
|
+
let leftValue = `${left}px`;
|
|
962
|
+
if (checkSafeAreaTop) {
|
|
963
|
+
topValue = `${top}px${safeAreaTop}`;
|
|
964
|
+
}
|
|
965
|
+
if (checkSafeAreaBottom && bottomValue !== undefined) {
|
|
966
|
+
bottomValue = `${bottom}px${safeAreaBottom}`;
|
|
967
|
+
}
|
|
968
|
+
if (checkSafeAreaLeft) {
|
|
969
|
+
leftValue = `${left}px${safeAreaLeft}`;
|
|
970
|
+
}
|
|
971
|
+
if (checkSafeAreaRight) {
|
|
972
|
+
leftValue = `${left}px${safeAreaRight}`;
|
|
973
|
+
}
|
|
902
974
|
const baseAnimation = createAnimation();
|
|
903
975
|
const backdropAnimation = createAnimation();
|
|
904
976
|
const wrapperAnimation = createAnimation();
|
|
@@ -915,13 +987,13 @@ const mdEnterAnimation = (baseEl, opts) => {
|
|
|
915
987
|
contentAnimation
|
|
916
988
|
.addElement(contentEl)
|
|
917
989
|
.beforeStyles({
|
|
918
|
-
top: `calc(${
|
|
919
|
-
left: `calc(${
|
|
990
|
+
top: `calc(${topValue} + var(--offset-y, 0px))`,
|
|
991
|
+
left: `calc(${leftValue} + var(--offset-x, 0px))`,
|
|
920
992
|
'transform-origin': `${originY} ${originX}`,
|
|
921
993
|
})
|
|
922
994
|
.beforeAddWrite(() => {
|
|
923
|
-
if (
|
|
924
|
-
contentEl.style.setProperty('bottom',
|
|
995
|
+
if (bottomValue !== undefined) {
|
|
996
|
+
contentEl.style.setProperty('bottom', `calc(${bottomValue})`);
|
|
925
997
|
}
|
|
926
998
|
})
|
|
927
999
|
.fromTo('transform', 'scale(0.8)', 'scale(1)');
|