@ionic/core 8.8.18-nightly.20260811 → 8.8.18
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/components/ion-content.js +1 -1
- package/components/ion-modal.js +1 -1
- package/components/ion-select-modal.js +1 -1
- package/components/ion-select.js +1 -1
- package/components/p-DRxvM2Ic.js +4 -0
- package/components/{p-BMaKgJFV.js → p-gYiraiT_.js} +1 -1
- package/components/p-yEQxMl70.js +4 -0
- package/dist/cjs/ion-app_8.cjs.entry.js +53 -3
- package/dist/cjs/ion-modal.cjs.entry.js +50 -10
- package/dist/cjs/ionic.cjs.js +1 -1
- package/dist/cjs/loader.cjs.js +1 -1
- package/dist/collection/components/content/content.js +55 -4
- package/dist/collection/components/modal/modal.js +16 -11
- package/dist/collection/components/modal/safe-area-utils.js +35 -0
- package/dist/docs.json +1 -1
- package/dist/esm/ion-app_8.entry.js +54 -4
- package/dist/esm/ion-modal.entry.js +50 -10
- package/dist/esm/ionic.js +1 -1
- package/dist/esm/loader.js +1 -1
- package/dist/ionic/ionic.esm.js +1 -1
- package/dist/ionic/p-5e2f73ee.entry.js +4 -0
- package/dist/ionic/p-ea56626d.entry.js +4 -0
- package/dist/types/components/content/content.d.ts +12 -0
- package/dist/types/components/modal/modal.d.ts +5 -3
- package/dist/types/components/modal/safe-area-utils.d.ts +6 -0
- package/hydrate/index.js +86 -13
- package/hydrate/index.mjs +86 -13
- package/package.json +1 -1
- package/components/p-BvmB20aD.js +0 -4
- package/components/p-scxfI1Dd.js +0 -4
- package/dist/ionic/p-15c9319c.entry.js +0 -4
- package/dist/ionic/p-d1aac015.entry.js +0 -4
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/*!
|
|
2
2
|
* (C) Ionic http://ionicframework.com - MIT License
|
|
3
3
|
*/
|
|
4
|
-
import { Build, Host, forceUpdate, h, readTask } from "@stencil/core";
|
|
4
|
+
import { Build, Host, forceUpdate, h, readTask, } from "@stencil/core";
|
|
5
5
|
import { componentOnReady, hasLazyBuild, inheritAriaAttributes } from "../../utils/helpers";
|
|
6
6
|
import { isPlatform } from "../../utils/platform";
|
|
7
7
|
import { isRTL } from "../../utils/rtl/index";
|
|
@@ -75,6 +75,9 @@ export class Content {
|
|
|
75
75
|
*/
|
|
76
76
|
this.scrollEvents = false;
|
|
77
77
|
}
|
|
78
|
+
fullscreenChanged() {
|
|
79
|
+
this.setupFullscreenResizeObserver();
|
|
80
|
+
}
|
|
78
81
|
componentWillLoad() {
|
|
79
82
|
this.inheritedAttributes = inheritAriaAttributes(this.el);
|
|
80
83
|
}
|
|
@@ -114,6 +117,12 @@ export class Content {
|
|
|
114
117
|
closestTabs.addEventListener('ionTabBarLoaded', this.tabsLoadCallback);
|
|
115
118
|
}
|
|
116
119
|
}
|
|
120
|
+
// Re-observe on reattach, since componentDidLoad only fires once.
|
|
121
|
+
this.setupFullscreenResizeObserver();
|
|
122
|
+
}
|
|
123
|
+
componentDidLoad() {
|
|
124
|
+
// The custom elements build assigns fullscreen after connectedCallback.
|
|
125
|
+
this.setupFullscreenResizeObserver();
|
|
117
126
|
}
|
|
118
127
|
disconnectedCallback() {
|
|
119
128
|
this.onScrollEnd();
|
|
@@ -135,6 +144,42 @@ export class Content {
|
|
|
135
144
|
clearTimeout(this.resizeTimeout);
|
|
136
145
|
this.resizeTimeout = null;
|
|
137
146
|
}
|
|
147
|
+
this.destroyFullscreenResizeObserver();
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* Header and footer sizes can change after load without a window resize
|
|
151
|
+
* firing, so the `resize` listener alone misses those changes.
|
|
152
|
+
*
|
|
153
|
+
* Popover content is excluded because `contain: none` lets its offsets drive
|
|
154
|
+
* the host's own height, which would feed back into the observer.
|
|
155
|
+
*/
|
|
156
|
+
setupFullscreenResizeObserver() {
|
|
157
|
+
if (!Build.isBrowser || typeof ResizeObserver === 'undefined') {
|
|
158
|
+
return;
|
|
159
|
+
}
|
|
160
|
+
if (!this.fullscreen || hostContext('ion-popover', this.el)) {
|
|
161
|
+
this.destroyFullscreenResizeObserver();
|
|
162
|
+
return;
|
|
163
|
+
}
|
|
164
|
+
if (this.fullscreenResizeObserver !== undefined) {
|
|
165
|
+
return;
|
|
166
|
+
}
|
|
167
|
+
this.fullscreenResizeObserver = new ResizeObserver(() => {
|
|
168
|
+
// A hidden page reports a 0x0 box, which would zero the offsets. Same
|
|
169
|
+
// reasoning as the guard in onResize, minus its debounce so the
|
|
170
|
+
// correction lands in the next frame instead of 100ms later.
|
|
171
|
+
if (this.el.offsetParent === null) {
|
|
172
|
+
return;
|
|
173
|
+
}
|
|
174
|
+
this.resize();
|
|
175
|
+
});
|
|
176
|
+
this.fullscreenResizeObserver.observe(this.el);
|
|
177
|
+
}
|
|
178
|
+
destroyFullscreenResizeObserver() {
|
|
179
|
+
if (this.fullscreenResizeObserver !== undefined) {
|
|
180
|
+
this.fullscreenResizeObserver.disconnect();
|
|
181
|
+
this.fullscreenResizeObserver = undefined;
|
|
182
|
+
}
|
|
138
183
|
}
|
|
139
184
|
/**
|
|
140
185
|
* Rotating certain devices can update
|
|
@@ -373,7 +418,7 @@ export class Content {
|
|
|
373
418
|
const forceOverscroll = this.shouldForceOverscroll();
|
|
374
419
|
const transitionShadow = mode === 'ios';
|
|
375
420
|
this.resize();
|
|
376
|
-
return (h(Host, Object.assign({ key: '
|
|
421
|
+
return (h(Host, Object.assign({ key: '9551c759df407b10d809171641fc6e8f14d92219', role: isMainContent ? 'main' : undefined, class: createColorClasses(this.color, {
|
|
377
422
|
[mode]: true,
|
|
378
423
|
'content-fullscreen': this.fullscreen,
|
|
379
424
|
'content-sizing': hostContext('ion-popover', this.el),
|
|
@@ -382,12 +427,12 @@ export class Content {
|
|
|
382
427
|
}), style: {
|
|
383
428
|
'--offset-top': `${this.cTop}px`,
|
|
384
429
|
'--offset-bottom': `${this.cBottom}px`,
|
|
385
|
-
} }, inheritedAttributes), h("div", { key: '
|
|
430
|
+
} }, inheritedAttributes), h("div", { key: 'c6de8fd226f0d10a534eb107fe032ac155fbe68e', ref: (el) => (this.backgroundContentEl = el), id: "background-content", part: "background" }), fixedSlotPlacement === 'before' ? h("slot", { name: "fixed" }) : null, h("div", { key: '082fc2936061360060b48221ecb1c864a3711fa0', class: {
|
|
386
431
|
'inner-scroll': true,
|
|
387
432
|
'scroll-x': scrollX,
|
|
388
433
|
'scroll-y': scrollY,
|
|
389
434
|
overscroll: (scrollX || scrollY) && forceOverscroll,
|
|
390
|
-
}, ref: (scrollEl) => (this.scrollEl = scrollEl), onScroll: this.scrollEvents ? (ev) => this.onScroll(ev) : undefined, part: "scroll" }, h("slot", { key: '
|
|
435
|
+
}, ref: (scrollEl) => (this.scrollEl = scrollEl), onScroll: this.scrollEvents ? (ev) => this.onScroll(ev) : undefined, part: "scroll" }, h("slot", { key: '0d2286206facb22696a9ca7e74a3f6b7d2397aab' })), transitionShadow ? (h("div", { class: "transition-effect" }, h("div", { class: "transition-cover" }), h("div", { class: "transition-shadow" }))) : null, fixedSlotPlacement === 'after' ? h("slot", { name: "fixed" }) : null));
|
|
391
436
|
}
|
|
392
437
|
static get is() { return "ion-content"; }
|
|
393
438
|
static get encapsulation() { return "shadow"; }
|
|
@@ -813,6 +858,12 @@ export class Content {
|
|
|
813
858
|
};
|
|
814
859
|
}
|
|
815
860
|
static get elementRef() { return "el"; }
|
|
861
|
+
static get watchers() {
|
|
862
|
+
return [{
|
|
863
|
+
"propName": "fullscreen",
|
|
864
|
+
"methodName": "fullscreenChanged"
|
|
865
|
+
}];
|
|
866
|
+
}
|
|
816
867
|
static get listeners() {
|
|
817
868
|
return [{
|
|
818
869
|
"name": "resize",
|
|
@@ -21,7 +21,7 @@ import { mdEnterAnimation } from "./animations/md.enter";
|
|
|
21
21
|
import { mdLeaveAnimation } from "./animations/md.leave";
|
|
22
22
|
import { createSheetGesture } from "./gestures/sheet";
|
|
23
23
|
import { createSwipeToCloseGesture, SwipeToCloseDefaults } from "./gestures/swipe-to-close";
|
|
24
|
-
import { getInitialSafeAreaConfig, getPositionBasedSafeAreaConfig, applySafeAreaOverrides, clearSafeAreaOverrides, getRootSafeAreaTop, hasCustomModalDimensions, } from "./safe-area-utils";
|
|
24
|
+
import { getInitialSafeAreaConfig, getPositionBasedSafeAreaConfig, applySafeAreaOverrides, clearSafeAreaOverrides, getRootSafeAreaTop, onRootSafeAreaTopChange, hasCustomModalDimensions, } from "./safe-area-utils";
|
|
25
25
|
import { setCardStatusBarDark, setCardStatusBarDefault } from "./utils";
|
|
26
26
|
// TODO(FW-2832): types
|
|
27
27
|
/**
|
|
@@ -1055,16 +1055,18 @@ export class Modal {
|
|
|
1055
1055
|
// Set the internal offset property with the resolved root safe-area-top value
|
|
1056
1056
|
if (context.isSheetModal) {
|
|
1057
1057
|
this.updateSheetOffsetTop();
|
|
1058
|
+
this.unsubscribeRootSafeAreaTop = onRootSafeAreaTopChange((safeAreaTop) => this.updateSheetOffsetTop(safeAreaTop));
|
|
1058
1059
|
}
|
|
1059
1060
|
}
|
|
1060
1061
|
/**
|
|
1061
|
-
*
|
|
1062
|
-
*
|
|
1063
|
-
* Called on present
|
|
1062
|
+
* Sets the internal --ion-modal-offset-top property on the host element,
|
|
1063
|
+
* resolving the current root --ion-safe-area-top when no value is given.
|
|
1064
|
+
* Called on present, on resize (e.g., device rotation changes safe-area),
|
|
1065
|
+
* and whenever the root safe-area value itself changes.
|
|
1064
1066
|
*/
|
|
1065
|
-
updateSheetOffsetTop() {
|
|
1066
|
-
const
|
|
1067
|
-
this.el.style.setProperty('--ion-modal-offset-top', `${
|
|
1067
|
+
updateSheetOffsetTop(safeAreaTop) {
|
|
1068
|
+
const value = safeAreaTop !== null && safeAreaTop !== void 0 ? safeAreaTop : getRootSafeAreaTop();
|
|
1069
|
+
this.el.style.setProperty('--ion-modal-offset-top', `${value}px`);
|
|
1068
1070
|
}
|
|
1069
1071
|
/**
|
|
1070
1072
|
* Updates safe-area overrides during dynamic state changes.
|
|
@@ -1163,7 +1165,10 @@ export class Modal {
|
|
|
1163
1165
|
* Clears all safe-area overrides and padding.
|
|
1164
1166
|
*/
|
|
1165
1167
|
cleanupSafeAreaOverrides() {
|
|
1168
|
+
var _a;
|
|
1166
1169
|
clearSafeAreaOverrides(this.el);
|
|
1170
|
+
(_a = this.unsubscribeRootSafeAreaTop) === null || _a === void 0 ? void 0 : _a.call(this);
|
|
1171
|
+
this.unsubscribeRootSafeAreaTop = undefined;
|
|
1167
1172
|
// Remove internal sheet offset property
|
|
1168
1173
|
this.el.style.removeProperty('--ion-modal-offset-top');
|
|
1169
1174
|
const { contentEl } = this.findContentAndFooter();
|
|
@@ -1176,11 +1181,11 @@ export class Modal {
|
|
|
1176
1181
|
const isCardModal = presentingElement !== undefined && mode === 'ios';
|
|
1177
1182
|
const isHandleCycle = handleBehavior === 'cycle';
|
|
1178
1183
|
const isSheetModalWithHandle = isSheetModal && showHandle;
|
|
1179
|
-
return (h(Host, Object.assign({ key: '
|
|
1184
|
+
return (h(Host, Object.assign({ key: 'c4b2713ebc788ac8672e18fdd5069e4253c4da34', "no-router": true,
|
|
1180
1185
|
// Allow the modal to be navigable when the handle is focusable
|
|
1181
1186
|
tabIndex: isHandleCycle && isSheetModalWithHandle ? 0 : -1 }, htmlAttributes, { style: {
|
|
1182
1187
|
zIndex: `${20000 + this.overlayIndex}`,
|
|
1183
|
-
}, class: Object.assign({ [mode]: true, ['modal-default']: !isCardModal && !isSheetModal, [`modal-card`]: isCardModal, [`modal-sheet`]: isSheetModal, [`modal-no-expand-scroll`]: isSheetModal && !expandToScroll, 'overlay-hidden': true, [FOCUS_TRAP_DISABLE_CLASS]: focusTrap === false }, getClassMap(this.cssClass)), onIonBackdropTap: this.onBackdropTap, onIonModalDidPresent: this.onLifecycle, onIonModalWillPresent: this.onLifecycle, onIonModalWillDismiss: this.onLifecycle, onIonModalDidDismiss: this.onLifecycle, onFocus: this.onModalFocus }), h("ion-backdrop", { key: '
|
|
1188
|
+
}, class: Object.assign({ [mode]: true, ['modal-default']: !isCardModal && !isSheetModal, [`modal-card`]: isCardModal, [`modal-sheet`]: isSheetModal, [`modal-no-expand-scroll`]: isSheetModal && !expandToScroll, 'overlay-hidden': true, [FOCUS_TRAP_DISABLE_CLASS]: focusTrap === false }, getClassMap(this.cssClass)), onIonBackdropTap: this.onBackdropTap, onIonModalDidPresent: this.onLifecycle, onIonModalWillPresent: this.onLifecycle, onIonModalWillDismiss: this.onLifecycle, onIonModalDidDismiss: this.onLifecycle, onFocus: this.onModalFocus }), h("ion-backdrop", { key: '2cc0afff8a815954492138afb0fca042243afddd', ref: (el) => (this.backdropEl = el), visible: this.showBackdrop, tappable: this.backdropDismiss, part: "backdrop" }), mode === 'ios' && h("div", { key: '9844700b9436f9bfa1a69ba436e9ca46d70cf316', class: "modal-shadow" }), h("div", Object.assign({ key: 'ab1cd56ca956c773c9242fb42ff320bac7627b4b',
|
|
1184
1189
|
/*
|
|
1185
1190
|
role and aria-modal must be used on the
|
|
1186
1191
|
same element. They must also be set inside the
|
|
@@ -1193,9 +1198,9 @@ export class Modal {
|
|
|
1193
1198
|
without the tabindex focus() would be a no-op and screen readers
|
|
1194
1199
|
may not properly announce the dialog and its content when it opens.
|
|
1195
1200
|
*/
|
|
1196
|
-
role: "dialog" }, inheritedAttributes, { "aria-modal": "true", tabIndex: -1, class: "modal-wrapper ion-overlay-wrapper", part: "content", ref: (el) => (this.wrapperEl = el) }), showHandle && (h("button", { key: '
|
|
1201
|
+
role: "dialog" }, inheritedAttributes, { "aria-modal": "true", tabIndex: -1, class: "modal-wrapper ion-overlay-wrapper", part: "content", ref: (el) => (this.wrapperEl = el) }), showHandle && (h("button", { key: 'c7706794e04a962178640e9a9a11c56288c45e08', class: "modal-handle",
|
|
1197
1202
|
// Prevents the handle from receiving keyboard focus when it does not cycle
|
|
1198
|
-
tabIndex: !isHandleCycle ? -1 : 0, "aria-label": "Activate to adjust the size of the dialog overlaying the screen", onClick: isHandleCycle ? this.onHandleClick : undefined, part: "handle", ref: (el) => (this.dragHandleEl = el) })), h("slot", { key: '
|
|
1203
|
+
tabIndex: !isHandleCycle ? -1 : 0, "aria-label": "Activate to adjust the size of the dialog overlaying the screen", onClick: isHandleCycle ? this.onHandleClick : undefined, part: "handle", ref: (el) => (this.dragHandleEl = el) })), h("slot", { key: 'c44fd9810cdd3286f096af98e5a4072f8f44c193', onSlotchange: this.onSlotChange }))));
|
|
1199
1204
|
}
|
|
1200
1205
|
static get is() { return "ion-modal"; }
|
|
1201
1206
|
static get encapsulation() { return "shadow"; }
|
|
@@ -69,6 +69,41 @@ export const getRootSafeAreaTop = () => {
|
|
|
69
69
|
}
|
|
70
70
|
return value;
|
|
71
71
|
};
|
|
72
|
+
/**
|
|
73
|
+
* Calls back when the resolved root `--ion-safe-area-top` changes, which no
|
|
74
|
+
* event and no window resize covers. The probe's height tracks the variable, so
|
|
75
|
+
* a change to it becomes a size change the observer can see.
|
|
76
|
+
*/
|
|
77
|
+
export const onRootSafeAreaTopChange = (callback) => {
|
|
78
|
+
const doc = win === null || win === void 0 ? void 0 : win.document;
|
|
79
|
+
if (!(doc === null || doc === void 0 ? void 0 : doc.body) || typeof ResizeObserver === 'undefined') {
|
|
80
|
+
return () => undefined;
|
|
81
|
+
}
|
|
82
|
+
const probe = doc.createElement('div');
|
|
83
|
+
probe.style.cssText =
|
|
84
|
+
'position:fixed;visibility:hidden;pointer-events:none;top:0;left:0;width:0;' +
|
|
85
|
+
'height:var(--ion-safe-area-top,0px);';
|
|
86
|
+
doc.body.appendChild(probe);
|
|
87
|
+
/**
|
|
88
|
+
* Seeded with the value the caller has already applied, so a change that
|
|
89
|
+
* lands before the observer's first delivery still gets reported. Comparing
|
|
90
|
+
* against an unset value instead would consume that first delivery and treat
|
|
91
|
+
* the new inset as the baseline.
|
|
92
|
+
*/
|
|
93
|
+
let lastHeight = getRootSafeAreaTop();
|
|
94
|
+
const observer = new ResizeObserver((entries) => {
|
|
95
|
+
const { height } = entries[0].contentRect;
|
|
96
|
+
if (height !== lastHeight) {
|
|
97
|
+
lastHeight = height;
|
|
98
|
+
callback(height);
|
|
99
|
+
}
|
|
100
|
+
});
|
|
101
|
+
observer.observe(probe);
|
|
102
|
+
return () => {
|
|
103
|
+
observer.disconnect();
|
|
104
|
+
probe.remove();
|
|
105
|
+
};
|
|
106
|
+
};
|
|
72
107
|
/**
|
|
73
108
|
* True when the modal host declares BOTH a non-fullscreen `--width` AND a
|
|
74
109
|
* non-fullscreen `--height` (i.e. a centered-dialog-like modal that doesn't
|
package/dist/docs.json
CHANGED
|
@@ -6,7 +6,7 @@ import { shouldUseCloseWatcher } from './hardware-back-button-B93Gru0Y.js';
|
|
|
6
6
|
import { a as isPlatform, b as getIonMode } from './ionic-global-Cp_eT4sZ.js';
|
|
7
7
|
import { i as inheritAriaAttributes, h as hasLazyBuild, c as componentOnReady, e as clamp, s as shallowEqualStringMap } from './helpers-HEqiOzXb.js';
|
|
8
8
|
import { i as isRTL } from './dir-C53feagD.js';
|
|
9
|
-
import {
|
|
9
|
+
import { h as hostContext, c as createColorClasses } from './theme-DiVJyqlX.js';
|
|
10
10
|
import { b as findIonContent, p as printIonContentErrorMsg, g as getScrollElement } from './index-Dw-wN0Ja.js';
|
|
11
11
|
import { c as createKeyboardController } from './keyboard-controller-BaaVITYt.js';
|
|
12
12
|
import { g as getTimeGivenProgression } from './cubic-bezier-hHmYLOfE.js';
|
|
@@ -224,6 +224,9 @@ const Content = class {
|
|
|
224
224
|
*/
|
|
225
225
|
this.scrollEvents = false;
|
|
226
226
|
}
|
|
227
|
+
fullscreenChanged() {
|
|
228
|
+
this.setupFullscreenResizeObserver();
|
|
229
|
+
}
|
|
227
230
|
componentWillLoad() {
|
|
228
231
|
this.inheritedAttributes = inheritAriaAttributes(this.el);
|
|
229
232
|
}
|
|
@@ -263,6 +266,12 @@ const Content = class {
|
|
|
263
266
|
closestTabs.addEventListener('ionTabBarLoaded', this.tabsLoadCallback);
|
|
264
267
|
}
|
|
265
268
|
}
|
|
269
|
+
// Re-observe on reattach, since componentDidLoad only fires once.
|
|
270
|
+
this.setupFullscreenResizeObserver();
|
|
271
|
+
}
|
|
272
|
+
componentDidLoad() {
|
|
273
|
+
// The custom elements build assigns fullscreen after connectedCallback.
|
|
274
|
+
this.setupFullscreenResizeObserver();
|
|
266
275
|
}
|
|
267
276
|
disconnectedCallback() {
|
|
268
277
|
this.onScrollEnd();
|
|
@@ -284,6 +293,42 @@ const Content = class {
|
|
|
284
293
|
clearTimeout(this.resizeTimeout);
|
|
285
294
|
this.resizeTimeout = null;
|
|
286
295
|
}
|
|
296
|
+
this.destroyFullscreenResizeObserver();
|
|
297
|
+
}
|
|
298
|
+
/**
|
|
299
|
+
* Header and footer sizes can change after load without a window resize
|
|
300
|
+
* firing, so the `resize` listener alone misses those changes.
|
|
301
|
+
*
|
|
302
|
+
* Popover content is excluded because `contain: none` lets its offsets drive
|
|
303
|
+
* the host's own height, which would feed back into the observer.
|
|
304
|
+
*/
|
|
305
|
+
setupFullscreenResizeObserver() {
|
|
306
|
+
if (typeof ResizeObserver === 'undefined') {
|
|
307
|
+
return;
|
|
308
|
+
}
|
|
309
|
+
if (!this.fullscreen || hostContext('ion-popover', this.el)) {
|
|
310
|
+
this.destroyFullscreenResizeObserver();
|
|
311
|
+
return;
|
|
312
|
+
}
|
|
313
|
+
if (this.fullscreenResizeObserver !== undefined) {
|
|
314
|
+
return;
|
|
315
|
+
}
|
|
316
|
+
this.fullscreenResizeObserver = new ResizeObserver(() => {
|
|
317
|
+
// A hidden page reports a 0x0 box, which would zero the offsets. Same
|
|
318
|
+
// reasoning as the guard in onResize, minus its debounce so the
|
|
319
|
+
// correction lands in the next frame instead of 100ms later.
|
|
320
|
+
if (this.el.offsetParent === null) {
|
|
321
|
+
return;
|
|
322
|
+
}
|
|
323
|
+
this.resize();
|
|
324
|
+
});
|
|
325
|
+
this.fullscreenResizeObserver.observe(this.el);
|
|
326
|
+
}
|
|
327
|
+
destroyFullscreenResizeObserver() {
|
|
328
|
+
if (this.fullscreenResizeObserver !== undefined) {
|
|
329
|
+
this.fullscreenResizeObserver.disconnect();
|
|
330
|
+
this.fullscreenResizeObserver = undefined;
|
|
331
|
+
}
|
|
287
332
|
}
|
|
288
333
|
/**
|
|
289
334
|
* Rotating certain devices can update
|
|
@@ -522,7 +567,7 @@ const Content = class {
|
|
|
522
567
|
const forceOverscroll = this.shouldForceOverscroll();
|
|
523
568
|
const transitionShadow = mode === 'ios';
|
|
524
569
|
this.resize();
|
|
525
|
-
return (h(Host, Object.assign({ key: '
|
|
570
|
+
return (h(Host, Object.assign({ key: '9551c759df407b10d809171641fc6e8f14d92219', role: isMainContent ? 'main' : undefined, class: createColorClasses(this.color, {
|
|
526
571
|
[mode]: true,
|
|
527
572
|
'content-fullscreen': this.fullscreen,
|
|
528
573
|
'content-sizing': hostContext('ion-popover', this.el),
|
|
@@ -531,14 +576,19 @@ const Content = class {
|
|
|
531
576
|
}), style: {
|
|
532
577
|
'--offset-top': `${this.cTop}px`,
|
|
533
578
|
'--offset-bottom': `${this.cBottom}px`,
|
|
534
|
-
} }, inheritedAttributes), h("div", { key: '
|
|
579
|
+
} }, inheritedAttributes), h("div", { key: 'c6de8fd226f0d10a534eb107fe032ac155fbe68e', ref: (el) => (this.backgroundContentEl = el), id: "background-content", part: "background" }), fixedSlotPlacement === 'before' ? h("slot", { name: "fixed" }) : null, h("div", { key: '082fc2936061360060b48221ecb1c864a3711fa0', class: {
|
|
535
580
|
'inner-scroll': true,
|
|
536
581
|
'scroll-x': scrollX,
|
|
537
582
|
'scroll-y': scrollY,
|
|
538
583
|
overscroll: (scrollX || scrollY) && forceOverscroll,
|
|
539
|
-
}, ref: (scrollEl) => (this.scrollEl = scrollEl), onScroll: this.scrollEvents ? (ev) => this.onScroll(ev) : undefined, part: "scroll" }, h("slot", { key: '
|
|
584
|
+
}, ref: (scrollEl) => (this.scrollEl = scrollEl), onScroll: this.scrollEvents ? (ev) => this.onScroll(ev) : undefined, part: "scroll" }, h("slot", { key: '0d2286206facb22696a9ca7e74a3f6b7d2397aab' })), transitionShadow ? (h("div", { class: "transition-effect" }, h("div", { class: "transition-cover" }), h("div", { class: "transition-shadow" }))) : null, fixedSlotPlacement === 'after' ? h("slot", { name: "fixed" }) : null));
|
|
540
585
|
}
|
|
541
586
|
get el() { return getElement(this); }
|
|
587
|
+
static get watchers() { return {
|
|
588
|
+
"fullscreen": [{
|
|
589
|
+
"fullscreenChanged": 0
|
|
590
|
+
}]
|
|
591
|
+
}; }
|
|
542
592
|
};
|
|
543
593
|
const getParentElement = (el) => {
|
|
544
594
|
var _a;
|
|
@@ -1695,6 +1695,41 @@ const getRootSafeAreaTop = () => {
|
|
|
1695
1695
|
}
|
|
1696
1696
|
return value;
|
|
1697
1697
|
};
|
|
1698
|
+
/**
|
|
1699
|
+
* Calls back when the resolved root `--ion-safe-area-top` changes, which no
|
|
1700
|
+
* event and no window resize covers. The probe's height tracks the variable, so
|
|
1701
|
+
* a change to it becomes a size change the observer can see.
|
|
1702
|
+
*/
|
|
1703
|
+
const onRootSafeAreaTopChange = (callback) => {
|
|
1704
|
+
const doc = win === null || win === void 0 ? void 0 : win.document;
|
|
1705
|
+
if (!(doc === null || doc === void 0 ? void 0 : doc.body) || typeof ResizeObserver === 'undefined') {
|
|
1706
|
+
return () => undefined;
|
|
1707
|
+
}
|
|
1708
|
+
const probe = doc.createElement('div');
|
|
1709
|
+
probe.style.cssText =
|
|
1710
|
+
'position:fixed;visibility:hidden;pointer-events:none;top:0;left:0;width:0;' +
|
|
1711
|
+
'height:var(--ion-safe-area-top,0px);';
|
|
1712
|
+
doc.body.appendChild(probe);
|
|
1713
|
+
/**
|
|
1714
|
+
* Seeded with the value the caller has already applied, so a change that
|
|
1715
|
+
* lands before the observer's first delivery still gets reported. Comparing
|
|
1716
|
+
* against an unset value instead would consume that first delivery and treat
|
|
1717
|
+
* the new inset as the baseline.
|
|
1718
|
+
*/
|
|
1719
|
+
let lastHeight = getRootSafeAreaTop();
|
|
1720
|
+
const observer = new ResizeObserver((entries) => {
|
|
1721
|
+
const { height } = entries[0].contentRect;
|
|
1722
|
+
if (height !== lastHeight) {
|
|
1723
|
+
lastHeight = height;
|
|
1724
|
+
callback(height);
|
|
1725
|
+
}
|
|
1726
|
+
});
|
|
1727
|
+
observer.observe(probe);
|
|
1728
|
+
return () => {
|
|
1729
|
+
observer.disconnect();
|
|
1730
|
+
probe.remove();
|
|
1731
|
+
};
|
|
1732
|
+
};
|
|
1698
1733
|
/**
|
|
1699
1734
|
* True when the modal host declares BOTH a non-fullscreen `--width` AND a
|
|
1700
1735
|
* non-fullscreen `--height` (i.e. a centered-dialog-like modal that doesn't
|
|
@@ -2847,16 +2882,18 @@ const Modal = class {
|
|
|
2847
2882
|
// Set the internal offset property with the resolved root safe-area-top value
|
|
2848
2883
|
if (context.isSheetModal) {
|
|
2849
2884
|
this.updateSheetOffsetTop();
|
|
2885
|
+
this.unsubscribeRootSafeAreaTop = onRootSafeAreaTopChange((safeAreaTop) => this.updateSheetOffsetTop(safeAreaTop));
|
|
2850
2886
|
}
|
|
2851
2887
|
}
|
|
2852
2888
|
/**
|
|
2853
|
-
*
|
|
2854
|
-
*
|
|
2855
|
-
* Called on present
|
|
2889
|
+
* Sets the internal --ion-modal-offset-top property on the host element,
|
|
2890
|
+
* resolving the current root --ion-safe-area-top when no value is given.
|
|
2891
|
+
* Called on present, on resize (e.g., device rotation changes safe-area),
|
|
2892
|
+
* and whenever the root safe-area value itself changes.
|
|
2856
2893
|
*/
|
|
2857
|
-
updateSheetOffsetTop() {
|
|
2858
|
-
const
|
|
2859
|
-
this.el.style.setProperty('--ion-modal-offset-top', `${
|
|
2894
|
+
updateSheetOffsetTop(safeAreaTop) {
|
|
2895
|
+
const value = safeAreaTop !== null && safeAreaTop !== void 0 ? safeAreaTop : getRootSafeAreaTop();
|
|
2896
|
+
this.el.style.setProperty('--ion-modal-offset-top', `${value}px`);
|
|
2860
2897
|
}
|
|
2861
2898
|
/**
|
|
2862
2899
|
* Updates safe-area overrides during dynamic state changes.
|
|
@@ -2955,7 +2992,10 @@ const Modal = class {
|
|
|
2955
2992
|
* Clears all safe-area overrides and padding.
|
|
2956
2993
|
*/
|
|
2957
2994
|
cleanupSafeAreaOverrides() {
|
|
2995
|
+
var _a;
|
|
2958
2996
|
clearSafeAreaOverrides(this.el);
|
|
2997
|
+
(_a = this.unsubscribeRootSafeAreaTop) === null || _a === void 0 ? void 0 : _a.call(this);
|
|
2998
|
+
this.unsubscribeRootSafeAreaTop = undefined;
|
|
2959
2999
|
// Remove internal sheet offset property
|
|
2960
3000
|
this.el.style.removeProperty('--ion-modal-offset-top');
|
|
2961
3001
|
const { contentEl } = this.findContentAndFooter();
|
|
@@ -2968,11 +3008,11 @@ const Modal = class {
|
|
|
2968
3008
|
const isCardModal = presentingElement !== undefined && mode === 'ios';
|
|
2969
3009
|
const isHandleCycle = handleBehavior === 'cycle';
|
|
2970
3010
|
const isSheetModalWithHandle = isSheetModal && showHandle;
|
|
2971
|
-
return (h(Host, Object.assign({ key: '
|
|
3011
|
+
return (h(Host, Object.assign({ key: 'c4b2713ebc788ac8672e18fdd5069e4253c4da34', "no-router": true,
|
|
2972
3012
|
// Allow the modal to be navigable when the handle is focusable
|
|
2973
3013
|
tabIndex: isHandleCycle && isSheetModalWithHandle ? 0 : -1 }, htmlAttributes, { style: {
|
|
2974
3014
|
zIndex: `${20000 + this.overlayIndex}`,
|
|
2975
|
-
}, class: Object.assign({ [mode]: true, ['modal-default']: !isCardModal && !isSheetModal, [`modal-card`]: isCardModal, [`modal-sheet`]: isSheetModal, [`modal-no-expand-scroll`]: isSheetModal && !expandToScroll, 'overlay-hidden': true, [FOCUS_TRAP_DISABLE_CLASS]: focusTrap === false }, getClassMap(this.cssClass)), onIonBackdropTap: this.onBackdropTap, onIonModalDidPresent: this.onLifecycle, onIonModalWillPresent: this.onLifecycle, onIonModalWillDismiss: this.onLifecycle, onIonModalDidDismiss: this.onLifecycle, onFocus: this.onModalFocus }), h("ion-backdrop", { key: '
|
|
3015
|
+
}, class: Object.assign({ [mode]: true, ['modal-default']: !isCardModal && !isSheetModal, [`modal-card`]: isCardModal, [`modal-sheet`]: isSheetModal, [`modal-no-expand-scroll`]: isSheetModal && !expandToScroll, 'overlay-hidden': true, [FOCUS_TRAP_DISABLE_CLASS]: focusTrap === false }, getClassMap(this.cssClass)), onIonBackdropTap: this.onBackdropTap, onIonModalDidPresent: this.onLifecycle, onIonModalWillPresent: this.onLifecycle, onIonModalWillDismiss: this.onLifecycle, onIonModalDidDismiss: this.onLifecycle, onFocus: this.onModalFocus }), h("ion-backdrop", { key: '2cc0afff8a815954492138afb0fca042243afddd', ref: (el) => (this.backdropEl = el), visible: this.showBackdrop, tappable: this.backdropDismiss, part: "backdrop" }), mode === 'ios' && h("div", { key: '9844700b9436f9bfa1a69ba436e9ca46d70cf316', class: "modal-shadow" }), h("div", Object.assign({ key: 'ab1cd56ca956c773c9242fb42ff320bac7627b4b',
|
|
2976
3016
|
/*
|
|
2977
3017
|
role and aria-modal must be used on the
|
|
2978
3018
|
same element. They must also be set inside the
|
|
@@ -2985,9 +3025,9 @@ const Modal = class {
|
|
|
2985
3025
|
without the tabindex focus() would be a no-op and screen readers
|
|
2986
3026
|
may not properly announce the dialog and its content when it opens.
|
|
2987
3027
|
*/
|
|
2988
|
-
role: "dialog" }, inheritedAttributes, { "aria-modal": "true", tabIndex: -1, class: "modal-wrapper ion-overlay-wrapper", part: "content", ref: (el) => (this.wrapperEl = el) }), showHandle && (h("button", { key: '
|
|
3028
|
+
role: "dialog" }, inheritedAttributes, { "aria-modal": "true", tabIndex: -1, class: "modal-wrapper ion-overlay-wrapper", part: "content", ref: (el) => (this.wrapperEl = el) }), showHandle && (h("button", { key: 'c7706794e04a962178640e9a9a11c56288c45e08', class: "modal-handle",
|
|
2989
3029
|
// Prevents the handle from receiving keyboard focus when it does not cycle
|
|
2990
|
-
tabIndex: !isHandleCycle ? -1 : 0, "aria-label": "Activate to adjust the size of the dialog overlaying the screen", onClick: isHandleCycle ? this.onHandleClick : undefined, part: "handle", ref: (el) => (this.dragHandleEl = el) })), h("slot", { key: '
|
|
3030
|
+
tabIndex: !isHandleCycle ? -1 : 0, "aria-label": "Activate to adjust the size of the dialog overlaying the screen", onClick: isHandleCycle ? this.onHandleClick : undefined, part: "handle", ref: (el) => (this.dragHandleEl = el) })), h("slot", { key: 'c44fd9810cdd3286f096af98e5a4072f8f44c193', onSlotchange: this.onSlotChange }))));
|
|
2991
3031
|
}
|
|
2992
3032
|
get el() { return getElement(this); }
|
|
2993
3033
|
static get watchers() { return {
|