@ionic/core 8.7.17-dev.11767717752.14fe98a4 → 8.7.17-dev.11767891829.1a63afa3
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 +68 -9
- package/components/modal.js +95 -27
- package/components/popover.js +11 -2
- package/dist/cjs/ion-app_8.cjs.entry.js +79 -21
- package/dist/cjs/ion-modal.cjs.entry.js +95 -27
- package/dist/cjs/ion-popover.cjs.entry.js +11 -2
- package/dist/collection/components/content/content.js +67 -8
- package/dist/collection/components/modal/modal.js +95 -26
- package/dist/collection/components/popover/animations/md.enter.js +11 -2
- package/dist/docs.json +1 -1
- package/dist/esm/ion-app_8.entry.js +68 -10
- package/dist/esm/ion-modal.entry.js +95 -27
- package/dist/esm/ion-popover.entry.js +11 -2
- package/dist/ionic/ionic.esm.js +1 -1
- package/dist/ionic/p-968a55d1.entry.js +4 -0
- package/dist/ionic/p-d9fd799f.entry.js +4 -0
- package/dist/ionic/p-ec9ca3fe.entry.js +4 -0
- package/dist/types/components/content/content.d.ts +15 -2
- package/dist/types/components/modal/modal.d.ts +18 -2
- package/hydrate/index.js +165 -37
- package/hydrate/index.mjs +165 -37
- package/package.json +1 -1
- package/dist/ionic/p-34cdcd15.entry.js +0 -4
- package/dist/ionic/p-a4827773.entry.js +0 -4
- package/dist/ionic/p-fedca459.entry.js +0 -4
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
'use strict';
|
|
5
5
|
|
|
6
6
|
var index$3 = require('./index-D6Wc6v08.js');
|
|
7
|
+
var index = require('./index-DkNv4J_i.js');
|
|
7
8
|
var index$2 = require('./index-CO6eryBo.js');
|
|
8
9
|
var frameworkDelegate = require('./framework-delegate-DMJRBuDi.js');
|
|
9
10
|
var helpers = require('./helpers-DrTqNghc.js');
|
|
@@ -17,7 +18,6 @@ var keyboard = require('./keyboard-hHzlEQpk.js');
|
|
|
17
18
|
var animation = require('./animation-Bt3H9L1C.js');
|
|
18
19
|
var cubicBezier = require('./cubic-bezier-DAjy1V-e.js');
|
|
19
20
|
var index$1 = require('./index-CAvQ7Tka.js');
|
|
20
|
-
var index = require('./index-DkNv4J_i.js');
|
|
21
21
|
require('./hardware-back-button-VCK4V3mG.js');
|
|
22
22
|
require('./gesture-controller-dtqlP_q4.js');
|
|
23
23
|
require('./keyboard-UuAS4D_9.js');
|
|
@@ -1505,6 +1505,8 @@ const Modal = class {
|
|
|
1505
1505
|
this.gestureAnimationDismissing = false;
|
|
1506
1506
|
// Whether to skip coordinate-based safe-area detection (for fullscreen phone modals)
|
|
1507
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 };
|
|
1508
1510
|
this.presented = false;
|
|
1509
1511
|
/** @internal */
|
|
1510
1512
|
this.hasController = false;
|
|
@@ -1695,7 +1697,8 @@ const Modal = class {
|
|
|
1695
1697
|
}
|
|
1696
1698
|
}
|
|
1697
1699
|
onWindowResize() {
|
|
1698
|
-
//
|
|
1700
|
+
// Invalidate safe-area cache on resize (device rotation may change values)
|
|
1701
|
+
this.cachedSafeAreas = undefined;
|
|
1699
1702
|
this.updateSafeAreaOverrides();
|
|
1700
1703
|
// Only handle view transition for iOS card modals when no custom animations are provided
|
|
1701
1704
|
if (ionicGlobal.getIonMode(this) !== 'ios' || !this.presentingElement || this.enterAnimation || this.leaveAnimation) {
|
|
@@ -1720,6 +1723,8 @@ const Modal = class {
|
|
|
1720
1723
|
this.triggerController.removeClickListener();
|
|
1721
1724
|
this.cleanupViewTransitionListener();
|
|
1722
1725
|
this.cleanupParentRemovalObserver();
|
|
1726
|
+
// Reset safe-area state to handle removal without dismiss (e.g., framework unmount)
|
|
1727
|
+
this.resetSafeAreaState();
|
|
1723
1728
|
}
|
|
1724
1729
|
componentWillLoad() {
|
|
1725
1730
|
var _a;
|
|
@@ -2154,8 +2159,28 @@ const Modal = class {
|
|
|
2154
2159
|
*/
|
|
2155
2160
|
applyFullscreenSafeArea() {
|
|
2156
2161
|
this.skipSafeAreaCoordinateDetection = true;
|
|
2162
|
+
this.updateFooterPadding();
|
|
2163
|
+
// Watch for dynamic footer additions/removals (e.g., async data loading)
|
|
2164
|
+
// Use subtree:true to support wrapped footers in framework components
|
|
2165
|
+
// (e.g., <my-footer><ion-footer>...</ion-footer></my-footer>)
|
|
2166
|
+
if (!this.footerObserver && index.win !== undefined && 'MutationObserver' in index.win) {
|
|
2167
|
+
this.footerObserver = new MutationObserver(() => this.updateFooterPadding());
|
|
2168
|
+
this.footerObserver.observe(this.el, { childList: true, subtree: true });
|
|
2169
|
+
}
|
|
2170
|
+
}
|
|
2171
|
+
/**
|
|
2172
|
+
* Updates wrapper padding based on footer presence.
|
|
2173
|
+
* Called initially and when footer is dynamically added/removed.
|
|
2174
|
+
*/
|
|
2175
|
+
updateFooterPadding() {
|
|
2176
|
+
if (!this.wrapperEl)
|
|
2177
|
+
return;
|
|
2157
2178
|
const hasFooter = this.el.querySelector('ion-footer') !== null;
|
|
2158
|
-
if (
|
|
2179
|
+
if (hasFooter) {
|
|
2180
|
+
this.wrapperEl.style.removeProperty('padding-bottom');
|
|
2181
|
+
this.wrapperEl.style.removeProperty('box-sizing');
|
|
2182
|
+
}
|
|
2183
|
+
else {
|
|
2159
2184
|
this.wrapperEl.style.setProperty('padding-bottom', 'var(--ion-safe-area-bottom, 0px)');
|
|
2160
2185
|
this.wrapperEl.style.setProperty('box-sizing', 'border-box');
|
|
2161
2186
|
}
|
|
@@ -2171,23 +2196,52 @@ const Modal = class {
|
|
|
2171
2196
|
style.setProperty('--ion-safe-area-left', '0px');
|
|
2172
2197
|
style.setProperty('--ion-safe-area-right', '0px');
|
|
2173
2198
|
}
|
|
2199
|
+
/**
|
|
2200
|
+
* Resets all safe-area related state and styles.
|
|
2201
|
+
* Called during dismiss and disconnectedCallback to ensure clean state
|
|
2202
|
+
* for re-presentation of inline modals.
|
|
2203
|
+
*/
|
|
2204
|
+
resetSafeAreaState() {
|
|
2205
|
+
var _a;
|
|
2206
|
+
this.skipSafeAreaCoordinateDetection = false;
|
|
2207
|
+
this.cachedSafeAreas = undefined;
|
|
2208
|
+
this.prevSafeAreaState = { top: false, bottom: false, left: false, right: false };
|
|
2209
|
+
(_a = this.footerObserver) === null || _a === void 0 ? void 0 : _a.disconnect();
|
|
2210
|
+
this.footerObserver = undefined;
|
|
2211
|
+
// Clear wrapper styles that may have been set for safe-area handling
|
|
2212
|
+
if (this.wrapperEl) {
|
|
2213
|
+
this.wrapperEl.style.removeProperty('padding-bottom');
|
|
2214
|
+
this.wrapperEl.style.removeProperty('box-sizing');
|
|
2215
|
+
}
|
|
2216
|
+
// Clear safe-area CSS variable overrides
|
|
2217
|
+
const style = this.el.style;
|
|
2218
|
+
style.removeProperty('--ion-safe-area-top');
|
|
2219
|
+
style.removeProperty('--ion-safe-area-bottom');
|
|
2220
|
+
style.removeProperty('--ion-safe-area-left');
|
|
2221
|
+
style.removeProperty('--ion-safe-area-right');
|
|
2222
|
+
}
|
|
2174
2223
|
/**
|
|
2175
2224
|
* Gets the root safe-area values from the document element.
|
|
2176
|
-
*
|
|
2225
|
+
* Uses cached values during gestures to avoid getComputedStyle calls.
|
|
2177
2226
|
*/
|
|
2178
|
-
|
|
2179
|
-
|
|
2180
|
-
|
|
2181
|
-
|
|
2182
|
-
|
|
2183
|
-
|
|
2184
|
-
|
|
2185
|
-
|
|
2227
|
+
getSafeAreaValues() {
|
|
2228
|
+
if (!this.cachedSafeAreas) {
|
|
2229
|
+
const rootStyle = getComputedStyle(document.documentElement);
|
|
2230
|
+
this.cachedSafeAreas = {
|
|
2231
|
+
top: parseFloat(rootStyle.getPropertyValue('--ion-safe-area-top')) || 0,
|
|
2232
|
+
bottom: parseFloat(rootStyle.getPropertyValue('--ion-safe-area-bottom')) || 0,
|
|
2233
|
+
left: parseFloat(rootStyle.getPropertyValue('--ion-safe-area-left')) || 0,
|
|
2234
|
+
right: parseFloat(rootStyle.getPropertyValue('--ion-safe-area-right')) || 0,
|
|
2235
|
+
};
|
|
2236
|
+
}
|
|
2237
|
+
return this.cachedSafeAreas;
|
|
2186
2238
|
}
|
|
2187
2239
|
/**
|
|
2188
2240
|
* Updates safe-area CSS variable overrides based on whether the modal
|
|
2189
2241
|
* extends into each safe-area region. Called after animation
|
|
2190
2242
|
* and during gestures to handle dynamic position changes.
|
|
2243
|
+
*
|
|
2244
|
+
* Optimized to avoid redundant DOM writes by tracking previous state.
|
|
2191
2245
|
*/
|
|
2192
2246
|
updateSafeAreaOverrides() {
|
|
2193
2247
|
if (this.skipSafeAreaCoordinateDetection) {
|
|
@@ -2198,20 +2252,34 @@ const Modal = class {
|
|
|
2198
2252
|
return;
|
|
2199
2253
|
}
|
|
2200
2254
|
const rect = wrapper.getBoundingClientRect();
|
|
2201
|
-
const safeAreas = this.
|
|
2255
|
+
const safeAreas = this.getSafeAreaValues();
|
|
2202
2256
|
const extendsIntoTop = rect.top < safeAreas.top;
|
|
2203
2257
|
const extendsIntoBottom = rect.bottom > window.innerHeight - safeAreas.bottom;
|
|
2204
2258
|
const extendsIntoLeft = rect.left < safeAreas.left;
|
|
2205
2259
|
const extendsIntoRight = rect.right > window.innerWidth - safeAreas.right;
|
|
2260
|
+
// Only update DOM when state actually changes
|
|
2261
|
+
const prev = this.prevSafeAreaState;
|
|
2206
2262
|
const style = this.el.style;
|
|
2207
|
-
extendsIntoTop
|
|
2208
|
-
|
|
2209
|
-
|
|
2210
|
-
|
|
2211
|
-
|
|
2212
|
-
|
|
2213
|
-
|
|
2214
|
-
|
|
2263
|
+
if (extendsIntoTop !== prev.top) {
|
|
2264
|
+
extendsIntoTop ? style.removeProperty('--ion-safe-area-top') : style.setProperty('--ion-safe-area-top', '0px');
|
|
2265
|
+
prev.top = extendsIntoTop;
|
|
2266
|
+
}
|
|
2267
|
+
if (extendsIntoBottom !== prev.bottom) {
|
|
2268
|
+
extendsIntoBottom
|
|
2269
|
+
? style.removeProperty('--ion-safe-area-bottom')
|
|
2270
|
+
: style.setProperty('--ion-safe-area-bottom', '0px');
|
|
2271
|
+
prev.bottom = extendsIntoBottom;
|
|
2272
|
+
}
|
|
2273
|
+
if (extendsIntoLeft !== prev.left) {
|
|
2274
|
+
extendsIntoLeft ? style.removeProperty('--ion-safe-area-left') : style.setProperty('--ion-safe-area-left', '0px');
|
|
2275
|
+
prev.left = extendsIntoLeft;
|
|
2276
|
+
}
|
|
2277
|
+
if (extendsIntoRight !== prev.right) {
|
|
2278
|
+
extendsIntoRight
|
|
2279
|
+
? style.removeProperty('--ion-safe-area-right')
|
|
2280
|
+
: style.setProperty('--ion-safe-area-right', '0px');
|
|
2281
|
+
prev.right = extendsIntoRight;
|
|
2282
|
+
}
|
|
2215
2283
|
}
|
|
2216
2284
|
sheetOnDismiss() {
|
|
2217
2285
|
/**
|
|
@@ -2305,8 +2373,8 @@ const Modal = class {
|
|
|
2305
2373
|
}
|
|
2306
2374
|
this.currentBreakpoint = undefined;
|
|
2307
2375
|
this.animation = undefined;
|
|
2308
|
-
// Reset safe-area
|
|
2309
|
-
this.
|
|
2376
|
+
// Reset safe-area state for potential re-presentation
|
|
2377
|
+
this.resetSafeAreaState();
|
|
2310
2378
|
unlock();
|
|
2311
2379
|
return dismissed;
|
|
2312
2380
|
}
|
|
@@ -2556,20 +2624,20 @@ const Modal = class {
|
|
|
2556
2624
|
const isCardModal = presentingElement !== undefined && mode === 'ios';
|
|
2557
2625
|
const isHandleCycle = handleBehavior === 'cycle';
|
|
2558
2626
|
const isSheetModalWithHandle = isSheetModal && showHandle;
|
|
2559
|
-
return (index$3.h(index$3.Host, Object.assign({ key: '
|
|
2627
|
+
return (index$3.h(index$3.Host, Object.assign({ key: '44022099fcaf047b97d1c2cb45b9b51c930e707c', "no-router": true,
|
|
2560
2628
|
// Allow the modal to be navigable when the handle is focusable
|
|
2561
2629
|
tabIndex: isHandleCycle && isSheetModalWithHandle ? 0 : -1 }, htmlAttributes, { style: {
|
|
2562
2630
|
zIndex: `${20000 + this.overlayIndex}`,
|
|
2563
|
-
}, 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: '
|
|
2631
|
+
}, 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: 'ddd7e4f6eef51ac1f62ac70e0af10fb01e707f07', ref: (el) => (this.backdropEl = el), visible: this.showBackdrop, tappable: this.backdropDismiss, part: "backdrop" }), mode === 'ios' && index$3.h("div", { key: '58620980e3e4ec273c6787bde026e1c010b904b7', class: "modal-shadow" }), index$3.h("div", Object.assign({ key: '3fb7f6218644ba898fc504467775593eb89426a0',
|
|
2564
2632
|
/*
|
|
2565
2633
|
role and aria-modal must be used on the
|
|
2566
2634
|
same element. They must also be set inside the
|
|
2567
2635
|
shadow DOM otherwise ion-button will not be highlighted
|
|
2568
2636
|
when using VoiceOver: https://bugs.webkit.org/show_bug.cgi?id=247134
|
|
2569
2637
|
*/
|
|
2570
|
-
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: '
|
|
2638
|
+
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: '9745cd590fdaa9d023a14b487ec2c87ddbafd7f7', class: "modal-handle",
|
|
2571
2639
|
// Prevents the handle from receiving keyboard focus when it does not cycle
|
|
2572
|
-
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: '
|
|
2640
|
+
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: 'b9a8b5d2d3d3c9b06f99179f496c9f08907d0bad', onSlotchange: this.onSlotChange }))));
|
|
2573
2641
|
}
|
|
2574
2642
|
get el() { return index$3.getElement(this); }
|
|
2575
2643
|
static get watchers() { return {
|
|
@@ -948,7 +948,7 @@ const mdEnterAnimation = (baseEl, opts) => {
|
|
|
948
948
|
};
|
|
949
949
|
const results = getPopoverPosition(isRTL, contentWidth, contentHeight, 0, 0, reference, side, align, defaultPosition, trigger, ev);
|
|
950
950
|
const padding = size === 'cover' ? 0 : POPOVER_MD_BODY_PADDING;
|
|
951
|
-
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);
|
|
951
|
+
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);
|
|
952
952
|
/**
|
|
953
953
|
* Safe area CSS variable adjustments.
|
|
954
954
|
* When the popover is positioned near an edge, we add the corresponding
|
|
@@ -957,14 +957,23 @@ const mdEnterAnimation = (baseEl, opts) => {
|
|
|
957
957
|
*/
|
|
958
958
|
const safeAreaTop = ' + var(--ion-safe-area-top, 0)';
|
|
959
959
|
const safeAreaBottom = ' + var(--ion-safe-area-bottom, 0)';
|
|
960
|
+
const safeAreaLeft = ' + var(--ion-safe-area-left, 0)';
|
|
961
|
+
const safeAreaRight = ' - var(--ion-safe-area-right, 0)';
|
|
960
962
|
let topValue = `${top}px`;
|
|
961
963
|
let bottomValue = bottom !== undefined ? `${bottom}px` : undefined;
|
|
964
|
+
let leftValue = `${left}px`;
|
|
962
965
|
if (checkSafeAreaTop) {
|
|
963
966
|
topValue = `${top}px${safeAreaTop}`;
|
|
964
967
|
}
|
|
965
968
|
if (checkSafeAreaBottom && bottomValue !== undefined) {
|
|
966
969
|
bottomValue = `${bottom}px${safeAreaBottom}`;
|
|
967
970
|
}
|
|
971
|
+
if (checkSafeAreaLeft) {
|
|
972
|
+
leftValue = `${left}px${safeAreaLeft}`;
|
|
973
|
+
}
|
|
974
|
+
if (checkSafeAreaRight) {
|
|
975
|
+
leftValue = `${left}px${safeAreaRight}`;
|
|
976
|
+
}
|
|
968
977
|
const baseAnimation = animation.createAnimation();
|
|
969
978
|
const backdropAnimation = animation.createAnimation();
|
|
970
979
|
const wrapperAnimation = animation.createAnimation();
|
|
@@ -982,7 +991,7 @@ const mdEnterAnimation = (baseEl, opts) => {
|
|
|
982
991
|
.addElement(contentEl)
|
|
983
992
|
.beforeStyles({
|
|
984
993
|
top: `calc(${topValue} + var(--offset-y, 0px))`,
|
|
985
|
-
left: `calc(${
|
|
994
|
+
left: `calc(${leftValue} + var(--offset-x, 0px))`,
|
|
986
995
|
'transform-origin': `${originY} ${originX}`,
|
|
987
996
|
})
|
|
988
997
|
.beforeAddWrite(() => {
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
* (C) Ionic http://ionicframework.com - MIT License
|
|
3
3
|
*/
|
|
4
4
|
import { Build, Host, forceUpdate, h, readTask } from "@stencil/core";
|
|
5
|
+
import { win } from "../../utils/browser/index";
|
|
5
6
|
import { componentOnReady, hasLazyBuild, inheritAriaAttributes } from "../../utils/helpers";
|
|
6
7
|
import { isPlatform } from "../../utils/platform";
|
|
7
8
|
import { isRTL } from "../../utils/rtl/index";
|
|
@@ -85,7 +86,11 @@ export class Content {
|
|
|
85
86
|
this.inheritedAttributes = inheritAriaAttributes(this.el);
|
|
86
87
|
}
|
|
87
88
|
connectedCallback() {
|
|
88
|
-
|
|
89
|
+
var _a;
|
|
90
|
+
// Content is "main" if not inside menu/popover/modal and not nested in another ion-content
|
|
91
|
+
this.isMainContent =
|
|
92
|
+
this.el.closest('ion-menu, ion-popover, ion-modal') === null &&
|
|
93
|
+
((_a = this.el.parentElement) === null || _a === void 0 ? void 0 : _a.closest('ion-content')) === null;
|
|
89
94
|
// Detect sibling header/footer for safe-area handling
|
|
90
95
|
this.detectSiblingElements();
|
|
91
96
|
/**
|
|
@@ -118,21 +123,55 @@ export class Content {
|
|
|
118
123
|
* bubbles, we can catch any instances of child tab bars loading by listening
|
|
119
124
|
* on IonTabs.
|
|
120
125
|
*/
|
|
121
|
-
this.tabsLoadCallback = () =>
|
|
126
|
+
this.tabsLoadCallback = () => {
|
|
127
|
+
this.resize();
|
|
128
|
+
// Re-detect footer when tab bar loads (it may not exist during initial detection)
|
|
129
|
+
this.updateSiblingDetection();
|
|
130
|
+
forceUpdate(this);
|
|
131
|
+
};
|
|
122
132
|
closestTabs.addEventListener('ionTabBarLoaded', this.tabsLoadCallback);
|
|
123
133
|
}
|
|
124
134
|
}
|
|
125
135
|
}
|
|
126
136
|
/**
|
|
127
|
-
* Detects sibling ion-header and ion-footer elements
|
|
128
|
-
*
|
|
137
|
+
* Detects sibling ion-header and ion-footer elements and sets up
|
|
138
|
+
* a mutation observer to handle dynamic changes (e.g., conditional rendering).
|
|
129
139
|
*/
|
|
130
140
|
detectSiblingElements() {
|
|
131
|
-
|
|
141
|
+
this.updateSiblingDetection();
|
|
142
|
+
// Watch for dynamic header/footer changes (common in React conditional rendering)
|
|
143
|
+
const parent = this.el.parentElement;
|
|
144
|
+
if (parent && !this.parentMutationObserver && win !== undefined && 'MutationObserver' in win) {
|
|
145
|
+
this.parentMutationObserver = new MutationObserver(() => {
|
|
146
|
+
const prevHasHeader = this.hasHeader;
|
|
147
|
+
const prevHasFooter = this.hasFooter;
|
|
148
|
+
this.updateSiblingDetection();
|
|
149
|
+
// Only trigger re-render if header/footer detection actually changed
|
|
150
|
+
if (prevHasHeader !== this.hasHeader || prevHasFooter !== this.hasFooter) {
|
|
151
|
+
forceUpdate(this);
|
|
152
|
+
}
|
|
153
|
+
});
|
|
154
|
+
this.parentMutationObserver.observe(parent, { childList: true });
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* Updates hasHeader/hasFooter based on current DOM state.
|
|
159
|
+
* Checks both direct siblings and elements wrapped in custom components
|
|
160
|
+
* (e.g., <my-header><ion-header>...</ion-header></my-header>).
|
|
161
|
+
*/
|
|
162
|
+
updateSiblingDetection() {
|
|
132
163
|
const parent = this.el.parentElement;
|
|
133
164
|
if (parent) {
|
|
165
|
+
// First check for direct ion-header/ion-footer siblings
|
|
134
166
|
this.hasHeader = parent.querySelector(':scope > ion-header') !== null;
|
|
135
167
|
this.hasFooter = parent.querySelector(':scope > ion-footer') !== null;
|
|
168
|
+
// If not found, check if any sibling contains them (wrapped components)
|
|
169
|
+
if (!this.hasHeader) {
|
|
170
|
+
this.hasHeader = this.siblingContainsElement(parent, 'ion-header');
|
|
171
|
+
}
|
|
172
|
+
if (!this.hasFooter) {
|
|
173
|
+
this.hasFooter = this.siblingContainsElement(parent, 'ion-footer');
|
|
174
|
+
}
|
|
136
175
|
}
|
|
137
176
|
// If no footer found, check if we're inside ion-tabs which has ion-tab-bar
|
|
138
177
|
if (!this.hasFooter) {
|
|
@@ -142,8 +181,28 @@ export class Content {
|
|
|
142
181
|
}
|
|
143
182
|
}
|
|
144
183
|
}
|
|
184
|
+
/**
|
|
185
|
+
* Checks if any sibling element of ion-content contains the specified element.
|
|
186
|
+
* Only searches one level deep to avoid finding elements in nested pages.
|
|
187
|
+
*/
|
|
188
|
+
siblingContainsElement(parent, tagName) {
|
|
189
|
+
for (const sibling of parent.children) {
|
|
190
|
+
// Skip ion-content itself
|
|
191
|
+
if (sibling === this.el)
|
|
192
|
+
continue;
|
|
193
|
+
// Check if this sibling contains the target element as an immediate child
|
|
194
|
+
if (sibling.querySelector(`:scope > ${tagName}`) !== null) {
|
|
195
|
+
return true;
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
return false;
|
|
199
|
+
}
|
|
145
200
|
disconnectedCallback() {
|
|
201
|
+
var _a;
|
|
146
202
|
this.onScrollEnd();
|
|
203
|
+
// Clean up mutation observer to prevent memory leaks
|
|
204
|
+
(_a = this.parentMutationObserver) === null || _a === void 0 ? void 0 : _a.disconnect();
|
|
205
|
+
this.parentMutationObserver = undefined;
|
|
147
206
|
if (hasLazyBuild(this.el)) {
|
|
148
207
|
/**
|
|
149
208
|
* The event listener and tabs caches need to
|
|
@@ -396,7 +455,7 @@ export class Content {
|
|
|
396
455
|
const forceOverscroll = this.shouldForceOverscroll();
|
|
397
456
|
const transitionShadow = mode === 'ios';
|
|
398
457
|
this.resize();
|
|
399
|
-
return (h(Host, Object.assign({ key: '
|
|
458
|
+
return (h(Host, Object.assign({ key: 'f7218f733e4022a30875441bd949747537d28aa1', role: isMainContent ? 'main' : undefined, class: createColorClasses(this.color, {
|
|
400
459
|
[mode]: true,
|
|
401
460
|
'content-sizing': hostContext('ion-popover', this.el),
|
|
402
461
|
overscroll: forceOverscroll,
|
|
@@ -406,12 +465,12 @@ export class Content {
|
|
|
406
465
|
}), style: {
|
|
407
466
|
'--offset-top': `${this.cTop}px`,
|
|
408
467
|
'--offset-bottom': `${this.cBottom}px`,
|
|
409
|
-
} }, inheritedAttributes), h("div", { key: '
|
|
468
|
+
} }, inheritedAttributes), h("div", { key: 'b735ec68c18c0b99c3595bb194029830e6542cde', ref: (el) => (this.backgroundContentEl = el), id: "background-content", part: "background" }), fixedSlotPlacement === 'before' ? h("slot", { name: "fixed" }) : null, h("div", { key: 'e76c00d030342d44ade6648c3f9e32ca990787ba', class: {
|
|
410
469
|
'inner-scroll': true,
|
|
411
470
|
'scroll-x': scrollX,
|
|
412
471
|
'scroll-y': scrollY,
|
|
413
472
|
overscroll: (scrollX || scrollY) && forceOverscroll,
|
|
414
|
-
}, ref: (scrollEl) => (this.scrollEl = scrollEl), onScroll: this.scrollEvents ? (ev) => this.onScroll(ev) : undefined, part: "scroll" }, h("slot", { key: '
|
|
473
|
+
}, ref: (scrollEl) => (this.scrollEl = scrollEl), onScroll: this.scrollEvents ? (ev) => this.onScroll(ev) : undefined, part: "scroll" }, h("slot", { key: '9049be4cea9b5da5ec1e1012248b05286fddeb7a' })), transitionShadow ? (h("div", { class: "transition-effect" }, h("div", { class: "transition-cover" }), h("div", { class: "transition-shadow" }))) : null, fixedSlotPlacement === 'after' ? h("slot", { name: "fixed" }) : null));
|
|
415
474
|
}
|
|
416
475
|
static get is() { return "ion-content"; }
|
|
417
476
|
static get encapsulation() { return "shadow"; }
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
* (C) Ionic http://ionicframework.com - MIT License
|
|
3
3
|
*/
|
|
4
4
|
import { Host, h, writeTask } from "@stencil/core";
|
|
5
|
+
import { win } from "../../utils/browser/index";
|
|
5
6
|
import { findIonContent, printIonContentErrorMsg } from "../../utils/content/index";
|
|
6
7
|
import { CoreDelegate, attachComponent, detachComponent } from "../../utils/framework-delegate";
|
|
7
8
|
import { raf, inheritAttributes, hasLazyBuild, getElementRoot } from "../../utils/helpers";
|
|
@@ -44,6 +45,8 @@ export class Modal {
|
|
|
44
45
|
this.gestureAnimationDismissing = false;
|
|
45
46
|
// Whether to skip coordinate-based safe-area detection (for fullscreen phone modals)
|
|
46
47
|
this.skipSafeAreaCoordinateDetection = false;
|
|
48
|
+
// Track previous safe-area state to avoid redundant DOM writes
|
|
49
|
+
this.prevSafeAreaState = { top: false, bottom: false, left: false, right: false };
|
|
47
50
|
this.presented = false;
|
|
48
51
|
/** @internal */
|
|
49
52
|
this.hasController = false;
|
|
@@ -234,7 +237,8 @@ export class Modal {
|
|
|
234
237
|
}
|
|
235
238
|
}
|
|
236
239
|
onWindowResize() {
|
|
237
|
-
//
|
|
240
|
+
// Invalidate safe-area cache on resize (device rotation may change values)
|
|
241
|
+
this.cachedSafeAreas = undefined;
|
|
238
242
|
this.updateSafeAreaOverrides();
|
|
239
243
|
// Only handle view transition for iOS card modals when no custom animations are provided
|
|
240
244
|
if (getIonMode(this) !== 'ios' || !this.presentingElement || this.enterAnimation || this.leaveAnimation) {
|
|
@@ -259,6 +263,8 @@ export class Modal {
|
|
|
259
263
|
this.triggerController.removeClickListener();
|
|
260
264
|
this.cleanupViewTransitionListener();
|
|
261
265
|
this.cleanupParentRemovalObserver();
|
|
266
|
+
// Reset safe-area state to handle removal without dismiss (e.g., framework unmount)
|
|
267
|
+
this.resetSafeAreaState();
|
|
262
268
|
}
|
|
263
269
|
componentWillLoad() {
|
|
264
270
|
var _a;
|
|
@@ -693,8 +699,28 @@ export class Modal {
|
|
|
693
699
|
*/
|
|
694
700
|
applyFullscreenSafeArea() {
|
|
695
701
|
this.skipSafeAreaCoordinateDetection = true;
|
|
702
|
+
this.updateFooterPadding();
|
|
703
|
+
// Watch for dynamic footer additions/removals (e.g., async data loading)
|
|
704
|
+
// Use subtree:true to support wrapped footers in framework components
|
|
705
|
+
// (e.g., <my-footer><ion-footer>...</ion-footer></my-footer>)
|
|
706
|
+
if (!this.footerObserver && win !== undefined && 'MutationObserver' in win) {
|
|
707
|
+
this.footerObserver = new MutationObserver(() => this.updateFooterPadding());
|
|
708
|
+
this.footerObserver.observe(this.el, { childList: true, subtree: true });
|
|
709
|
+
}
|
|
710
|
+
}
|
|
711
|
+
/**
|
|
712
|
+
* Updates wrapper padding based on footer presence.
|
|
713
|
+
* Called initially and when footer is dynamically added/removed.
|
|
714
|
+
*/
|
|
715
|
+
updateFooterPadding() {
|
|
716
|
+
if (!this.wrapperEl)
|
|
717
|
+
return;
|
|
696
718
|
const hasFooter = this.el.querySelector('ion-footer') !== null;
|
|
697
|
-
if (
|
|
719
|
+
if (hasFooter) {
|
|
720
|
+
this.wrapperEl.style.removeProperty('padding-bottom');
|
|
721
|
+
this.wrapperEl.style.removeProperty('box-sizing');
|
|
722
|
+
}
|
|
723
|
+
else {
|
|
698
724
|
this.wrapperEl.style.setProperty('padding-bottom', 'var(--ion-safe-area-bottom, 0px)');
|
|
699
725
|
this.wrapperEl.style.setProperty('box-sizing', 'border-box');
|
|
700
726
|
}
|
|
@@ -710,23 +736,52 @@ export class Modal {
|
|
|
710
736
|
style.setProperty('--ion-safe-area-left', '0px');
|
|
711
737
|
style.setProperty('--ion-safe-area-right', '0px');
|
|
712
738
|
}
|
|
739
|
+
/**
|
|
740
|
+
* Resets all safe-area related state and styles.
|
|
741
|
+
* Called during dismiss and disconnectedCallback to ensure clean state
|
|
742
|
+
* for re-presentation of inline modals.
|
|
743
|
+
*/
|
|
744
|
+
resetSafeAreaState() {
|
|
745
|
+
var _a;
|
|
746
|
+
this.skipSafeAreaCoordinateDetection = false;
|
|
747
|
+
this.cachedSafeAreas = undefined;
|
|
748
|
+
this.prevSafeAreaState = { top: false, bottom: false, left: false, right: false };
|
|
749
|
+
(_a = this.footerObserver) === null || _a === void 0 ? void 0 : _a.disconnect();
|
|
750
|
+
this.footerObserver = undefined;
|
|
751
|
+
// Clear wrapper styles that may have been set for safe-area handling
|
|
752
|
+
if (this.wrapperEl) {
|
|
753
|
+
this.wrapperEl.style.removeProperty('padding-bottom');
|
|
754
|
+
this.wrapperEl.style.removeProperty('box-sizing');
|
|
755
|
+
}
|
|
756
|
+
// Clear safe-area CSS variable overrides
|
|
757
|
+
const style = this.el.style;
|
|
758
|
+
style.removeProperty('--ion-safe-area-top');
|
|
759
|
+
style.removeProperty('--ion-safe-area-bottom');
|
|
760
|
+
style.removeProperty('--ion-safe-area-left');
|
|
761
|
+
style.removeProperty('--ion-safe-area-right');
|
|
762
|
+
}
|
|
713
763
|
/**
|
|
714
764
|
* Gets the root safe-area values from the document element.
|
|
715
|
-
*
|
|
765
|
+
* Uses cached values during gestures to avoid getComputedStyle calls.
|
|
716
766
|
*/
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
767
|
+
getSafeAreaValues() {
|
|
768
|
+
if (!this.cachedSafeAreas) {
|
|
769
|
+
const rootStyle = getComputedStyle(document.documentElement);
|
|
770
|
+
this.cachedSafeAreas = {
|
|
771
|
+
top: parseFloat(rootStyle.getPropertyValue('--ion-safe-area-top')) || 0,
|
|
772
|
+
bottom: parseFloat(rootStyle.getPropertyValue('--ion-safe-area-bottom')) || 0,
|
|
773
|
+
left: parseFloat(rootStyle.getPropertyValue('--ion-safe-area-left')) || 0,
|
|
774
|
+
right: parseFloat(rootStyle.getPropertyValue('--ion-safe-area-right')) || 0,
|
|
775
|
+
};
|
|
776
|
+
}
|
|
777
|
+
return this.cachedSafeAreas;
|
|
725
778
|
}
|
|
726
779
|
/**
|
|
727
780
|
* Updates safe-area CSS variable overrides based on whether the modal
|
|
728
781
|
* extends into each safe-area region. Called after animation
|
|
729
782
|
* and during gestures to handle dynamic position changes.
|
|
783
|
+
*
|
|
784
|
+
* Optimized to avoid redundant DOM writes by tracking previous state.
|
|
730
785
|
*/
|
|
731
786
|
updateSafeAreaOverrides() {
|
|
732
787
|
if (this.skipSafeAreaCoordinateDetection) {
|
|
@@ -737,20 +792,34 @@ export class Modal {
|
|
|
737
792
|
return;
|
|
738
793
|
}
|
|
739
794
|
const rect = wrapper.getBoundingClientRect();
|
|
740
|
-
const safeAreas = this.
|
|
795
|
+
const safeAreas = this.getSafeAreaValues();
|
|
741
796
|
const extendsIntoTop = rect.top < safeAreas.top;
|
|
742
797
|
const extendsIntoBottom = rect.bottom > window.innerHeight - safeAreas.bottom;
|
|
743
798
|
const extendsIntoLeft = rect.left < safeAreas.left;
|
|
744
799
|
const extendsIntoRight = rect.right > window.innerWidth - safeAreas.right;
|
|
800
|
+
// Only update DOM when state actually changes
|
|
801
|
+
const prev = this.prevSafeAreaState;
|
|
745
802
|
const style = this.el.style;
|
|
746
|
-
extendsIntoTop
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
803
|
+
if (extendsIntoTop !== prev.top) {
|
|
804
|
+
extendsIntoTop ? style.removeProperty('--ion-safe-area-top') : style.setProperty('--ion-safe-area-top', '0px');
|
|
805
|
+
prev.top = extendsIntoTop;
|
|
806
|
+
}
|
|
807
|
+
if (extendsIntoBottom !== prev.bottom) {
|
|
808
|
+
extendsIntoBottom
|
|
809
|
+
? style.removeProperty('--ion-safe-area-bottom')
|
|
810
|
+
: style.setProperty('--ion-safe-area-bottom', '0px');
|
|
811
|
+
prev.bottom = extendsIntoBottom;
|
|
812
|
+
}
|
|
813
|
+
if (extendsIntoLeft !== prev.left) {
|
|
814
|
+
extendsIntoLeft ? style.removeProperty('--ion-safe-area-left') : style.setProperty('--ion-safe-area-left', '0px');
|
|
815
|
+
prev.left = extendsIntoLeft;
|
|
816
|
+
}
|
|
817
|
+
if (extendsIntoRight !== prev.right) {
|
|
818
|
+
extendsIntoRight
|
|
819
|
+
? style.removeProperty('--ion-safe-area-right')
|
|
820
|
+
: style.setProperty('--ion-safe-area-right', '0px');
|
|
821
|
+
prev.right = extendsIntoRight;
|
|
822
|
+
}
|
|
754
823
|
}
|
|
755
824
|
sheetOnDismiss() {
|
|
756
825
|
/**
|
|
@@ -844,8 +913,8 @@ export class Modal {
|
|
|
844
913
|
}
|
|
845
914
|
this.currentBreakpoint = undefined;
|
|
846
915
|
this.animation = undefined;
|
|
847
|
-
// Reset safe-area
|
|
848
|
-
this.
|
|
916
|
+
// Reset safe-area state for potential re-presentation
|
|
917
|
+
this.resetSafeAreaState();
|
|
849
918
|
unlock();
|
|
850
919
|
return dismissed;
|
|
851
920
|
}
|
|
@@ -1103,20 +1172,20 @@ export class Modal {
|
|
|
1103
1172
|
const isCardModal = presentingElement !== undefined && mode === 'ios';
|
|
1104
1173
|
const isHandleCycle = handleBehavior === 'cycle';
|
|
1105
1174
|
const isSheetModalWithHandle = isSheetModal && showHandle;
|
|
1106
|
-
return (h(Host, Object.assign({ key: '
|
|
1175
|
+
return (h(Host, Object.assign({ key: '44022099fcaf047b97d1c2cb45b9b51c930e707c', "no-router": true,
|
|
1107
1176
|
// Allow the modal to be navigable when the handle is focusable
|
|
1108
1177
|
tabIndex: isHandleCycle && isSheetModalWithHandle ? 0 : -1 }, htmlAttributes, { style: {
|
|
1109
1178
|
zIndex: `${20000 + this.overlayIndex}`,
|
|
1110
|
-
}, 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: '
|
|
1179
|
+
}, 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: 'ddd7e4f6eef51ac1f62ac70e0af10fb01e707f07', ref: (el) => (this.backdropEl = el), visible: this.showBackdrop, tappable: this.backdropDismiss, part: "backdrop" }), mode === 'ios' && h("div", { key: '58620980e3e4ec273c6787bde026e1c010b904b7', class: "modal-shadow" }), h("div", Object.assign({ key: '3fb7f6218644ba898fc504467775593eb89426a0',
|
|
1111
1180
|
/*
|
|
1112
1181
|
role and aria-modal must be used on the
|
|
1113
1182
|
same element. They must also be set inside the
|
|
1114
1183
|
shadow DOM otherwise ion-button will not be highlighted
|
|
1115
1184
|
when using VoiceOver: https://bugs.webkit.org/show_bug.cgi?id=247134
|
|
1116
1185
|
*/
|
|
1117
|
-
role: "dialog" }, inheritedAttributes, { "aria-modal": "true", class: "modal-wrapper ion-overlay-wrapper", part: "content", ref: (el) => (this.wrapperEl = el) }), showHandle && (h("button", { key: '
|
|
1186
|
+
role: "dialog" }, inheritedAttributes, { "aria-modal": "true", class: "modal-wrapper ion-overlay-wrapper", part: "content", ref: (el) => (this.wrapperEl = el) }), showHandle && (h("button", { key: '9745cd590fdaa9d023a14b487ec2c87ddbafd7f7', class: "modal-handle",
|
|
1118
1187
|
// Prevents the handle from receiving keyboard focus when it does not cycle
|
|
1119
|
-
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: '
|
|
1188
|
+
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: 'b9a8b5d2d3d3c9b06f99179f496c9f08907d0bad', onSlotchange: this.onSlotChange }))));
|
|
1120
1189
|
}
|
|
1121
1190
|
static get is() { return "ion-modal"; }
|
|
1122
1191
|
static get encapsulation() { return "shadow"; }
|
|
@@ -28,7 +28,7 @@ export const mdEnterAnimation = (baseEl, opts) => {
|
|
|
28
28
|
};
|
|
29
29
|
const results = getPopoverPosition(isRTL, contentWidth, contentHeight, 0, 0, reference, side, align, defaultPosition, trigger, ev);
|
|
30
30
|
const padding = size === 'cover' ? 0 : POPOVER_MD_BODY_PADDING;
|
|
31
|
-
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);
|
|
31
|
+
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);
|
|
32
32
|
/**
|
|
33
33
|
* Safe area CSS variable adjustments.
|
|
34
34
|
* When the popover is positioned near an edge, we add the corresponding
|
|
@@ -37,14 +37,23 @@ export const mdEnterAnimation = (baseEl, opts) => {
|
|
|
37
37
|
*/
|
|
38
38
|
const safeAreaTop = ' + var(--ion-safe-area-top, 0)';
|
|
39
39
|
const safeAreaBottom = ' + var(--ion-safe-area-bottom, 0)';
|
|
40
|
+
const safeAreaLeft = ' + var(--ion-safe-area-left, 0)';
|
|
41
|
+
const safeAreaRight = ' - var(--ion-safe-area-right, 0)';
|
|
40
42
|
let topValue = `${top}px`;
|
|
41
43
|
let bottomValue = bottom !== undefined ? `${bottom}px` : undefined;
|
|
44
|
+
let leftValue = `${left}px`;
|
|
42
45
|
if (checkSafeAreaTop) {
|
|
43
46
|
topValue = `${top}px${safeAreaTop}`;
|
|
44
47
|
}
|
|
45
48
|
if (checkSafeAreaBottom && bottomValue !== undefined) {
|
|
46
49
|
bottomValue = `${bottom}px${safeAreaBottom}`;
|
|
47
50
|
}
|
|
51
|
+
if (checkSafeAreaLeft) {
|
|
52
|
+
leftValue = `${left}px${safeAreaLeft}`;
|
|
53
|
+
}
|
|
54
|
+
if (checkSafeAreaRight) {
|
|
55
|
+
leftValue = `${left}px${safeAreaRight}`;
|
|
56
|
+
}
|
|
48
57
|
const baseAnimation = createAnimation();
|
|
49
58
|
const backdropAnimation = createAnimation();
|
|
50
59
|
const wrapperAnimation = createAnimation();
|
|
@@ -62,7 +71,7 @@ export const mdEnterAnimation = (baseEl, opts) => {
|
|
|
62
71
|
.addElement(contentEl)
|
|
63
72
|
.beforeStyles({
|
|
64
73
|
top: `calc(${topValue} + var(--offset-y, 0px))`,
|
|
65
|
-
left: `calc(${
|
|
74
|
+
left: `calc(${leftValue} + var(--offset-x, 0px))`,
|
|
66
75
|
'transform-origin': `${originY} ${originX}`,
|
|
67
76
|
})
|
|
68
77
|
.beforeAddWrite(() => {
|