@ionic/core 8.7.17-dev.11767980394.1d9266a9 → 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)}::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,28 +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: '8b40855d7b3257fac16b0c945dc54b75a8a36b1f', 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
380
  }), style: {
484
381
  '--offset-top': `${this.cTop}px`,
485
382
  '--offset-bottom': `${this.cBottom}px`,
486
- } }, inheritedAttributes), h("div", { key: '1ec3de99f33ed7a252a637c14887043c96046536', ref: (el) => (this.backgroundContentEl = el), id: "background-content", part: "background" }), fixedSlotPlacement === 'before' ? h("slot", { name: "fixed" }) : null, h("div", { key: 'dae33d14c489a55fcb6eceabbec3cb3b04726f34', 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: {
487
384
  'inner-scroll': true,
488
385
  'scroll-x': scrollX,
489
386
  'scroll-y': scrollY,
490
387
  overscroll: (scrollX || scrollY) && forceOverscroll,
491
- }, ref: (scrollEl) => (this.scrollEl = scrollEl), onScroll: this.scrollEvents ? (ev) => this.onScroll(ev) : undefined, part: "scroll" }, h("slot", { key: 'e99873d5fcc573e5d6ccad0f7c79192e99f4b749' })), 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));
492
389
  }
493
390
  get el() { return this; }
494
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)}::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,28 +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: '8b40855d7b3257fac16b0c945dc54b75a8a36b1f', 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
523
  }), style: {
626
524
  '--offset-top': `${this.cTop}px`,
627
525
  '--offset-bottom': `${this.cBottom}px`,
628
- } }, inheritedAttributes), index.h("div", { key: '1ec3de99f33ed7a252a637c14887043c96046536', ref: (el) => (this.backgroundContentEl = el), id: "background-content", part: "background" }), fixedSlotPlacement === 'before' ? index.h("slot", { name: "fixed" }) : null, index.h("div", { key: 'dae33d14c489a55fcb6eceabbec3cb3b04726f34', 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: {
629
527
  'inner-scroll': true,
630
528
  'scroll-x': scrollX,
631
529
  'scroll-y': scrollY,
632
530
  overscroll: (scrollX || scrollY) && forceOverscroll,
633
- }, ref: (scrollEl) => (this.scrollEl = scrollEl), onScroll: this.scrollEvents ? (ev) => this.onScroll(ev) : undefined, part: "scroll" }, index.h("slot", { key: 'e99873d5fcc573e5d6ccad0f7c79192e99f4b749' })), 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));
634
532
  }
635
533
  get el() { return index.getElement(this); }
636
534
  };
@@ -748,16 +646,16 @@ const Footer = class {
748
646
  this.destroyCollapsibleFooter();
749
647
  if (hasFade) {
750
648
  const pageEl = this.el.closest('ion-app,ion-page,.ion-page,page-inner');
751
- const contentEl = pageEl ? index$2.findIonContent(pageEl) : null;
649
+ const contentEl = pageEl ? index$1.findIonContent(pageEl) : null;
752
650
  if (!contentEl) {
753
- index$2.printIonContentErrorMsg(this.el);
651
+ index$1.printIonContentErrorMsg(this.el);
754
652
  return;
755
653
  }
756
654
  this.setupFadeFooter(contentEl);
757
655
  }
758
656
  };
759
657
  this.setupFadeFooter = async (contentEl) => {
760
- const scrollEl = (this.scrollEl = await index$2.getScrollElement(contentEl));
658
+ const scrollEl = (this.scrollEl = await index$1.getScrollElement(contentEl));
761
659
  /**
762
660
  * Handle fading of toolbars on scroll
763
661
  */
@@ -1070,7 +968,7 @@ const Header = class {
1070
968
  */
1071
969
  this.translucent = false;
1072
970
  this.setupFadeHeader = async (contentEl, condenseHeader) => {
1073
- const scrollEl = (this.scrollEl = await index$2.getScrollElement(contentEl));
971
+ const scrollEl = (this.scrollEl = await index$1.getScrollElement(contentEl));
1074
972
  /**
1075
973
  * Handle fading of toolbars on scroll
1076
974
  */
@@ -1104,7 +1002,7 @@ const Header = class {
1104
1002
  this.destroyCollapsibleHeader();
1105
1003
  if (hasCondense) {
1106
1004
  const pageEl = this.el.closest('ion-app,ion-page,.ion-page,page-inner');
1107
- const contentEl = pageEl ? index$2.findIonContent(pageEl) : null;
1005
+ const contentEl = pageEl ? index$1.findIonContent(pageEl) : null;
1108
1006
  // Cloned elements are always needed in iOS transition
1109
1007
  index.writeTask(() => {
1110
1008
  const title = cloneElement('ion-title');
@@ -1115,9 +1013,9 @@ const Header = class {
1115
1013
  }
1116
1014
  else if (hasFade) {
1117
1015
  const pageEl = this.el.closest('ion-app,ion-page,.ion-page,page-inner');
1118
- const contentEl = pageEl ? index$2.findIonContent(pageEl) : null;
1016
+ const contentEl = pageEl ? index$1.findIonContent(pageEl) : null;
1119
1017
  if (!contentEl) {
1120
- index$2.printIonContentErrorMsg(this.el);
1018
+ index$1.printIonContentErrorMsg(this.el);
1121
1019
  return;
1122
1020
  }
1123
1021
  const condenseHeader = contentEl.querySelector('ion-header[collapse="condense"]');
@@ -1140,13 +1038,13 @@ const Header = class {
1140
1038
  }
1141
1039
  async setupCondenseHeader(contentEl, pageEl) {
1142
1040
  if (!contentEl || !pageEl) {
1143
- index$2.printIonContentErrorMsg(this.el);
1041
+ index$1.printIonContentErrorMsg(this.el);
1144
1042
  return;
1145
1043
  }
1146
1044
  if (typeof IntersectionObserver === 'undefined') {
1147
1045
  return;
1148
1046
  }
1149
- this.scrollEl = await index$2.getScrollElement(contentEl);
1047
+ this.scrollEl = await index$1.getScrollElement(contentEl);
1150
1048
  const headers = pageEl.querySelectorAll('ion-header');
1151
1049
  this.collapsibleMainHeader = Array.from(headers).find((header) => header.collapse !== 'condense');
1152
1050
  if (!this.collapsibleMainHeader) {
@@ -1344,7 +1242,7 @@ const RouterOutlet = class {
1344
1242
  const { el, mode } = this;
1345
1243
  const animated = this.animated && index.config.getBoolean('animated', true);
1346
1244
  const animationBuilder = opts.animationBuilder || this.animation || index.config.get('navAnimation');
1347
- await index$3.transition(Object.assign(Object.assign({ mode,
1245
+ await index$2.transition(Object.assign(Object.assign({ mode,
1348
1246
  animated,
1349
1247
  enteringEl,
1350
1248
  leavingEl, baseEl: el,
@@ -263,16 +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
266
  ::slotted([slot=fixed]) {
277
267
  position: absolute;
278
268
  /**