@ionic/core 8.7.17-dev.11767984108.1f9159e1 → 8.7.17-dev.11768239180.18ee1069

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.
@@ -1,14 +1,13 @@
1
1
  /*!
2
2
  * (C) Ionic http://ionicframework.com - MIT License
3
3
  */
4
- import { proxyCustomElement, HTMLElement, createEvent, forceUpdate, Build, readTask, h, Host } from '@stencil/core/internal/client';
5
- import { w as win } from './index9.js';
4
+ import { proxyCustomElement, HTMLElement, createEvent, Build, readTask, forceUpdate, h, Host } from '@stencil/core/internal/client';
6
5
  import { i as inheritAriaAttributes, k as hasLazyBuild, c as componentOnReady } from './helpers.js';
7
6
  import { b as getIonMode, a as isPlatform } from './ionic-global.js';
8
7
  import { i as isRTL } from './dir.js';
9
8
  import { c as createColorClasses, h as hostContext } from './theme.js';
10
9
 
11
- const contentCss = ":host{--background:var(--ion-background-color, #fff);--color:var(--ion-text-color, #000);--padding-top:0px;--padding-bottom:0px;--padding-start:0px;--padding-end:0px;--keyboard-offset:0px;--offset-top:0px;--offset-bottom:0px;--overflow:auto;display:block;position:relative;-ms-flex:1;flex:1;width:100%;height:100%;margin:0 !important;padding:0 !important;font-family:var(--ion-font-family, inherit);contain:size style}:host(.ion-color) .inner-scroll{background:var(--ion-color-base);color:var(--ion-color-contrast)}#background-content{left:0px;right:0px;top:calc(var(--offset-top) * -1);bottom:calc(var(--offset-bottom) * -1);position:absolute;background:var(--background)}.inner-scroll{left:0px;right:0px;top:calc(var(--offset-top) * -1);bottom:calc(var(--offset-bottom) * -1);-webkit-padding-start:var(--padding-start);padding-inline-start:var(--padding-start);-webkit-padding-end:var(--padding-end);padding-inline-end:var(--padding-end);padding-top:calc(var(--padding-top) + var(--offset-top));padding-bottom:calc(var(--padding-bottom) + var(--keyboard-offset) + var(--offset-bottom));position:absolute;color:var(--color);-webkit-box-sizing:border-box;box-sizing:border-box;overflow:hidden;-ms-touch-action:pan-x pan-y pinch-zoom;touch-action:pan-x pan-y pinch-zoom}.scroll-y,.scroll-x{-webkit-overflow-scrolling:touch;z-index:0;will-change:scroll-position}.scroll-y{overflow-y:var(--overflow);overscroll-behavior-y:contain}.scroll-x{overflow-x:var(--overflow);overscroll-behavior-x:contain}.overscroll::before,.overscroll::after{position:absolute;width:1px;height:1px;content:\"\"}.overscroll::before{bottom:-1px}.overscroll::after{top:-1px}:host(.content-sizing){display:-ms-flexbox;display:flex;-ms-flex-direction:column;flex-direction:column;min-height:0;contain:none}:host(.content-sizing) .inner-scroll{position:relative;top:0;bottom:0;margin-top:calc(var(--offset-top) * -1);margin-bottom:calc(var(--offset-bottom) * -1)}.transition-effect{display:none;position:absolute;width:100%;height:100vh;opacity:0;pointer-events:none}:host(.content-ltr) .transition-effect{left:-100%;}:host(.content-rtl) .transition-effect{right:-100%;}.transition-cover{position:absolute;right:0;width:100%;height:100%;background:black;opacity:0.1}.transition-shadow{display:block;position:absolute;width:100%;height:100%;-webkit-box-shadow:inset -9px 0 9px 0 rgba(0, 0, 100, 0.03);box-shadow:inset -9px 0 9px 0 rgba(0, 0, 100, 0.03)}:host(.content-ltr) .transition-shadow{right:0;}:host(.content-rtl) .transition-shadow{left:0;-webkit-transform:scaleX(-1);transform:scaleX(-1)}:host(.safe-area-top) #background-content,:host(.safe-area-top) .inner-scroll{top:var(--ion-safe-area-top, 0px)}:host(.safe-area-bottom) #background-content,:host(.safe-area-bottom) .inner-scroll{bottom:var(--ion-safe-area-bottom, 0px)}:host(.safe-area-left) #background-content,:host(.safe-area-left) .inner-scroll{left:var(--ion-safe-area-left, 0px)}:host(.safe-area-right) #background-content,:host(.safe-area-right) .inner-scroll{right:var(--ion-safe-area-right, 0px)}::slotted([slot=fixed]){position:absolute;-webkit-transform:translateZ(0);transform:translateZ(0)}";
10
+ const contentCss = ":host{--background:var(--ion-background-color, #fff);--color:var(--ion-text-color, #000);--padding-top:0px;--padding-bottom:0px;--padding-start:0px;--padding-end:0px;--keyboard-offset:0px;--offset-top:0px;--offset-bottom:0px;--overflow:auto;display:block;position:relative;-ms-flex:1;flex:1;width:100%;height:100%;margin:0 !important;padding:0 !important;font-family:var(--ion-font-family, inherit);contain:size style}:host(.ion-color) .inner-scroll{background:var(--ion-color-base);color:var(--ion-color-contrast)}#background-content{left:0px;right:0px;top:calc(var(--offset-top) * -1);bottom:calc(var(--offset-bottom) * -1);position:absolute;background:var(--background)}.inner-scroll{left:0px;right:0px;top:calc(var(--offset-top) * -1);bottom:calc(var(--offset-bottom) * -1);-webkit-padding-start:var(--padding-start);padding-inline-start:var(--padding-start);-webkit-padding-end:var(--padding-end);padding-inline-end:var(--padding-end);padding-top:calc(var(--padding-top) + var(--offset-top));padding-bottom:calc(var(--padding-bottom) + var(--keyboard-offset) + var(--offset-bottom));position:absolute;color:var(--color);-webkit-box-sizing:border-box;box-sizing:border-box;overflow:hidden;-ms-touch-action:pan-x pan-y pinch-zoom;touch-action:pan-x pan-y pinch-zoom}.scroll-y,.scroll-x{-webkit-overflow-scrolling:touch;z-index:0;will-change:scroll-position}.scroll-y{overflow-y:var(--overflow);overscroll-behavior-y:contain}.scroll-x{overflow-x:var(--overflow);overscroll-behavior-x:contain}.overscroll::before,.overscroll::after{position:absolute;width:1px;height:1px;content:\"\"}.overscroll::before{bottom:-1px}.overscroll::after{top:-1px}:host(.content-sizing){display:-ms-flexbox;display:flex;-ms-flex-direction:column;flex-direction:column;min-height:0;contain:none}:host(.content-sizing) .inner-scroll{position:relative;top:0;bottom:0;margin-top:calc(var(--offset-top) * -1);margin-bottom:calc(var(--offset-bottom) * -1)}.transition-effect{display:none;position:absolute;width:100%;height:100vh;opacity:0;pointer-events:none}:host(.content-ltr) .transition-effect{left:-100%;}:host(.content-rtl) .transition-effect{right:-100%;}.transition-cover{position:absolute;right:0;width:100%;height:100%;background:black;opacity:0.1}.transition-shadow{display:block;position:absolute;width:100%;height:100%;-webkit-box-shadow:inset -9px 0 9px 0 rgba(0, 0, 100, 0.03);box-shadow:inset -9px 0 9px 0 rgba(0, 0, 100, 0.03)}:host(.content-ltr) .transition-shadow{right:0;}:host(.content-rtl) .transition-shadow{left:0;-webkit-transform:scaleX(-1);transform:scaleX(-1)}::slotted([slot=fixed]){position:absolute;-webkit-transform:translateZ(0);transform:translateZ(0)}";
12
11
 
13
12
  const Content = /*@__PURE__*/ proxyCustomElement(class Content extends HTMLElement {
14
13
  constructor(registerHost) {
@@ -29,12 +28,6 @@ const Content = /*@__PURE__*/ proxyCustomElement(class Content extends HTMLEleme
29
28
  this.isMainContent = true;
30
29
  this.resizeTimeout = null;
31
30
  this.inheritedAttributes = {};
32
- /**
33
- * Track whether this content has sibling header/footer elements.
34
- * When absent, we need to apply safe-area padding directly.
35
- */
36
- this.hasHeader = false;
37
- this.hasFooter = false;
38
31
  this.tabsElement = null;
39
32
  // Detail is used in a hot loop in the scroll event, by allocating it here
40
33
  // V8 will be able to inline any read/write to it since it's a monomorphic class.
@@ -89,13 +82,7 @@ const Content = /*@__PURE__*/ proxyCustomElement(class Content extends HTMLEleme
89
82
  this.inheritedAttributes = inheritAriaAttributes(this.el);
90
83
  }
91
84
  connectedCallback() {
92
- var _a;
93
- // Content is "main" if not inside menu/popover/modal and not nested in another ion-content
94
- this.isMainContent =
95
- this.el.closest('ion-menu, ion-popover, ion-modal') === null &&
96
- ((_a = this.el.parentElement) === null || _a === void 0 ? void 0 : _a.closest('ion-content')) === null;
97
- // Detect sibling header/footer for safe-area handling
98
- this.detectSiblingElements();
85
+ this.isMainContent = this.el.closest('ion-menu, ion-popover, ion-modal') === null;
99
86
  /**
100
87
  * The fullscreen content offsets need to be
101
88
  * computed after the tab bar has loaded. Since
@@ -126,101 +113,13 @@ const Content = /*@__PURE__*/ proxyCustomElement(class Content extends HTMLEleme
126
113
  * bubbles, we can catch any instances of child tab bars loading by listening
127
114
  * on IonTabs.
128
115
  */
129
- this.tabsLoadCallback = () => {
130
- this.resize();
131
- // Re-detect footer when tab bar loads (it may not exist during initial detection)
132
- this.updateSiblingDetection();
133
- forceUpdate(this);
134
- };
116
+ this.tabsLoadCallback = () => this.resize();
135
117
  closestTabs.addEventListener('ionTabBarLoaded', this.tabsLoadCallback);
136
118
  }
137
119
  }
138
120
  }
139
- /**
140
- * Detects sibling ion-header and ion-footer elements and sets up
141
- * a mutation observer to handle dynamic changes (e.g., conditional rendering).
142
- */
143
- detectSiblingElements() {
144
- this.updateSiblingDetection();
145
- // Watch for dynamic header/footer changes (common in React conditional rendering)
146
- const parent = this.el.parentElement;
147
- if (parent && !this.parentMutationObserver && win !== undefined && 'MutationObserver' in win) {
148
- this.parentMutationObserver = new MutationObserver(() => {
149
- const prevHasHeader = this.hasHeader;
150
- const prevHasFooter = this.hasFooter;
151
- this.updateSiblingDetection();
152
- // Only trigger re-render if header/footer detection actually changed
153
- if (prevHasHeader !== this.hasHeader || prevHasFooter !== this.hasFooter) {
154
- forceUpdate(this);
155
- }
156
- });
157
- this.parentMutationObserver.observe(parent, { childList: true });
158
- }
159
- // Watch for dynamic tab bar changes in ion-tabs (common in Angular conditional rendering)
160
- const tabs = this.el.closest('ion-tabs');
161
- if (tabs && !this.tabsMutationObserver && win !== undefined && 'MutationObserver' in win) {
162
- this.tabsMutationObserver = new MutationObserver(() => {
163
- const prevHasFooter = this.hasFooter;
164
- this.updateSiblingDetection();
165
- // Only trigger re-render if footer detection actually changed
166
- if (prevHasFooter !== this.hasFooter) {
167
- forceUpdate(this);
168
- }
169
- });
170
- this.tabsMutationObserver.observe(tabs, { childList: true });
171
- }
172
- }
173
- /**
174
- * Updates hasHeader/hasFooter based on current DOM state.
175
- * Checks both direct siblings and elements wrapped in custom components
176
- * (e.g., <my-header><ion-header>...</ion-header></my-header>).
177
- */
178
- updateSiblingDetection() {
179
- const parent = this.el.parentElement;
180
- if (parent) {
181
- // First check for direct ion-header/ion-footer siblings
182
- this.hasHeader = parent.querySelector(':scope > ion-header') !== null;
183
- this.hasFooter = parent.querySelector(':scope > ion-footer') !== null;
184
- // If not found, check if any sibling contains them (wrapped components)
185
- if (!this.hasHeader) {
186
- this.hasHeader = this.siblingContainsElement(parent, 'ion-header');
187
- }
188
- if (!this.hasFooter) {
189
- this.hasFooter = this.siblingContainsElement(parent, 'ion-footer');
190
- }
191
- }
192
- // If no footer found, check if we're inside ion-tabs which has ion-tab-bar
193
- if (!this.hasFooter) {
194
- const tabs = this.el.closest('ion-tabs');
195
- if (tabs) {
196
- this.hasFooter = tabs.querySelector(':scope > ion-tab-bar') !== null;
197
- }
198
- }
199
- }
200
- /**
201
- * Checks if any sibling element of ion-content contains the specified element.
202
- * Only searches one level deep to avoid finding elements in nested pages.
203
- */
204
- siblingContainsElement(parent, tagName) {
205
- for (const sibling of parent.children) {
206
- // Skip ion-content itself
207
- if (sibling === this.el)
208
- continue;
209
- // Check if this sibling contains the target element as an immediate child
210
- if (sibling.querySelector(`:scope > ${tagName}`) !== null) {
211
- return true;
212
- }
213
- }
214
- return false;
215
- }
216
121
  disconnectedCallback() {
217
- var _a, _b;
218
122
  this.onScrollEnd();
219
- // Clean up mutation observers to prevent memory leaks
220
- (_a = this.parentMutationObserver) === null || _a === void 0 ? void 0 : _a.disconnect();
221
- this.parentMutationObserver = undefined;
222
- (_b = this.tabsMutationObserver) === null || _b === void 0 ? void 0 : _b.disconnect();
223
- this.tabsMutationObserver = undefined;
224
123
  if (hasLazyBuild(this.el)) {
225
124
  /**
226
125
  * The event listener and tabs caches need to
@@ -467,30 +366,26 @@ const Content = /*@__PURE__*/ proxyCustomElement(class Content extends HTMLEleme
467
366
  }
468
367
  }
469
368
  render() {
470
- const { fixedSlotPlacement, hasFooter, hasHeader, inheritedAttributes, isMainContent, scrollX, scrollY, el } = this;
369
+ const { fixedSlotPlacement, inheritedAttributes, isMainContent, scrollX, scrollY, el } = this;
471
370
  const rtl = isRTL(el) ? 'rtl' : 'ltr';
472
371
  const mode = getIonMode(this);
473
372
  const forceOverscroll = this.shouldForceOverscroll();
474
373
  const transitionShadow = mode === 'ios';
475
374
  this.resize();
476
- return (h(Host, Object.assign({ key: 'bc3b1ed3c6128b3b3474c052f2b75f3f8ea7a8cb', role: isMainContent ? 'main' : undefined, class: createColorClasses(this.color, {
375
+ return (h(Host, Object.assign({ key: 'cd8781f848d8dc926fe66f43d43c49564425a507', role: isMainContent ? 'main' : undefined, class: createColorClasses(this.color, {
477
376
  [mode]: true,
478
377
  'content-sizing': hostContext('ion-popover', this.el),
479
378
  overscroll: forceOverscroll,
480
379
  [`content-${rtl}`]: true,
481
- 'safe-area-top': isMainContent && !hasHeader,
482
- 'safe-area-bottom': isMainContent && !hasFooter,
483
- 'safe-area-left': isMainContent,
484
- 'safe-area-right': isMainContent,
485
380
  }), style: {
486
381
  '--offset-top': `${this.cTop}px`,
487
382
  '--offset-bottom': `${this.cBottom}px`,
488
- } }, inheritedAttributes), h("div", { key: '251af16d9d5c5bf50f5b9cf14f5002a35ada7409', ref: (el) => (this.backgroundContentEl = el), id: "background-content", part: "background" }), fixedSlotPlacement === 'before' ? h("slot", { name: "fixed" }) : null, h("div", { key: '218f567f5fec257562e5ac1167cdaac9e95bc04d', class: {
383
+ } }, inheritedAttributes), h("div", { key: '95b112d7cae30f22ef778ceffb88edb4d941c170', ref: (el) => (this.backgroundContentEl = el), id: "background-content", part: "background" }), fixedSlotPlacement === 'before' ? h("slot", { name: "fixed" }) : null, h("div", { key: '2fdfcbc39fb66f11b6191911f2941c660f4c12e5', class: {
489
384
  'inner-scroll': true,
490
385
  'scroll-x': scrollX,
491
386
  'scroll-y': scrollY,
492
387
  overscroll: (scrollX || scrollY) && forceOverscroll,
493
- }, ref: (scrollEl) => (this.scrollEl = scrollEl), onScroll: this.scrollEvents ? (ev) => this.onScroll(ev) : undefined, part: "scroll" }, h("slot", { key: '8acb832123f95730d45996bd54ed8f52b366cf74' })), transitionShadow ? (h("div", { class: "transition-effect" }, h("div", { class: "transition-cover" }), h("div", { class: "transition-shadow" }))) : null, fixedSlotPlacement === 'after' ? h("slot", { name: "fixed" }) : null));
388
+ }, ref: (scrollEl) => (this.scrollEl = scrollEl), onScroll: this.scrollEvents ? (ev) => this.onScroll(ev) : undefined, part: "scroll" }, h("slot", { key: '6bc77e0054ec8e21635a7f2abfe0ca46e0962e03' })), transitionShadow ? (h("div", { class: "transition-effect" }, h("div", { class: "transition-cover" }), h("div", { class: "transition-shadow" }))) : null, fixedSlotPlacement === 'after' ? h("slot", { name: "fixed" }) : null));
494
389
  }
495
390
  get el() { return this; }
496
391
  static get style() { return contentCss; }
@@ -6,16 +6,16 @@
6
6
  var index = require('./index-D6Wc6v08.js');
7
7
  var hardwareBackButton = require('./hardware-back-button-VCK4V3mG.js');
8
8
  var ionicGlobal = require('./ionic-global-HMVqOFGO.js');
9
- var index$1 = require('./index-DkNv4J_i.js');
10
9
  var helpers = require('./helpers-DrTqNghc.js');
11
10
  var dir = require('./dir-Cn0z1rJH.js');
12
11
  var theme = require('./theme-CeDs6Hcv.js');
13
- var index$2 = require('./index-CO6eryBo.js');
12
+ var index$1 = require('./index-CO6eryBo.js');
14
13
  var keyboardController = require('./keyboard-controller-GXBiBRKS.js');
15
14
  var cubicBezier = require('./cubic-bezier-DAjy1V-e.js');
16
15
  var frameworkDelegate = require('./framework-delegate-DMJRBuDi.js');
17
16
  var lockController = require('./lock-controller-aDB9wrEf.js');
18
- var index$3 = require('./index-094mMFB-.js');
17
+ var index$2 = require('./index-094mMFB-.js');
18
+ require('./index-DkNv4J_i.js');
19
19
  require('./keyboard-UuAS4D_9.js');
20
20
  require('./capacitor-DmA66EwP.js');
21
21
 
@@ -154,7 +154,7 @@ Buttons.style = {
154
154
  md: buttonsMdCss
155
155
  };
156
156
 
157
- const contentCss = ":host{--background:var(--ion-background-color, #fff);--color:var(--ion-text-color, #000);--padding-top:0px;--padding-bottom:0px;--padding-start:0px;--padding-end:0px;--keyboard-offset:0px;--offset-top:0px;--offset-bottom:0px;--overflow:auto;display:block;position:relative;-ms-flex:1;flex:1;width:100%;height:100%;margin:0 !important;padding:0 !important;font-family:var(--ion-font-family, inherit);contain:size style}:host(.ion-color) .inner-scroll{background:var(--ion-color-base);color:var(--ion-color-contrast)}#background-content{left:0px;right:0px;top:calc(var(--offset-top) * -1);bottom:calc(var(--offset-bottom) * -1);position:absolute;background:var(--background)}.inner-scroll{left:0px;right:0px;top:calc(var(--offset-top) * -1);bottom:calc(var(--offset-bottom) * -1);-webkit-padding-start:var(--padding-start);padding-inline-start:var(--padding-start);-webkit-padding-end:var(--padding-end);padding-inline-end:var(--padding-end);padding-top:calc(var(--padding-top) + var(--offset-top));padding-bottom:calc(var(--padding-bottom) + var(--keyboard-offset) + var(--offset-bottom));position:absolute;color:var(--color);-webkit-box-sizing:border-box;box-sizing:border-box;overflow:hidden;-ms-touch-action:pan-x pan-y pinch-zoom;touch-action:pan-x pan-y pinch-zoom}.scroll-y,.scroll-x{-webkit-overflow-scrolling:touch;z-index:0;will-change:scroll-position}.scroll-y{overflow-y:var(--overflow);overscroll-behavior-y:contain}.scroll-x{overflow-x:var(--overflow);overscroll-behavior-x:contain}.overscroll::before,.overscroll::after{position:absolute;width:1px;height:1px;content:\"\"}.overscroll::before{bottom:-1px}.overscroll::after{top:-1px}:host(.content-sizing){display:-ms-flexbox;display:flex;-ms-flex-direction:column;flex-direction:column;min-height:0;contain:none}:host(.content-sizing) .inner-scroll{position:relative;top:0;bottom:0;margin-top:calc(var(--offset-top) * -1);margin-bottom:calc(var(--offset-bottom) * -1)}.transition-effect{display:none;position:absolute;width:100%;height:100vh;opacity:0;pointer-events:none}:host(.content-ltr) .transition-effect{left:-100%;}:host(.content-rtl) .transition-effect{right:-100%;}.transition-cover{position:absolute;right:0;width:100%;height:100%;background:black;opacity:0.1}.transition-shadow{display:block;position:absolute;width:100%;height:100%;-webkit-box-shadow:inset -9px 0 9px 0 rgba(0, 0, 100, 0.03);box-shadow:inset -9px 0 9px 0 rgba(0, 0, 100, 0.03)}:host(.content-ltr) .transition-shadow{right:0;}:host(.content-rtl) .transition-shadow{left:0;-webkit-transform:scaleX(-1);transform:scaleX(-1)}:host(.safe-area-top) #background-content,:host(.safe-area-top) .inner-scroll{top:var(--ion-safe-area-top, 0px)}:host(.safe-area-bottom) #background-content,:host(.safe-area-bottom) .inner-scroll{bottom:var(--ion-safe-area-bottom, 0px)}:host(.safe-area-left) #background-content,:host(.safe-area-left) .inner-scroll{left:var(--ion-safe-area-left, 0px)}:host(.safe-area-right) #background-content,:host(.safe-area-right) .inner-scroll{right:var(--ion-safe-area-right, 0px)}::slotted([slot=fixed]){position:absolute;-webkit-transform:translateZ(0);transform:translateZ(0)}";
157
+ const contentCss = ":host{--background:var(--ion-background-color, #fff);--color:var(--ion-text-color, #000);--padding-top:0px;--padding-bottom:0px;--padding-start:0px;--padding-end:0px;--keyboard-offset:0px;--offset-top:0px;--offset-bottom:0px;--overflow:auto;display:block;position:relative;-ms-flex:1;flex:1;width:100%;height:100%;margin:0 !important;padding:0 !important;font-family:var(--ion-font-family, inherit);contain:size style}:host(.ion-color) .inner-scroll{background:var(--ion-color-base);color:var(--ion-color-contrast)}#background-content{left:0px;right:0px;top:calc(var(--offset-top) * -1);bottom:calc(var(--offset-bottom) * -1);position:absolute;background:var(--background)}.inner-scroll{left:0px;right:0px;top:calc(var(--offset-top) * -1);bottom:calc(var(--offset-bottom) * -1);-webkit-padding-start:var(--padding-start);padding-inline-start:var(--padding-start);-webkit-padding-end:var(--padding-end);padding-inline-end:var(--padding-end);padding-top:calc(var(--padding-top) + var(--offset-top));padding-bottom:calc(var(--padding-bottom) + var(--keyboard-offset) + var(--offset-bottom));position:absolute;color:var(--color);-webkit-box-sizing:border-box;box-sizing:border-box;overflow:hidden;-ms-touch-action:pan-x pan-y pinch-zoom;touch-action:pan-x pan-y pinch-zoom}.scroll-y,.scroll-x{-webkit-overflow-scrolling:touch;z-index:0;will-change:scroll-position}.scroll-y{overflow-y:var(--overflow);overscroll-behavior-y:contain}.scroll-x{overflow-x:var(--overflow);overscroll-behavior-x:contain}.overscroll::before,.overscroll::after{position:absolute;width:1px;height:1px;content:\"\"}.overscroll::before{bottom:-1px}.overscroll::after{top:-1px}:host(.content-sizing){display:-ms-flexbox;display:flex;-ms-flex-direction:column;flex-direction:column;min-height:0;contain:none}:host(.content-sizing) .inner-scroll{position:relative;top:0;bottom:0;margin-top:calc(var(--offset-top) * -1);margin-bottom:calc(var(--offset-bottom) * -1)}.transition-effect{display:none;position:absolute;width:100%;height:100vh;opacity:0;pointer-events:none}:host(.content-ltr) .transition-effect{left:-100%;}:host(.content-rtl) .transition-effect{right:-100%;}.transition-cover{position:absolute;right:0;width:100%;height:100%;background:black;opacity:0.1}.transition-shadow{display:block;position:absolute;width:100%;height:100%;-webkit-box-shadow:inset -9px 0 9px 0 rgba(0, 0, 100, 0.03);box-shadow:inset -9px 0 9px 0 rgba(0, 0, 100, 0.03)}:host(.content-ltr) .transition-shadow{right:0;}:host(.content-rtl) .transition-shadow{left:0;-webkit-transform:scaleX(-1);transform:scaleX(-1)}::slotted([slot=fixed]){position:absolute;-webkit-transform:translateZ(0);transform:translateZ(0)}";
158
158
 
159
159
  const Content = class {
160
160
  constructor(hostRef) {
@@ -171,12 +171,6 @@ const Content = class {
171
171
  this.isMainContent = true;
172
172
  this.resizeTimeout = null;
173
173
  this.inheritedAttributes = {};
174
- /**
175
- * Track whether this content has sibling header/footer elements.
176
- * When absent, we need to apply safe-area padding directly.
177
- */
178
- this.hasHeader = false;
179
- this.hasFooter = false;
180
174
  this.tabsElement = null;
181
175
  // Detail is used in a hot loop in the scroll event, by allocating it here
182
176
  // V8 will be able to inline any read/write to it since it's a monomorphic class.
@@ -231,13 +225,7 @@ const Content = class {
231
225
  this.inheritedAttributes = helpers.inheritAriaAttributes(this.el);
232
226
  }
233
227
  connectedCallback() {
234
- var _a;
235
- // Content is "main" if not inside menu/popover/modal and not nested in another ion-content
236
- this.isMainContent =
237
- this.el.closest('ion-menu, ion-popover, ion-modal') === null &&
238
- ((_a = this.el.parentElement) === null || _a === void 0 ? void 0 : _a.closest('ion-content')) === null;
239
- // Detect sibling header/footer for safe-area handling
240
- this.detectSiblingElements();
228
+ this.isMainContent = this.el.closest('ion-menu, ion-popover, ion-modal') === null;
241
229
  /**
242
230
  * The fullscreen content offsets need to be
243
231
  * computed after the tab bar has loaded. Since
@@ -268,101 +256,13 @@ const Content = class {
268
256
  * bubbles, we can catch any instances of child tab bars loading by listening
269
257
  * on IonTabs.
270
258
  */
271
- this.tabsLoadCallback = () => {
272
- this.resize();
273
- // Re-detect footer when tab bar loads (it may not exist during initial detection)
274
- this.updateSiblingDetection();
275
- index.forceUpdate(this);
276
- };
259
+ this.tabsLoadCallback = () => this.resize();
277
260
  closestTabs.addEventListener('ionTabBarLoaded', this.tabsLoadCallback);
278
261
  }
279
262
  }
280
263
  }
281
- /**
282
- * Detects sibling ion-header and ion-footer elements and sets up
283
- * a mutation observer to handle dynamic changes (e.g., conditional rendering).
284
- */
285
- detectSiblingElements() {
286
- this.updateSiblingDetection();
287
- // Watch for dynamic header/footer changes (common in React conditional rendering)
288
- const parent = this.el.parentElement;
289
- if (parent && !this.parentMutationObserver && index$1.win !== undefined && 'MutationObserver' in index$1.win) {
290
- this.parentMutationObserver = new MutationObserver(() => {
291
- const prevHasHeader = this.hasHeader;
292
- const prevHasFooter = this.hasFooter;
293
- this.updateSiblingDetection();
294
- // Only trigger re-render if header/footer detection actually changed
295
- if (prevHasHeader !== this.hasHeader || prevHasFooter !== this.hasFooter) {
296
- index.forceUpdate(this);
297
- }
298
- });
299
- this.parentMutationObserver.observe(parent, { childList: true });
300
- }
301
- // Watch for dynamic tab bar changes in ion-tabs (common in Angular conditional rendering)
302
- const tabs = this.el.closest('ion-tabs');
303
- if (tabs && !this.tabsMutationObserver && index$1.win !== undefined && 'MutationObserver' in index$1.win) {
304
- this.tabsMutationObserver = new MutationObserver(() => {
305
- const prevHasFooter = this.hasFooter;
306
- this.updateSiblingDetection();
307
- // Only trigger re-render if footer detection actually changed
308
- if (prevHasFooter !== this.hasFooter) {
309
- index.forceUpdate(this);
310
- }
311
- });
312
- this.tabsMutationObserver.observe(tabs, { childList: true });
313
- }
314
- }
315
- /**
316
- * Updates hasHeader/hasFooter based on current DOM state.
317
- * Checks both direct siblings and elements wrapped in custom components
318
- * (e.g., <my-header><ion-header>...</ion-header></my-header>).
319
- */
320
- updateSiblingDetection() {
321
- const parent = this.el.parentElement;
322
- if (parent) {
323
- // First check for direct ion-header/ion-footer siblings
324
- this.hasHeader = parent.querySelector(':scope > ion-header') !== null;
325
- this.hasFooter = parent.querySelector(':scope > ion-footer') !== null;
326
- // If not found, check if any sibling contains them (wrapped components)
327
- if (!this.hasHeader) {
328
- this.hasHeader = this.siblingContainsElement(parent, 'ion-header');
329
- }
330
- if (!this.hasFooter) {
331
- this.hasFooter = this.siblingContainsElement(parent, 'ion-footer');
332
- }
333
- }
334
- // If no footer found, check if we're inside ion-tabs which has ion-tab-bar
335
- if (!this.hasFooter) {
336
- const tabs = this.el.closest('ion-tabs');
337
- if (tabs) {
338
- this.hasFooter = tabs.querySelector(':scope > ion-tab-bar') !== null;
339
- }
340
- }
341
- }
342
- /**
343
- * Checks if any sibling element of ion-content contains the specified element.
344
- * Only searches one level deep to avoid finding elements in nested pages.
345
- */
346
- siblingContainsElement(parent, tagName) {
347
- for (const sibling of parent.children) {
348
- // Skip ion-content itself
349
- if (sibling === this.el)
350
- continue;
351
- // Check if this sibling contains the target element as an immediate child
352
- if (sibling.querySelector(`:scope > ${tagName}`) !== null) {
353
- return true;
354
- }
355
- }
356
- return false;
357
- }
358
264
  disconnectedCallback() {
359
- var _a, _b;
360
265
  this.onScrollEnd();
361
- // Clean up mutation observers to prevent memory leaks
362
- (_a = this.parentMutationObserver) === null || _a === void 0 ? void 0 : _a.disconnect();
363
- this.parentMutationObserver = undefined;
364
- (_b = this.tabsMutationObserver) === null || _b === void 0 ? void 0 : _b.disconnect();
365
- this.tabsMutationObserver = undefined;
366
266
  if (helpers.hasLazyBuild(this.el)) {
367
267
  /**
368
268
  * The event listener and tabs caches need to
@@ -609,30 +509,26 @@ const Content = class {
609
509
  }
610
510
  }
611
511
  render() {
612
- const { fixedSlotPlacement, hasFooter, hasHeader, inheritedAttributes, isMainContent, scrollX, scrollY, el } = this;
512
+ const { fixedSlotPlacement, inheritedAttributes, isMainContent, scrollX, scrollY, el } = this;
613
513
  const rtl = dir.isRTL(el) ? 'rtl' : 'ltr';
614
514
  const mode = ionicGlobal.getIonMode(this);
615
515
  const forceOverscroll = this.shouldForceOverscroll();
616
516
  const transitionShadow = mode === 'ios';
617
517
  this.resize();
618
- return (index.h(index.Host, Object.assign({ key: 'bc3b1ed3c6128b3b3474c052f2b75f3f8ea7a8cb', role: isMainContent ? 'main' : undefined, class: theme.createColorClasses(this.color, {
518
+ return (index.h(index.Host, Object.assign({ key: 'cd8781f848d8dc926fe66f43d43c49564425a507', role: isMainContent ? 'main' : undefined, class: theme.createColorClasses(this.color, {
619
519
  [mode]: true,
620
520
  'content-sizing': theme.hostContext('ion-popover', this.el),
621
521
  overscroll: forceOverscroll,
622
522
  [`content-${rtl}`]: true,
623
- 'safe-area-top': isMainContent && !hasHeader,
624
- 'safe-area-bottom': isMainContent && !hasFooter,
625
- 'safe-area-left': isMainContent,
626
- 'safe-area-right': isMainContent,
627
523
  }), style: {
628
524
  '--offset-top': `${this.cTop}px`,
629
525
  '--offset-bottom': `${this.cBottom}px`,
630
- } }, inheritedAttributes), index.h("div", { key: '251af16d9d5c5bf50f5b9cf14f5002a35ada7409', ref: (el) => (this.backgroundContentEl = el), id: "background-content", part: "background" }), fixedSlotPlacement === 'before' ? index.h("slot", { name: "fixed" }) : null, index.h("div", { key: '218f567f5fec257562e5ac1167cdaac9e95bc04d', class: {
526
+ } }, inheritedAttributes), index.h("div", { key: '95b112d7cae30f22ef778ceffb88edb4d941c170', ref: (el) => (this.backgroundContentEl = el), id: "background-content", part: "background" }), fixedSlotPlacement === 'before' ? index.h("slot", { name: "fixed" }) : null, index.h("div", { key: '2fdfcbc39fb66f11b6191911f2941c660f4c12e5', class: {
631
527
  'inner-scroll': true,
632
528
  'scroll-x': scrollX,
633
529
  'scroll-y': scrollY,
634
530
  overscroll: (scrollX || scrollY) && forceOverscroll,
635
- }, ref: (scrollEl) => (this.scrollEl = scrollEl), onScroll: this.scrollEvents ? (ev) => this.onScroll(ev) : undefined, part: "scroll" }, index.h("slot", { key: '8acb832123f95730d45996bd54ed8f52b366cf74' })), transitionShadow ? (index.h("div", { class: "transition-effect" }, index.h("div", { class: "transition-cover" }), index.h("div", { class: "transition-shadow" }))) : null, fixedSlotPlacement === 'after' ? index.h("slot", { name: "fixed" }) : null));
531
+ }, ref: (scrollEl) => (this.scrollEl = scrollEl), onScroll: this.scrollEvents ? (ev) => this.onScroll(ev) : undefined, part: "scroll" }, index.h("slot", { key: '6bc77e0054ec8e21635a7f2abfe0ca46e0962e03' })), transitionShadow ? (index.h("div", { class: "transition-effect" }, index.h("div", { class: "transition-cover" }), index.h("div", { class: "transition-shadow" }))) : null, fixedSlotPlacement === 'after' ? index.h("slot", { name: "fixed" }) : null));
636
532
  }
637
533
  get el() { return index.getElement(this); }
638
534
  };
@@ -750,16 +646,16 @@ const Footer = class {
750
646
  this.destroyCollapsibleFooter();
751
647
  if (hasFade) {
752
648
  const pageEl = this.el.closest('ion-app,ion-page,.ion-page,page-inner');
753
- const contentEl = pageEl ? index$2.findIonContent(pageEl) : null;
649
+ const contentEl = pageEl ? index$1.findIonContent(pageEl) : null;
754
650
  if (!contentEl) {
755
- index$2.printIonContentErrorMsg(this.el);
651
+ index$1.printIonContentErrorMsg(this.el);
756
652
  return;
757
653
  }
758
654
  this.setupFadeFooter(contentEl);
759
655
  }
760
656
  };
761
657
  this.setupFadeFooter = async (contentEl) => {
762
- const scrollEl = (this.scrollEl = await index$2.getScrollElement(contentEl));
658
+ const scrollEl = (this.scrollEl = await index$1.getScrollElement(contentEl));
763
659
  /**
764
660
  * Handle fading of toolbars on scroll
765
661
  */
@@ -1072,7 +968,7 @@ const Header = class {
1072
968
  */
1073
969
  this.translucent = false;
1074
970
  this.setupFadeHeader = async (contentEl, condenseHeader) => {
1075
- const scrollEl = (this.scrollEl = await index$2.getScrollElement(contentEl));
971
+ const scrollEl = (this.scrollEl = await index$1.getScrollElement(contentEl));
1076
972
  /**
1077
973
  * Handle fading of toolbars on scroll
1078
974
  */
@@ -1106,7 +1002,7 @@ const Header = class {
1106
1002
  this.destroyCollapsibleHeader();
1107
1003
  if (hasCondense) {
1108
1004
  const pageEl = this.el.closest('ion-app,ion-page,.ion-page,page-inner');
1109
- const contentEl = pageEl ? index$2.findIonContent(pageEl) : null;
1005
+ const contentEl = pageEl ? index$1.findIonContent(pageEl) : null;
1110
1006
  // Cloned elements are always needed in iOS transition
1111
1007
  index.writeTask(() => {
1112
1008
  const title = cloneElement('ion-title');
@@ -1117,9 +1013,9 @@ const Header = class {
1117
1013
  }
1118
1014
  else if (hasFade) {
1119
1015
  const pageEl = this.el.closest('ion-app,ion-page,.ion-page,page-inner');
1120
- const contentEl = pageEl ? index$2.findIonContent(pageEl) : null;
1016
+ const contentEl = pageEl ? index$1.findIonContent(pageEl) : null;
1121
1017
  if (!contentEl) {
1122
- index$2.printIonContentErrorMsg(this.el);
1018
+ index$1.printIonContentErrorMsg(this.el);
1123
1019
  return;
1124
1020
  }
1125
1021
  const condenseHeader = contentEl.querySelector('ion-header[collapse="condense"]');
@@ -1142,13 +1038,13 @@ const Header = class {
1142
1038
  }
1143
1039
  async setupCondenseHeader(contentEl, pageEl) {
1144
1040
  if (!contentEl || !pageEl) {
1145
- index$2.printIonContentErrorMsg(this.el);
1041
+ index$1.printIonContentErrorMsg(this.el);
1146
1042
  return;
1147
1043
  }
1148
1044
  if (typeof IntersectionObserver === 'undefined') {
1149
1045
  return;
1150
1046
  }
1151
- this.scrollEl = await index$2.getScrollElement(contentEl);
1047
+ this.scrollEl = await index$1.getScrollElement(contentEl);
1152
1048
  const headers = pageEl.querySelectorAll('ion-header');
1153
1049
  this.collapsibleMainHeader = Array.from(headers).find((header) => header.collapse !== 'condense');
1154
1050
  if (!this.collapsibleMainHeader) {
@@ -1346,7 +1242,7 @@ const RouterOutlet = class {
1346
1242
  const { el, mode } = this;
1347
1243
  const animated = this.animated && index.config.getBoolean('animated', true);
1348
1244
  const animationBuilder = opts.animationBuilder || this.animation || index.config.get('navAnimation');
1349
- await index$3.transition(Object.assign(Object.assign({ mode,
1245
+ await index$2.transition(Object.assign(Object.assign({ mode,
1350
1246
  animated,
1351
1247
  enteringEl,
1352
1248
  leavingEl, baseEl: el,
@@ -263,26 +263,6 @@
263
263
  transform: scaleX(-1);
264
264
  }
265
265
 
266
- :host(.safe-area-top) #background-content,
267
- :host(.safe-area-top) .inner-scroll {
268
- top: var(--ion-safe-area-top, 0px);
269
- }
270
-
271
- :host(.safe-area-bottom) #background-content,
272
- :host(.safe-area-bottom) .inner-scroll {
273
- bottom: var(--ion-safe-area-bottom, 0px);
274
- }
275
-
276
- :host(.safe-area-left) #background-content,
277
- :host(.safe-area-left) .inner-scroll {
278
- left: var(--ion-safe-area-left, 0px);
279
- }
280
-
281
- :host(.safe-area-right) #background-content,
282
- :host(.safe-area-right) .inner-scroll {
283
- right: var(--ion-safe-area-right, 0px);
284
- }
285
-
286
266
  ::slotted([slot=fixed]) {
287
267
  position: absolute;
288
268
  /**