@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/hydrate/index.js CHANGED
@@ -10583,7 +10583,11 @@ class Content {
10583
10583
  this.inheritedAttributes = inheritAriaAttributes(this.el);
10584
10584
  }
10585
10585
  connectedCallback() {
10586
- this.isMainContent = this.el.closest('ion-menu, ion-popover, ion-modal') === null;
10586
+ var _a;
10587
+ // Content is "main" if not inside menu/popover/modal and not nested in another ion-content
10588
+ this.isMainContent =
10589
+ this.el.closest('ion-menu, ion-popover, ion-modal') === null &&
10590
+ ((_a = this.el.parentElement) === null || _a === void 0 ? void 0 : _a.closest('ion-content')) === null;
10587
10591
  // Detect sibling header/footer for safe-area handling
10588
10592
  this.detectSiblingElements();
10589
10593
  /**
@@ -10616,21 +10620,48 @@ class Content {
10616
10620
  * bubbles, we can catch any instances of child tab bars loading by listening
10617
10621
  * on IonTabs.
10618
10622
  */
10619
- this.tabsLoadCallback = () => this.resize();
10623
+ this.tabsLoadCallback = () => {
10624
+ this.resize();
10625
+ // Re-detect footer when tab bar loads (it may not exist during initial detection)
10626
+ this.updateSiblingDetection();
10627
+ };
10620
10628
  closestTabs.addEventListener('ionTabBarLoaded', this.tabsLoadCallback);
10621
10629
  }
10622
10630
  }
10623
10631
  }
10624
10632
  /**
10625
- * Detects sibling ion-header and ion-footer elements.
10626
- * When these are absent, content needs to handle safe-area padding directly.
10633
+ * Detects sibling ion-header and ion-footer elements and sets up
10634
+ * a mutation observer to handle dynamic changes (e.g., conditional rendering).
10627
10635
  */
10628
10636
  detectSiblingElements() {
10629
- // Check parent element for sibling header/footer.
10637
+ this.updateSiblingDetection();
10638
+ // Watch for dynamic header/footer changes (common in React conditional rendering)
10639
+ const parent = this.el.parentElement;
10640
+ if (parent && !this.parentMutationObserver && win$1 !== undefined && 'MutationObserver' in win$1) {
10641
+ this.parentMutationObserver = new MutationObserver(() => {
10642
+ this.updateSiblingDetection();
10643
+ });
10644
+ this.parentMutationObserver.observe(parent, { childList: true });
10645
+ }
10646
+ }
10647
+ /**
10648
+ * Updates hasHeader/hasFooter based on current DOM state.
10649
+ * Checks both direct siblings and elements wrapped in custom components
10650
+ * (e.g., <my-header><ion-header>...</ion-header></my-header>).
10651
+ */
10652
+ updateSiblingDetection() {
10630
10653
  const parent = this.el.parentElement;
10631
10654
  if (parent) {
10655
+ // First check for direct ion-header/ion-footer siblings
10632
10656
  this.hasHeader = parent.querySelector(':scope > ion-header') !== null;
10633
10657
  this.hasFooter = parent.querySelector(':scope > ion-footer') !== null;
10658
+ // If not found, check if any sibling contains them (wrapped components)
10659
+ if (!this.hasHeader) {
10660
+ this.hasHeader = this.siblingContainsElement(parent, 'ion-header');
10661
+ }
10662
+ if (!this.hasFooter) {
10663
+ this.hasFooter = this.siblingContainsElement(parent, 'ion-footer');
10664
+ }
10634
10665
  }
10635
10666
  // If no footer found, check if we're inside ion-tabs which has ion-tab-bar
10636
10667
  if (!this.hasFooter) {
@@ -10640,8 +10671,28 @@ class Content {
10640
10671
  }
10641
10672
  }
10642
10673
  }
10674
+ /**
10675
+ * Checks if any sibling element of ion-content contains the specified element.
10676
+ * Only searches one level deep to avoid finding elements in nested pages.
10677
+ */
10678
+ siblingContainsElement(parent, tagName) {
10679
+ for (const sibling of parent.children) {
10680
+ // Skip ion-content itself
10681
+ if (sibling === this.el)
10682
+ continue;
10683
+ // Check if this sibling contains the target element as an immediate child
10684
+ if (sibling.querySelector(`:scope > ${tagName}`) !== null) {
10685
+ return true;
10686
+ }
10687
+ }
10688
+ return false;
10689
+ }
10643
10690
  disconnectedCallback() {
10691
+ var _a;
10644
10692
  this.onScrollEnd();
10693
+ // Clean up mutation observer to prevent memory leaks
10694
+ (_a = this.parentMutationObserver) === null || _a === void 0 ? void 0 : _a.disconnect();
10695
+ this.parentMutationObserver = undefined;
10645
10696
  if (hasLazyBuild(this.el)) {
10646
10697
  /**
10647
10698
  * The event listener and tabs caches need to
@@ -10876,7 +10927,7 @@ class Content {
10876
10927
  const forceOverscroll = this.shouldForceOverscroll();
10877
10928
  const transitionShadow = mode === 'ios';
10878
10929
  this.resize();
10879
- return (hAsync(Host, Object.assign({ key: '83665c0e35e4f4117709606e47d27ad36e343458', role: isMainContent ? 'main' : undefined, class: createColorClasses$1(this.color, {
10930
+ return (hAsync(Host, Object.assign({ key: 'f7218f733e4022a30875441bd949747537d28aa1', role: isMainContent ? 'main' : undefined, class: createColorClasses$1(this.color, {
10880
10931
  [mode]: true,
10881
10932
  'content-sizing': hostContext('ion-popover', this.el),
10882
10933
  overscroll: forceOverscroll,
@@ -10886,12 +10937,12 @@ class Content {
10886
10937
  }), style: {
10887
10938
  '--offset-top': `${this.cTop}px`,
10888
10939
  '--offset-bottom': `${this.cBottom}px`,
10889
- } }, inheritedAttributes), hAsync("div", { key: '75d7cf9315bc8dfb150c3b5bcc356a1f9c793b5a', ref: (el) => (this.backgroundContentEl = el), id: "background-content", part: "background" }), fixedSlotPlacement === 'before' ? hAsync("slot", { name: "fixed" }) : null, hAsync("div", { key: 'f68bc5843c93ed6f32e998b80c5edc553c77a2d7', class: {
10940
+ } }, inheritedAttributes), hAsync("div", { key: 'b735ec68c18c0b99c3595bb194029830e6542cde', ref: (el) => (this.backgroundContentEl = el), id: "background-content", part: "background" }), fixedSlotPlacement === 'before' ? hAsync("slot", { name: "fixed" }) : null, hAsync("div", { key: 'e76c00d030342d44ade6648c3f9e32ca990787ba', class: {
10890
10941
  'inner-scroll': true,
10891
10942
  'scroll-x': scrollX,
10892
10943
  'scroll-y': scrollY,
10893
10944
  overscroll: (scrollX || scrollY) && forceOverscroll,
10894
- }, ref: (scrollEl) => (this.scrollEl = scrollEl), onScroll: this.scrollEvents ? (ev) => this.onScroll(ev) : undefined, part: "scroll" }, hAsync("slot", { key: '8d4b2be00f036f6a24bfa65e6324ca715dd93b60' })), transitionShadow ? (hAsync("div", { class: "transition-effect" }, hAsync("div", { class: "transition-cover" }), hAsync("div", { class: "transition-shadow" }))) : null, fixedSlotPlacement === 'after' ? hAsync("slot", { name: "fixed" }) : null));
10945
+ }, ref: (scrollEl) => (this.scrollEl = scrollEl), onScroll: this.scrollEvents ? (ev) => this.onScroll(ev) : undefined, part: "scroll" }, hAsync("slot", { key: '9049be4cea9b5da5ec1e1012248b05286fddeb7a' })), transitionShadow ? (hAsync("div", { class: "transition-effect" }, hAsync("div", { class: "transition-cover" }), hAsync("div", { class: "transition-shadow" }))) : null, fixedSlotPlacement === 'after' ? hAsync("slot", { name: "fixed" }) : null));
10895
10946
  }
10896
10947
  get el() { return getElement(this); }
10897
10948
  static get style() { return contentCss; }
@@ -22828,6 +22879,8 @@ class Modal {
22828
22879
  this.gestureAnimationDismissing = false;
22829
22880
  // Whether to skip coordinate-based safe-area detection (for fullscreen phone modals)
22830
22881
  this.skipSafeAreaCoordinateDetection = false;
22882
+ // Track previous safe-area state to avoid redundant DOM writes
22883
+ this.prevSafeAreaState = { top: false, bottom: false, left: false, right: false };
22831
22884
  this.presented = false;
22832
22885
  /** @internal */
22833
22886
  this.hasController = false;
@@ -23018,7 +23071,8 @@ class Modal {
23018
23071
  }
23019
23072
  }
23020
23073
  onWindowResize() {
23021
- // Update safe-area overrides for all modal types on resize
23074
+ // Invalidate safe-area cache on resize (device rotation may change values)
23075
+ this.cachedSafeAreas = undefined;
23022
23076
  this.updateSafeAreaOverrides();
23023
23077
  // Only handle view transition for iOS card modals when no custom animations are provided
23024
23078
  if (getIonMode$1(this) !== 'ios' || !this.presentingElement || this.enterAnimation || this.leaveAnimation) {
@@ -23043,6 +23097,8 @@ class Modal {
23043
23097
  this.triggerController.removeClickListener();
23044
23098
  this.cleanupViewTransitionListener();
23045
23099
  this.cleanupParentRemovalObserver();
23100
+ // Reset safe-area state to handle removal without dismiss (e.g., framework unmount)
23101
+ this.resetSafeAreaState();
23046
23102
  }
23047
23103
  componentWillLoad() {
23048
23104
  var _a;
@@ -23477,8 +23533,28 @@ class Modal {
23477
23533
  */
23478
23534
  applyFullscreenSafeArea() {
23479
23535
  this.skipSafeAreaCoordinateDetection = true;
23536
+ this.updateFooterPadding();
23537
+ // Watch for dynamic footer additions/removals (e.g., async data loading)
23538
+ // Use subtree:true to support wrapped footers in framework components
23539
+ // (e.g., <my-footer><ion-footer>...</ion-footer></my-footer>)
23540
+ if (!this.footerObserver && win$1 !== undefined && 'MutationObserver' in win$1) {
23541
+ this.footerObserver = new MutationObserver(() => this.updateFooterPadding());
23542
+ this.footerObserver.observe(this.el, { childList: true, subtree: true });
23543
+ }
23544
+ }
23545
+ /**
23546
+ * Updates wrapper padding based on footer presence.
23547
+ * Called initially and when footer is dynamically added/removed.
23548
+ */
23549
+ updateFooterPadding() {
23550
+ if (!this.wrapperEl)
23551
+ return;
23480
23552
  const hasFooter = this.el.querySelector('ion-footer') !== null;
23481
- if (!hasFooter && this.wrapperEl) {
23553
+ if (hasFooter) {
23554
+ this.wrapperEl.style.removeProperty('padding-bottom');
23555
+ this.wrapperEl.style.removeProperty('box-sizing');
23556
+ }
23557
+ else {
23482
23558
  this.wrapperEl.style.setProperty('padding-bottom', 'var(--ion-safe-area-bottom, 0px)');
23483
23559
  this.wrapperEl.style.setProperty('box-sizing', 'border-box');
23484
23560
  }
@@ -23495,22 +23571,51 @@ class Modal {
23495
23571
  style.setProperty('--ion-safe-area-right', '0px');
23496
23572
  }
23497
23573
  /**
23498
- * Gets the root safe-area values from the document element.
23499
- * These represent the actual device safe areas before any overlay overrides.
23574
+ * Resets all safe-area related state and styles.
23575
+ * Called during dismiss and disconnectedCallback to ensure clean state
23576
+ * for re-presentation of inline modals.
23500
23577
  */
23501
- getRootSafeAreaValues() {
23502
- const rootStyle = getComputedStyle(document.documentElement);
23503
- return {
23504
- top: parseFloat(rootStyle.getPropertyValue('--ion-safe-area-top')) || 0,
23505
- bottom: parseFloat(rootStyle.getPropertyValue('--ion-safe-area-bottom')) || 0,
23506
- left: parseFloat(rootStyle.getPropertyValue('--ion-safe-area-left')) || 0,
23507
- right: parseFloat(rootStyle.getPropertyValue('--ion-safe-area-right')) || 0,
23508
- };
23578
+ resetSafeAreaState() {
23579
+ var _a;
23580
+ this.skipSafeAreaCoordinateDetection = false;
23581
+ this.cachedSafeAreas = undefined;
23582
+ this.prevSafeAreaState = { top: false, bottom: false, left: false, right: false };
23583
+ (_a = this.footerObserver) === null || _a === void 0 ? void 0 : _a.disconnect();
23584
+ this.footerObserver = undefined;
23585
+ // Clear wrapper styles that may have been set for safe-area handling
23586
+ if (this.wrapperEl) {
23587
+ this.wrapperEl.style.removeProperty('padding-bottom');
23588
+ this.wrapperEl.style.removeProperty('box-sizing');
23589
+ }
23590
+ // Clear safe-area CSS variable overrides
23591
+ const style = this.el.style;
23592
+ style.removeProperty('--ion-safe-area-top');
23593
+ style.removeProperty('--ion-safe-area-bottom');
23594
+ style.removeProperty('--ion-safe-area-left');
23595
+ style.removeProperty('--ion-safe-area-right');
23596
+ }
23597
+ /**
23598
+ * Gets the root safe-area values from the document element.
23599
+ * Uses cached values during gestures to avoid getComputedStyle calls.
23600
+ */
23601
+ getSafeAreaValues() {
23602
+ if (!this.cachedSafeAreas) {
23603
+ const rootStyle = getComputedStyle(document.documentElement);
23604
+ this.cachedSafeAreas = {
23605
+ top: parseFloat(rootStyle.getPropertyValue('--ion-safe-area-top')) || 0,
23606
+ bottom: parseFloat(rootStyle.getPropertyValue('--ion-safe-area-bottom')) || 0,
23607
+ left: parseFloat(rootStyle.getPropertyValue('--ion-safe-area-left')) || 0,
23608
+ right: parseFloat(rootStyle.getPropertyValue('--ion-safe-area-right')) || 0,
23609
+ };
23610
+ }
23611
+ return this.cachedSafeAreas;
23509
23612
  }
23510
23613
  /**
23511
23614
  * Updates safe-area CSS variable overrides based on whether the modal
23512
23615
  * extends into each safe-area region. Called after animation
23513
23616
  * and during gestures to handle dynamic position changes.
23617
+ *
23618
+ * Optimized to avoid redundant DOM writes by tracking previous state.
23514
23619
  */
23515
23620
  updateSafeAreaOverrides() {
23516
23621
  if (this.skipSafeAreaCoordinateDetection) {
@@ -23521,20 +23626,34 @@ class Modal {
23521
23626
  return;
23522
23627
  }
23523
23628
  const rect = wrapper.getBoundingClientRect();
23524
- const safeAreas = this.getRootSafeAreaValues();
23629
+ const safeAreas = this.getSafeAreaValues();
23525
23630
  const extendsIntoTop = rect.top < safeAreas.top;
23526
23631
  const extendsIntoBottom = rect.bottom > window.innerHeight - safeAreas.bottom;
23527
23632
  const extendsIntoLeft = rect.left < safeAreas.left;
23528
23633
  const extendsIntoRight = rect.right > window.innerWidth - safeAreas.right;
23634
+ // Only update DOM when state actually changes
23635
+ const prev = this.prevSafeAreaState;
23529
23636
  const style = this.el.style;
23530
- extendsIntoTop ? style.removeProperty('--ion-safe-area-top') : style.setProperty('--ion-safe-area-top', '0px');
23531
- extendsIntoBottom
23532
- ? style.removeProperty('--ion-safe-area-bottom')
23533
- : style.setProperty('--ion-safe-area-bottom', '0px');
23534
- extendsIntoLeft ? style.removeProperty('--ion-safe-area-left') : style.setProperty('--ion-safe-area-left', '0px');
23535
- extendsIntoRight
23536
- ? style.removeProperty('--ion-safe-area-right')
23537
- : style.setProperty('--ion-safe-area-right', '0px');
23637
+ if (extendsIntoTop !== prev.top) {
23638
+ extendsIntoTop ? style.removeProperty('--ion-safe-area-top') : style.setProperty('--ion-safe-area-top', '0px');
23639
+ prev.top = extendsIntoTop;
23640
+ }
23641
+ if (extendsIntoBottom !== prev.bottom) {
23642
+ extendsIntoBottom
23643
+ ? style.removeProperty('--ion-safe-area-bottom')
23644
+ : style.setProperty('--ion-safe-area-bottom', '0px');
23645
+ prev.bottom = extendsIntoBottom;
23646
+ }
23647
+ if (extendsIntoLeft !== prev.left) {
23648
+ extendsIntoLeft ? style.removeProperty('--ion-safe-area-left') : style.setProperty('--ion-safe-area-left', '0px');
23649
+ prev.left = extendsIntoLeft;
23650
+ }
23651
+ if (extendsIntoRight !== prev.right) {
23652
+ extendsIntoRight
23653
+ ? style.removeProperty('--ion-safe-area-right')
23654
+ : style.setProperty('--ion-safe-area-right', '0px');
23655
+ prev.right = extendsIntoRight;
23656
+ }
23538
23657
  }
23539
23658
  sheetOnDismiss() {
23540
23659
  /**
@@ -23628,8 +23747,8 @@ class Modal {
23628
23747
  }
23629
23748
  this.currentBreakpoint = undefined;
23630
23749
  this.animation = undefined;
23631
- // Reset safe-area detection flag for potential re-presentation
23632
- this.skipSafeAreaCoordinateDetection = false;
23750
+ // Reset safe-area state for potential re-presentation
23751
+ this.resetSafeAreaState();
23633
23752
  unlock();
23634
23753
  return dismissed;
23635
23754
  }
@@ -23879,20 +23998,20 @@ class Modal {
23879
23998
  const isCardModal = presentingElement !== undefined && mode === 'ios';
23880
23999
  const isHandleCycle = handleBehavior === 'cycle';
23881
24000
  const isSheetModalWithHandle = isSheetModal && showHandle;
23882
- return (hAsync(Host, Object.assign({ key: '07ebca6a70eb99f8a2236e1d66a03097a7bb67d8', "no-router": true,
24001
+ return (hAsync(Host, Object.assign({ key: '44022099fcaf047b97d1c2cb45b9b51c930e707c', "no-router": true,
23883
24002
  // Allow the modal to be navigable when the handle is focusable
23884
24003
  tabIndex: isHandleCycle && isSheetModalWithHandle ? 0 : -1 }, htmlAttributes, { style: {
23885
24004
  zIndex: `${20000 + this.overlayIndex}`,
23886
- }, 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: '1b6850d9b9f6e8f3865b49e0a14399e2ef43a5d6', ref: (el) => (this.backdropEl = el), visible: this.showBackdrop, tappable: this.backdropDismiss, part: "backdrop" }), mode === 'ios' && hAsync("div", { key: 'eab52c0ebccb820781e92392dc6fa90db93525d5', class: "modal-shadow" }), hAsync("div", Object.assign({ key: 'ab9448cabdf03a633319999771ce1ca1edce5699',
24005
+ }, 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: 'ddd7e4f6eef51ac1f62ac70e0af10fb01e707f07', ref: (el) => (this.backdropEl = el), visible: this.showBackdrop, tappable: this.backdropDismiss, part: "backdrop" }), mode === 'ios' && hAsync("div", { key: '58620980e3e4ec273c6787bde026e1c010b904b7', class: "modal-shadow" }), hAsync("div", Object.assign({ key: '3fb7f6218644ba898fc504467775593eb89426a0',
23887
24006
  /*
23888
24007
  role and aria-modal must be used on the
23889
24008
  same element. They must also be set inside the
23890
24009
  shadow DOM otherwise ion-button will not be highlighted
23891
24010
  when using VoiceOver: https://bugs.webkit.org/show_bug.cgi?id=247134
23892
24011
  */
23893
- role: "dialog" }, inheritedAttributes, { "aria-modal": "true", class: "modal-wrapper ion-overlay-wrapper", part: "content", ref: (el) => (this.wrapperEl = el) }), showHandle && (hAsync("button", { key: 'b2b8c0a8d8add0d43e928dd3d3519f184551e62b', class: "modal-handle",
24012
+ role: "dialog" }, inheritedAttributes, { "aria-modal": "true", class: "modal-wrapper ion-overlay-wrapper", part: "content", ref: (el) => (this.wrapperEl = el) }), showHandle && (hAsync("button", { key: '9745cd590fdaa9d023a14b487ec2c87ddbafd7f7', class: "modal-handle",
23894
24013
  // Prevents the handle from receiving keyboard focus when it does not cycle
23895
- 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: 'b994f206765f7b340971d378f00999c0da334102', onSlotchange: this.onSlotChange }))));
24014
+ 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: 'b9a8b5d2d3d3c9b06f99179f496c9f08907d0bad', onSlotchange: this.onSlotChange }))));
23896
24015
  }
23897
24016
  get el() { return getElement(this); }
23898
24017
  static get watchers() { return {
@@ -27758,7 +27877,7 @@ const mdEnterAnimation$1 = (baseEl, opts) => {
27758
27877
  };
27759
27878
  const results = getPopoverPosition(isRTL, contentWidth, contentHeight, 0, 0, reference, side, align, defaultPosition, trigger, ev);
27760
27879
  const padding = size === 'cover' ? 0 : POPOVER_MD_BODY_PADDING;
27761
- 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);
27880
+ 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);
27762
27881
  /**
27763
27882
  * Safe area CSS variable adjustments.
27764
27883
  * When the popover is positioned near an edge, we add the corresponding
@@ -27767,14 +27886,23 @@ const mdEnterAnimation$1 = (baseEl, opts) => {
27767
27886
  */
27768
27887
  const safeAreaTop = ' + var(--ion-safe-area-top, 0)';
27769
27888
  const safeAreaBottom = ' + var(--ion-safe-area-bottom, 0)';
27889
+ const safeAreaLeft = ' + var(--ion-safe-area-left, 0)';
27890
+ const safeAreaRight = ' - var(--ion-safe-area-right, 0)';
27770
27891
  let topValue = `${top}px`;
27771
27892
  let bottomValue = bottom !== undefined ? `${bottom}px` : undefined;
27893
+ let leftValue = `${left}px`;
27772
27894
  if (checkSafeAreaTop) {
27773
27895
  topValue = `${top}px${safeAreaTop}`;
27774
27896
  }
27775
27897
  if (checkSafeAreaBottom && bottomValue !== undefined) {
27776
27898
  bottomValue = `${bottom}px${safeAreaBottom}`;
27777
27899
  }
27900
+ if (checkSafeAreaLeft) {
27901
+ leftValue = `${left}px${safeAreaLeft}`;
27902
+ }
27903
+ if (checkSafeAreaRight) {
27904
+ leftValue = `${left}px${safeAreaRight}`;
27905
+ }
27778
27906
  const baseAnimation = createAnimation();
27779
27907
  const backdropAnimation = createAnimation();
27780
27908
  const wrapperAnimation = createAnimation();
@@ -27792,7 +27920,7 @@ const mdEnterAnimation$1 = (baseEl, opts) => {
27792
27920
  .addElement(contentEl)
27793
27921
  .beforeStyles({
27794
27922
  top: `calc(${topValue} + var(--offset-y, 0px))`,
27795
- left: `calc(${left}px + var(--offset-x, 0px))`,
27923
+ left: `calc(${leftValue} + var(--offset-x, 0px))`,
27796
27924
  'transform-origin': `${originY} ${originX}`,
27797
27925
  })
27798
27926
  .beforeAddWrite(() => {