@ionic/core 8.7.18-dev.11769790854.11895f8f → 8.7.18-dev.11770316329.126ef4af

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.
Files changed (38) hide show
  1. package/components/ion-refresher.js +32 -3
  2. package/components/modal.js +12 -220
  3. package/components/popover.js +11 -83
  4. package/dist/cjs/ion-modal.cjs.entry.js +12 -220
  5. package/dist/cjs/ion-popover.cjs.entry.js +11 -83
  6. package/dist/cjs/ion-refresher_2.cjs.entry.js +32 -3
  7. package/dist/collection/components/modal/gestures/sheet.js +1 -3
  8. package/dist/collection/components/modal/gestures/swipe-to-close.js +1 -3
  9. package/dist/collection/components/modal/modal.ios.css +4 -0
  10. package/dist/collection/components/modal/modal.js +7 -215
  11. package/dist/collection/components/modal/modal.md.css +4 -0
  12. package/dist/collection/components/popover/animations/ios.enter.js +5 -21
  13. package/dist/collection/components/popover/animations/md.enter.js +5 -30
  14. package/dist/collection/components/popover/utils.js +1 -32
  15. package/dist/collection/components/refresher/refresher.js +70 -4
  16. package/dist/docs.json +49 -4
  17. package/dist/esm/ion-modal.entry.js +12 -220
  18. package/dist/esm/ion-popover.entry.js +11 -83
  19. package/dist/esm/ion-refresher_2.entry.js +32 -3
  20. package/dist/html.html-data.json +1 -1
  21. package/dist/ionic/ionic.esm.js +1 -1
  22. package/dist/ionic/p-90f2d3ff.entry.js +4 -0
  23. package/dist/ionic/p-91840a80.entry.js +4 -0
  24. package/dist/ionic/p-f9061316.entry.js +4 -0
  25. package/dist/types/components/modal/gestures/sheet.d.ts +1 -1
  26. package/dist/types/components/modal/gestures/swipe-to-close.d.ts +1 -1
  27. package/dist/types/components/modal/modal.d.ts +0 -47
  28. package/dist/types/components/popover/utils.d.ts +0 -2
  29. package/dist/types/components/refresher/refresher-interface.d.ts +7 -0
  30. package/dist/types/components/refresher/refresher.d.ts +16 -3
  31. package/dist/types/components.d.ts +16 -5
  32. package/dist/types/interface.d.ts +1 -1
  33. package/hydrate/index.js +54 -305
  34. package/hydrate/index.mjs +54 -305
  35. package/package.json +2 -4
  36. package/dist/ionic/p-639dd543.entry.js +0 -4
  37. package/dist/ionic/p-ec9ca3fe.entry.js +0 -4
  38. package/dist/ionic/p-ef4256eb.entry.js +0 -4
@@ -23,6 +23,8 @@ const Refresher = /*@__PURE__*/ proxyCustomElement(class Refresher extends HTMLE
23
23
  this.ionRefresh = createEvent(this, "ionRefresh", 7);
24
24
  this.ionPull = createEvent(this, "ionPull", 7);
25
25
  this.ionStart = createEvent(this, "ionStart", 7);
26
+ this.ionPullStart = createEvent(this, "ionPullStart", 7);
27
+ this.ionPullEnd = createEvent(this, "ionPullEnd", 7);
26
28
  this.appliedStyles = false;
27
29
  this.didStart = false;
28
30
  this.progress = 0;
@@ -77,8 +79,8 @@ const Refresher = /*@__PURE__*/ proxyCustomElement(class Refresher extends HTMLE
77
79
  * than `1`. The default value is `1` which is equal to the speed of the cursor.
78
80
  * If a negative value is passed in, the factor will be `1` instead.
79
81
  *
80
- * For example: If the value passed is `1.2` and the content is dragged by
81
- * `10` pixels, instead of `10` pixels the content will be pulled by `12` pixels
82
+ * For example, If the value passed is `1.2` and the content is dragged by
83
+ * `10` pixels, instead of `10` pixels, the content will be pulled by `12` pixels
82
84
  * (an increase of 20 percent). If the value passed is `0.8`, the dragged amount
83
85
  * will be `8` pixels, less than the amount the cursor has moved.
84
86
  *
@@ -128,6 +130,9 @@ const Refresher = /*@__PURE__*/ proxyCustomElement(class Refresher extends HTMLE
128
130
  this.animations = [];
129
131
  this.progress = 0;
130
132
  this.state = 1 /* RefresherState.Inactive */;
133
+ this.ionPullEnd.emit({
134
+ reason: state === 32 /* RefresherState.Completing */ ? 'complete' : 'cancel',
135
+ });
131
136
  }
132
137
  async setupiOSNativeRefresher(pullingSpinner, refreshingSpinner) {
133
138
  this.elementToTransform = this.scrollEl;
@@ -160,6 +165,7 @@ const Refresher = /*@__PURE__*/ proxyCustomElement(class Refresher extends HTMLE
160
165
  if (!this.didStart) {
161
166
  this.didStart = true;
162
167
  this.ionStart.emit();
168
+ this.ionPullStart.emit();
163
169
  }
164
170
  // emit "pulling" on every move
165
171
  if (this.pointerDown) {
@@ -235,6 +241,7 @@ const Refresher = /*@__PURE__*/ proxyCustomElement(class Refresher extends HTMLE
235
241
  this.lastVelocityY = ev.velocityY;
236
242
  },
237
243
  onEnd: () => {
244
+ const hadStarted = this.didStart;
238
245
  this.pointerDown = false;
239
246
  this.didStart = false;
240
247
  if (this.needsCompletion) {
@@ -244,6 +251,13 @@ const Refresher = /*@__PURE__*/ proxyCustomElement(class Refresher extends HTMLE
244
251
  else if (this.didRefresh) {
245
252
  readTask(() => translateElement(this.elementToTransform, `${this.el.clientHeight}px`));
246
253
  }
254
+ else if (hadStarted) {
255
+ /**
256
+ * User started pulling but released before reaching the refresh threshold.
257
+ * Emit ionPullEnd to complete the event pair.
258
+ */
259
+ this.ionPullEnd.emit({ reason: 'cancel' });
260
+ }
247
261
  },
248
262
  });
249
263
  this.disabledChanged();
@@ -290,6 +304,7 @@ const Refresher = /*@__PURE__*/ proxyCustomElement(class Refresher extends HTMLE
290
304
  ev.data.animation = animation;
291
305
  animation.progressStart(false, 0);
292
306
  this.ionStart.emit();
307
+ this.ionPullStart.emit();
293
308
  this.animations.push(animation);
294
309
  return;
295
310
  }
@@ -312,6 +327,7 @@ const Refresher = /*@__PURE__*/ proxyCustomElement(class Refresher extends HTMLE
312
327
  this.animations = [];
313
328
  this.gesture.enable(true);
314
329
  this.state = 1 /* RefresherState.Inactive */;
330
+ this.ionPullEnd.emit({ reason: 'cancel' });
315
331
  });
316
332
  return;
317
333
  }
@@ -556,6 +572,7 @@ const Refresher = /*@__PURE__*/ proxyCustomElement(class Refresher extends HTMLE
556
572
  if (!this.didStart) {
557
573
  this.didStart = true;
558
574
  this.ionStart.emit();
575
+ this.ionPullStart.emit();
559
576
  }
560
577
  // emit "pulling" on every move
561
578
  this.ionPull.emit();
@@ -599,6 +616,15 @@ const Refresher = /*@__PURE__*/ proxyCustomElement(class Refresher extends HTMLE
599
616
  * available right away.
600
617
  */
601
618
  this.restoreOverflowStyle();
619
+ /**
620
+ * If ionPullStart was emitted, we need to emit ionPullEnd
621
+ * even though the gesture was aborted before reaching the
622
+ * pulling threshold.
623
+ */
624
+ if (this.didStart) {
625
+ this.didStart = false;
626
+ this.ionPullEnd.emit({ reason: 'cancel' });
627
+ }
602
628
  }
603
629
  }
604
630
  beginRefresh() {
@@ -645,6 +671,9 @@ const Refresher = /*@__PURE__*/ proxyCustomElement(class Refresher extends HTMLE
645
671
  if (this.contentFullscreen && this.backgroundContentEl) {
646
672
  (_a = this.backgroundContentEl) === null || _a === void 0 ? void 0 : _a.style.removeProperty('--offset-top');
647
673
  }
674
+ this.ionPullEnd.emit({
675
+ reason: state === 32 /* RefresherState.Completing */ ? 'complete' : 'cancel',
676
+ });
648
677
  }, 600);
649
678
  // reset the styles on the scroll element
650
679
  // set that the refresh is actively cancelling/completing
@@ -698,7 +727,7 @@ const Refresher = /*@__PURE__*/ proxyCustomElement(class Refresher extends HTMLE
698
727
  }
699
728
  render() {
700
729
  const mode = getIonMode(this);
701
- return (h(Host, { key: '2d1bd880877b698604542ab2d602d38b9504d975', slot: "fixed", class: {
730
+ return (h(Host, { key: 'bed0c2f44c32ecac24b7d8326ac7c7ef1d12c44f', slot: "fixed", class: {
702
731
  [mode]: true,
703
732
  // Used internally for styling
704
733
  [`refresher-${mode}`]: true,
@@ -2,7 +2,6 @@
2
2
  * (C) Ionic http://ionicframework.com - MIT License
3
3
  */
4
4
  import { proxyCustomElement, HTMLElement, createEvent, writeTask, h, Host } from '@stencil/core/internal/client';
5
- import { w as win } from './index9.js';
6
5
  import { a as findClosestIonContent, i as isIonContent, d as disableContentScrollY, r as resetContentScrollY, f as findIonContent, p as printIonContentErrorMsg } from './index8.js';
7
6
  import { C as CoreDelegate, a as attachComponent, d as detachComponent } from './framework-delegate.js';
8
7
  import { f as clamp, g as getElementRoot, r as raf, d as inheritAttributes, k as hasLazyBuild } from './helpers.js';
@@ -17,6 +16,7 @@ import { KEYBOARD_DID_OPEN } from './keyboard.js';
17
16
  import { c as createAnimation } from './animation.js';
18
17
  import { g as getTimeGivenProgression } from './cubic-bezier.js';
19
18
  import { createGesture } from './index3.js';
19
+ import { w as win } from './index9.js';
20
20
  import { d as defineCustomElement$1 } from './backdrop.js';
21
21
 
22
22
  var Style;
@@ -246,7 +246,7 @@ const calculateSpringStep = (t) => {
246
246
  const SwipeToCloseDefaults = {
247
247
  MIN_PRESENTING_SCALE: 0.915,
248
248
  };
249
- const createSwipeToCloseGesture = (el, animation, statusBarStyle, onDismiss, onGestureMove) => {
249
+ const createSwipeToCloseGesture = (el, animation, statusBarStyle, onDismiss) => {
250
250
  /**
251
251
  * The step value at which a card modal
252
252
  * is eligible for dismissing via gesture.
@@ -403,8 +403,6 @@ const createSwipeToCloseGesture = (el, animation, statusBarStyle, onDismiss, onG
403
403
  const processedStep = isAttemptingDismissWithCanDismiss ? calculateSpringStep(step / maxStep) : step;
404
404
  const clampedStep = clamp(0.0001, processedStep, maxStep);
405
405
  animation.progressStep(clampedStep);
406
- // Notify modal of position change for safe-area updates
407
- onGestureMove === null || onGestureMove === void 0 ? void 0 : onGestureMove();
408
406
  /**
409
407
  * When swiping down half way, the status bar style
410
408
  * should be reset to its default value.
@@ -948,7 +946,7 @@ const mdLeaveAnimation = (baseEl, opts) => {
948
946
  return baseAnimation;
949
947
  };
950
948
 
951
- const createSheetGesture = (baseEl, backdropEl, wrapperEl, initialBreakpoint, backdropBreakpoint, animation, breakpoints = [], expandToScroll, getCurrentBreakpoint, onDismiss, onBreakpointChange, onGestureMove) => {
949
+ const createSheetGesture = (baseEl, backdropEl, wrapperEl, initialBreakpoint, backdropBreakpoint, animation, breakpoints = [], expandToScroll, getCurrentBreakpoint, onDismiss, onBreakpointChange) => {
952
950
  // Defaults for the sheet swipe animation
953
951
  const defaultBackdrop = [
954
952
  { offset: 0, opacity: 'var(--backdrop-opacity)' },
@@ -1279,8 +1277,6 @@ const createSheetGesture = (baseEl, backdropEl, wrapperEl, initialBreakpoint, ba
1279
1277
  : step;
1280
1278
  offset = clamp(0.0001, processedStep, maxStep);
1281
1279
  animation.progressStep(offset);
1282
- // Notify modal of position change for safe-area updates
1283
- onGestureMove === null || onGestureMove === void 0 ? void 0 : onGestureMove();
1284
1280
  };
1285
1281
  const onEnd = (detail) => {
1286
1282
  /**
@@ -1475,9 +1471,9 @@ const createSheetGesture = (baseEl, backdropEl, wrapperEl, initialBreakpoint, ba
1475
1471
  };
1476
1472
  };
1477
1473
 
1478
- const modalIosCss = ":host{--width:100%;--min-width:auto;--max-width:auto;--height:100%;--min-height:auto;--max-height:auto;--overflow:hidden;--border-radius:0;--border-width:0;--border-style:none;--border-color:transparent;--background:var(--ion-background-color, #fff);--box-shadow:none;--backdrop-opacity:0;left:0;right:0;top:0;bottom:0;display:-ms-flexbox;display:flex;position:absolute;-ms-flex-align:center;align-items:center;-ms-flex-pack:center;justify-content:center;outline:none;color:var(--ion-text-color, #000);contain:strict}.modal-wrapper,ion-backdrop{pointer-events:auto}:host(.overlay-hidden){display:none}.modal-wrapper,.modal-shadow{border-radius:var(--border-radius);width:var(--width);min-width:var(--min-width);max-width:var(--max-width);height:var(--height);min-height:var(--min-height);max-height:var(--max-height);border-width:var(--border-width);border-style:var(--border-style);border-color:var(--border-color);background:var(--background);-webkit-box-shadow:var(--box-shadow);box-shadow:var(--box-shadow);overflow:var(--overflow);z-index:10}.modal-shadow{position:absolute;background:transparent}@media only screen and (min-width: 768px) and (min-height: 600px){:host{--width:600px;--height:500px}}@media only screen and (min-width: 768px) and (min-height: 768px){:host{--width:600px;--height:600px}}.modal-handle{left:0px;right:0px;top:5px;border-radius:8px;-webkit-margin-start:auto;margin-inline-start:auto;-webkit-margin-end:auto;margin-inline-end:auto;position:absolute;width:36px;height:5px;-webkit-transform:translateZ(0);transform:translateZ(0);border:0;background:var(--ion-color-step-350, var(--ion-background-color-step-350, #c0c0be));cursor:pointer;z-index:11}.modal-handle::before{-webkit-padding-start:4px;padding-inline-start:4px;-webkit-padding-end:4px;padding-inline-end:4px;padding-top:4px;padding-bottom:4px;position:absolute;width:36px;height:5px;-webkit-transform:translate(-50%, -50%);transform:translate(-50%, -50%);content:\"\"}:host(.modal-sheet){--height:calc(100% - (var(--ion-safe-area-top) + 10px))}:host(.modal-sheet) .modal-wrapper,:host(.modal-sheet) .modal-shadow{position:absolute;bottom:0}:host(.modal-sheet.modal-no-expand-scroll) ion-footer{position:absolute;bottom:0;width:var(--width)}:host{--backdrop-opacity:var(--ion-backdrop-opacity, 0.4)}:host(.modal-card),:host(.modal-sheet){--border-radius:10px}@media only screen and (min-width: 768px) and (min-height: 600px){:host{--border-radius:10px}}.modal-wrapper{-webkit-transform:translate3d(0, 100%, 0);transform:translate3d(0, 100%, 0)}@media screen and (max-width: 767px){@supports (width: max(0px, 1px)){:host(.modal-card){--height:calc(100% - max(30px, var(--ion-safe-area-top)) - 10px)}}@supports not (width: max(0px, 1px)){:host(.modal-card){--height:calc(100% - 40px)}}:host(.modal-card) .modal-wrapper{border-start-start-radius:var(--border-radius);border-start-end-radius:var(--border-radius);border-end-end-radius:0;border-end-start-radius:0}:host(.modal-card){--backdrop-opacity:0;--width:100%;-ms-flex-align:end;align-items:flex-end}:host(.modal-card) .modal-shadow{display:none}:host(.modal-card) ion-backdrop{pointer-events:none}}@media screen and (min-width: 768px){:host(.modal-card){--width:calc(100% - 120px);--height:calc(100% - (120px + var(--ion-safe-area-top) + var(--ion-safe-area-bottom)));--max-width:720px;--max-height:1000px;--backdrop-opacity:0;--box-shadow:0px 0px 30px 10px rgba(0, 0, 0, 0.1);-webkit-transition:all 0.5s ease-in-out;transition:all 0.5s ease-in-out}:host(.modal-card) .modal-wrapper{-webkit-box-shadow:none;box-shadow:none}:host(.modal-card) .modal-shadow{-webkit-box-shadow:var(--box-shadow);box-shadow:var(--box-shadow)}}:host(.modal-sheet) .modal-wrapper{border-start-start-radius:var(--border-radius);border-start-end-radius:var(--border-radius);border-end-end-radius:0;border-end-start-radius:0}";
1474
+ const modalIosCss = ":host{--width:100%;--min-width:auto;--max-width:auto;--height:100%;--min-height:auto;--max-height:auto;--overflow:hidden;--border-radius:0;--border-width:0;--border-style:none;--border-color:transparent;--background:var(--ion-background-color, #fff);--box-shadow:none;--backdrop-opacity:0;left:0;right:0;top:0;bottom:0;display:-ms-flexbox;display:flex;position:absolute;-ms-flex-align:center;align-items:center;-ms-flex-pack:center;justify-content:center;outline:none;color:var(--ion-text-color, #000);contain:strict}.modal-wrapper,ion-backdrop{pointer-events:auto}:host(.overlay-hidden){display:none}.modal-wrapper,.modal-shadow{border-radius:var(--border-radius);width:var(--width);min-width:var(--min-width);max-width:var(--max-width);height:var(--height);min-height:var(--min-height);max-height:var(--max-height);border-width:var(--border-width);border-style:var(--border-style);border-color:var(--border-color);background:var(--background);-webkit-box-shadow:var(--box-shadow);box-shadow:var(--box-shadow);overflow:var(--overflow);z-index:10}.modal-shadow{position:absolute;background:transparent}@media only screen and (min-width: 768px) and (min-height: 600px){:host{--width:600px;--height:500px;--ion-safe-area-top:0px;--ion-safe-area-bottom:0px;--ion-safe-area-right:0px;--ion-safe-area-left:0px}}@media only screen and (min-width: 768px) and (min-height: 768px){:host{--width:600px;--height:600px}}.modal-handle{left:0px;right:0px;top:5px;border-radius:8px;-webkit-margin-start:auto;margin-inline-start:auto;-webkit-margin-end:auto;margin-inline-end:auto;position:absolute;width:36px;height:5px;-webkit-transform:translateZ(0);transform:translateZ(0);border:0;background:var(--ion-color-step-350, var(--ion-background-color-step-350, #c0c0be));cursor:pointer;z-index:11}.modal-handle::before{-webkit-padding-start:4px;padding-inline-start:4px;-webkit-padding-end:4px;padding-inline-end:4px;padding-top:4px;padding-bottom:4px;position:absolute;width:36px;height:5px;-webkit-transform:translate(-50%, -50%);transform:translate(-50%, -50%);content:\"\"}:host(.modal-sheet){--height:calc(100% - (var(--ion-safe-area-top) + 10px))}:host(.modal-sheet) .modal-wrapper,:host(.modal-sheet) .modal-shadow{position:absolute;bottom:0}:host(.modal-sheet.modal-no-expand-scroll) ion-footer{position:absolute;bottom:0;width:var(--width)}:host{--backdrop-opacity:var(--ion-backdrop-opacity, 0.4)}:host(.modal-card),:host(.modal-sheet){--border-radius:10px}@media only screen and (min-width: 768px) and (min-height: 600px){:host{--border-radius:10px}}.modal-wrapper{-webkit-transform:translate3d(0, 100%, 0);transform:translate3d(0, 100%, 0)}@media screen and (max-width: 767px){@supports (width: max(0px, 1px)){:host(.modal-card){--height:calc(100% - max(30px, var(--ion-safe-area-top)) - 10px)}}@supports not (width: max(0px, 1px)){:host(.modal-card){--height:calc(100% - 40px)}}:host(.modal-card) .modal-wrapper{border-start-start-radius:var(--border-radius);border-start-end-radius:var(--border-radius);border-end-end-radius:0;border-end-start-radius:0}:host(.modal-card){--backdrop-opacity:0;--width:100%;-ms-flex-align:end;align-items:flex-end}:host(.modal-card) .modal-shadow{display:none}:host(.modal-card) ion-backdrop{pointer-events:none}}@media screen and (min-width: 768px){:host(.modal-card){--width:calc(100% - 120px);--height:calc(100% - (120px + var(--ion-safe-area-top) + var(--ion-safe-area-bottom)));--max-width:720px;--max-height:1000px;--backdrop-opacity:0;--box-shadow:0px 0px 30px 10px rgba(0, 0, 0, 0.1);-webkit-transition:all 0.5s ease-in-out;transition:all 0.5s ease-in-out}:host(.modal-card) .modal-wrapper{-webkit-box-shadow:none;box-shadow:none}:host(.modal-card) .modal-shadow{-webkit-box-shadow:var(--box-shadow);box-shadow:var(--box-shadow)}}:host(.modal-sheet) .modal-wrapper{border-start-start-radius:var(--border-radius);border-start-end-radius:var(--border-radius);border-end-end-radius:0;border-end-start-radius:0}";
1479
1475
 
1480
- const modalMdCss = ":host{--width:100%;--min-width:auto;--max-width:auto;--height:100%;--min-height:auto;--max-height:auto;--overflow:hidden;--border-radius:0;--border-width:0;--border-style:none;--border-color:transparent;--background:var(--ion-background-color, #fff);--box-shadow:none;--backdrop-opacity:0;left:0;right:0;top:0;bottom:0;display:-ms-flexbox;display:flex;position:absolute;-ms-flex-align:center;align-items:center;-ms-flex-pack:center;justify-content:center;outline:none;color:var(--ion-text-color, #000);contain:strict}.modal-wrapper,ion-backdrop{pointer-events:auto}:host(.overlay-hidden){display:none}.modal-wrapper,.modal-shadow{border-radius:var(--border-radius);width:var(--width);min-width:var(--min-width);max-width:var(--max-width);height:var(--height);min-height:var(--min-height);max-height:var(--max-height);border-width:var(--border-width);border-style:var(--border-style);border-color:var(--border-color);background:var(--background);-webkit-box-shadow:var(--box-shadow);box-shadow:var(--box-shadow);overflow:var(--overflow);z-index:10}.modal-shadow{position:absolute;background:transparent}@media only screen and (min-width: 768px) and (min-height: 600px){:host{--width:600px;--height:500px}}@media only screen and (min-width: 768px) and (min-height: 768px){:host{--width:600px;--height:600px}}.modal-handle{left:0px;right:0px;top:5px;border-radius:8px;-webkit-margin-start:auto;margin-inline-start:auto;-webkit-margin-end:auto;margin-inline-end:auto;position:absolute;width:36px;height:5px;-webkit-transform:translateZ(0);transform:translateZ(0);border:0;background:var(--ion-color-step-350, var(--ion-background-color-step-350, #c0c0be));cursor:pointer;z-index:11}.modal-handle::before{-webkit-padding-start:4px;padding-inline-start:4px;-webkit-padding-end:4px;padding-inline-end:4px;padding-top:4px;padding-bottom:4px;position:absolute;width:36px;height:5px;-webkit-transform:translate(-50%, -50%);transform:translate(-50%, -50%);content:\"\"}:host(.modal-sheet){--height:calc(100% - (var(--ion-safe-area-top) + 10px))}:host(.modal-sheet) .modal-wrapper,:host(.modal-sheet) .modal-shadow{position:absolute;bottom:0}:host(.modal-sheet.modal-no-expand-scroll) ion-footer{position:absolute;bottom:0;width:var(--width)}:host{--backdrop-opacity:var(--ion-backdrop-opacity, 0.32)}@media only screen and (min-width: 768px) and (min-height: 600px){:host{--border-radius:2px;--box-shadow:0 28px 48px rgba(0, 0, 0, 0.4)}}.modal-wrapper{-webkit-transform:translate3d(0, 40px, 0);transform:translate3d(0, 40px, 0);opacity:0.01}";
1476
+ const modalMdCss = ":host{--width:100%;--min-width:auto;--max-width:auto;--height:100%;--min-height:auto;--max-height:auto;--overflow:hidden;--border-radius:0;--border-width:0;--border-style:none;--border-color:transparent;--background:var(--ion-background-color, #fff);--box-shadow:none;--backdrop-opacity:0;left:0;right:0;top:0;bottom:0;display:-ms-flexbox;display:flex;position:absolute;-ms-flex-align:center;align-items:center;-ms-flex-pack:center;justify-content:center;outline:none;color:var(--ion-text-color, #000);contain:strict}.modal-wrapper,ion-backdrop{pointer-events:auto}:host(.overlay-hidden){display:none}.modal-wrapper,.modal-shadow{border-radius:var(--border-radius);width:var(--width);min-width:var(--min-width);max-width:var(--max-width);height:var(--height);min-height:var(--min-height);max-height:var(--max-height);border-width:var(--border-width);border-style:var(--border-style);border-color:var(--border-color);background:var(--background);-webkit-box-shadow:var(--box-shadow);box-shadow:var(--box-shadow);overflow:var(--overflow);z-index:10}.modal-shadow{position:absolute;background:transparent}@media only screen and (min-width: 768px) and (min-height: 600px){:host{--width:600px;--height:500px;--ion-safe-area-top:0px;--ion-safe-area-bottom:0px;--ion-safe-area-right:0px;--ion-safe-area-left:0px}}@media only screen and (min-width: 768px) and (min-height: 768px){:host{--width:600px;--height:600px}}.modal-handle{left:0px;right:0px;top:5px;border-radius:8px;-webkit-margin-start:auto;margin-inline-start:auto;-webkit-margin-end:auto;margin-inline-end:auto;position:absolute;width:36px;height:5px;-webkit-transform:translateZ(0);transform:translateZ(0);border:0;background:var(--ion-color-step-350, var(--ion-background-color-step-350, #c0c0be));cursor:pointer;z-index:11}.modal-handle::before{-webkit-padding-start:4px;padding-inline-start:4px;-webkit-padding-end:4px;padding-inline-end:4px;padding-top:4px;padding-bottom:4px;position:absolute;width:36px;height:5px;-webkit-transform:translate(-50%, -50%);transform:translate(-50%, -50%);content:\"\"}:host(.modal-sheet){--height:calc(100% - (var(--ion-safe-area-top) + 10px))}:host(.modal-sheet) .modal-wrapper,:host(.modal-sheet) .modal-shadow{position:absolute;bottom:0}:host(.modal-sheet.modal-no-expand-scroll) ion-footer{position:absolute;bottom:0;width:var(--width)}:host{--backdrop-opacity:var(--ion-backdrop-opacity, 0.32)}@media only screen and (min-width: 768px) and (min-height: 600px){:host{--border-radius:2px;--box-shadow:0 28px 48px rgba(0, 0, 0, 0.4)}}.modal-wrapper{-webkit-transform:translate3d(0, 40px, 0);transform:translate3d(0, 40px, 0);opacity:0.01}";
1481
1477
 
1482
1478
  const Modal = /*@__PURE__*/ proxyCustomElement(class Modal extends HTMLElement {
1483
1479
  constructor(registerHost) {
@@ -1504,10 +1500,6 @@ const Modal = /*@__PURE__*/ proxyCustomElement(class Modal extends HTMLElement {
1504
1500
  this.inline = false;
1505
1501
  // Whether or not modal is being dismissed via gesture
1506
1502
  this.gestureAnimationDismissing = false;
1507
- // Whether to skip coordinate-based safe-area detection (for fullscreen phone modals)
1508
- this.skipSafeAreaCoordinateDetection = false;
1509
- // Track previous safe-area state to avoid redundant DOM writes
1510
- this.prevSafeAreaState = { top: false, bottom: false, left: false, right: false };
1511
1503
  this.presented = false;
1512
1504
  /** @internal */
1513
1505
  this.hasController = false;
@@ -1698,10 +1690,7 @@ const Modal = /*@__PURE__*/ proxyCustomElement(class Modal extends HTMLElement {
1698
1690
  }
1699
1691
  }
1700
1692
  onWindowResize() {
1701
- // Invalidate safe-area cache on resize (device rotation may change values)
1702
- this.cachedSafeAreas = undefined;
1703
- this.updateSafeAreaOverrides();
1704
- // Only handle view transition for iOS card modals when no custom animations are provided
1693
+ // Only handle resize for iOS card modals when no custom animations are provided
1705
1694
  if (getIonMode(this) !== 'ios' || !this.presentingElement || this.enterAnimation || this.leaveAnimation) {
1706
1695
  return;
1707
1696
  }
@@ -1724,8 +1713,6 @@ const Modal = /*@__PURE__*/ proxyCustomElement(class Modal extends HTMLElement {
1724
1713
  this.triggerController.removeClickListener();
1725
1714
  this.cleanupViewTransitionListener();
1726
1715
  this.cleanupParentRemovalObserver();
1727
- // Reset safe-area state to handle removal without dismiss (e.g., framework unmount)
1728
- this.resetSafeAreaState();
1729
1716
  }
1730
1717
  componentWillLoad() {
1731
1718
  var _a;
@@ -1885,8 +1872,6 @@ const Modal = /*@__PURE__*/ proxyCustomElement(class Modal extends HTMLElement {
1885
1872
  else if (!this.keepContentsMounted) {
1886
1873
  await waitForMount();
1887
1874
  }
1888
- // Predict safe-area needs based on modal configuration to avoid visual snap
1889
- this.setInitialSafeAreaOverrides(presentingElement);
1890
1875
  writeTask(() => this.el.classList.add('show-modal'));
1891
1876
  const hasCardModal = presentingElement !== undefined;
1892
1877
  /**
@@ -1948,8 +1933,6 @@ const Modal = /*@__PURE__*/ proxyCustomElement(class Modal extends HTMLElement {
1948
1933
  else if (hasCardModal) {
1949
1934
  this.initSwipeToClose();
1950
1935
  }
1951
- // Now that animation is complete, update safe-area based on actual position
1952
- this.updateSafeAreaOverrides();
1953
1936
  // Initialize view transition listener for iOS card modals
1954
1937
  this.initViewTransitionListener();
1955
1938
  // Initialize parent removal observer
@@ -2001,7 +1984,7 @@ const Modal = /*@__PURE__*/ proxyCustomElement(class Modal extends HTMLElement {
2001
1984
  await this.dismiss(undefined, GESTURE);
2002
1985
  this.gestureAnimationDismissing = false;
2003
1986
  });
2004
- }, () => this.updateSafeAreaOverrides());
1987
+ });
2005
1988
  this.gesture.enable(true);
2006
1989
  }
2007
1990
  initSheetGesture() {
@@ -2022,8 +2005,7 @@ const Modal = /*@__PURE__*/ proxyCustomElement(class Modal extends HTMLElement {
2022
2005
  this.currentBreakpoint = breakpoint;
2023
2006
  this.ionBreakpointDidChange.emit({ breakpoint });
2024
2007
  }
2025
- this.updateSafeAreaOverrides();
2026
- }, () => this.updateSafeAreaOverrides());
2008
+ });
2027
2009
  this.gesture = gesture;
2028
2010
  this.moveSheetToBreakpoint = moveSheetToBreakpoint;
2029
2011
  this.gesture.enable(true);
@@ -2101,194 +2083,6 @@ const Modal = /*@__PURE__*/ proxyCustomElement(class Modal extends HTMLElement {
2101
2083
  // Clear the cached reference
2102
2084
  this.cachedPageParent = undefined;
2103
2085
  }
2104
- /**
2105
- * Sets initial safe-area overrides based on modal configuration before
2106
- * the modal becomes visible. This predicts whether the modal will touch
2107
- * screen edges to avoid a visual snap after animation completes.
2108
- */
2109
- setInitialSafeAreaOverrides(presentingElement) {
2110
- const style = this.el.style;
2111
- const mode = getIonMode(this);
2112
- const isSheetModal = this.breakpoints !== undefined && this.initialBreakpoint !== undefined;
2113
- // Card modals only exist in iOS mode - in MD mode, presentingElement is ignored
2114
- const isCardModal = presentingElement !== undefined && mode === 'ios';
2115
- const isTablet = window.innerWidth >= 768;
2116
- // Sheet modals always touch bottom edge, never top/left/right
2117
- if (isSheetModal) {
2118
- style.setProperty('--ion-safe-area-top', '0px');
2119
- style.setProperty('--ion-safe-area-left', '0px');
2120
- style.setProperty('--ion-safe-area-right', '0px');
2121
- return;
2122
- }
2123
- // Card modals have rounded top corners
2124
- if (isCardModal) {
2125
- style.setProperty('--ion-safe-area-top', '0px');
2126
- if (isTablet) {
2127
- // On tablets, card modals are inset from all edges
2128
- this.zeroAllSafeAreas();
2129
- }
2130
- else {
2131
- // On phones, card modals still extend to the bottom edge
2132
- style.setProperty('--ion-safe-area-left', '0px');
2133
- style.setProperty('--ion-safe-area-right', '0px');
2134
- this.applyFullscreenSafeArea();
2135
- }
2136
- return;
2137
- }
2138
- // Check if modal is fullscreen via CSS custom properties
2139
- // This applies to both phone and tablet sizes - custom modals may have
2140
- // non-fullscreen dimensions even on phones (e.g., --height: 70%)
2141
- const computedStyle = getComputedStyle(this.el);
2142
- const width = computedStyle.getPropertyValue('--width').trim();
2143
- const height = computedStyle.getPropertyValue('--height').trim();
2144
- const isFullscreen = width === '100%' && height === '100%';
2145
- if (isFullscreen) {
2146
- this.applyFullscreenSafeArea();
2147
- }
2148
- else if (isTablet) {
2149
- // Centered dialog on tablet doesn't touch edges
2150
- this.zeroAllSafeAreas();
2151
- }
2152
- else ;
2153
- }
2154
- /**
2155
- * Applies safe-area handling for fullscreen modals.
2156
- * Adds wrapper padding when no footer is present to prevent
2157
- * content from overlapping system navigation areas.
2158
- */
2159
- applyFullscreenSafeArea() {
2160
- this.skipSafeAreaCoordinateDetection = true;
2161
- this.updateFooterPadding();
2162
- // Watch for dynamic footer additions/removals (e.g., async data loading)
2163
- // Use subtree:true to support wrapped footers in framework components
2164
- // (e.g., <my-footer><ion-footer>...</ion-footer></my-footer>)
2165
- if (!this.footerObserver && win !== undefined && 'MutationObserver' in win) {
2166
- this.footerObserver = new MutationObserver(() => this.updateFooterPadding());
2167
- this.footerObserver.observe(this.el, { childList: true, subtree: true });
2168
- }
2169
- }
2170
- /**
2171
- * Updates wrapper and shadow padding based on footer presence.
2172
- * Called initially and when footer is dynamically added/removed.
2173
- * Both elements must be styled identically to prevent visual mismatches.
2174
- */
2175
- updateFooterPadding() {
2176
- if (!this.wrapperEl)
2177
- return;
2178
- const hasFooter = this.el.querySelector('ion-footer') !== null;
2179
- // Apply to both wrapper and shadow to keep them in sync
2180
- const elements = [this.wrapperEl, this.shadowEl].filter(Boolean);
2181
- if (hasFooter) {
2182
- elements.forEach((el) => {
2183
- el.style.removeProperty('padding-bottom');
2184
- el.style.removeProperty('box-sizing');
2185
- });
2186
- }
2187
- else {
2188
- elements.forEach((el) => {
2189
- el.style.setProperty('padding-bottom', 'var(--ion-safe-area-bottom, 0px)');
2190
- el.style.setProperty('box-sizing', 'border-box');
2191
- });
2192
- }
2193
- }
2194
- /**
2195
- * Sets all safe-area CSS variables to 0px for modals that
2196
- * don't touch screen edges.
2197
- */
2198
- zeroAllSafeAreas() {
2199
- const style = this.el.style;
2200
- style.setProperty('--ion-safe-area-top', '0px');
2201
- style.setProperty('--ion-safe-area-bottom', '0px');
2202
- style.setProperty('--ion-safe-area-left', '0px');
2203
- style.setProperty('--ion-safe-area-right', '0px');
2204
- }
2205
- /**
2206
- * Resets all safe-area related state and styles.
2207
- * Called during dismiss and disconnectedCallback to ensure clean state
2208
- * for re-presentation of inline modals.
2209
- */
2210
- resetSafeAreaState() {
2211
- var _a;
2212
- this.skipSafeAreaCoordinateDetection = false;
2213
- this.cachedSafeAreas = undefined;
2214
- this.prevSafeAreaState = { top: false, bottom: false, left: false, right: false };
2215
- (_a = this.footerObserver) === null || _a === void 0 ? void 0 : _a.disconnect();
2216
- this.footerObserver = undefined;
2217
- // Clear wrapper and shadow styles that may have been set for safe-area handling
2218
- [this.wrapperEl, this.shadowEl].forEach((el) => {
2219
- if (el) {
2220
- el.style.removeProperty('padding-bottom');
2221
- el.style.removeProperty('box-sizing');
2222
- }
2223
- });
2224
- // Clear safe-area CSS variable overrides
2225
- const style = this.el.style;
2226
- style.removeProperty('--ion-safe-area-top');
2227
- style.removeProperty('--ion-safe-area-bottom');
2228
- style.removeProperty('--ion-safe-area-left');
2229
- style.removeProperty('--ion-safe-area-right');
2230
- }
2231
- /**
2232
- * Gets the root safe-area values from the document element.
2233
- * Uses cached values during gestures to avoid getComputedStyle calls.
2234
- */
2235
- getSafeAreaValues() {
2236
- if (!this.cachedSafeAreas) {
2237
- const rootStyle = getComputedStyle(document.documentElement);
2238
- this.cachedSafeAreas = {
2239
- top: parseFloat(rootStyle.getPropertyValue('--ion-safe-area-top')) || 0,
2240
- bottom: parseFloat(rootStyle.getPropertyValue('--ion-safe-area-bottom')) || 0,
2241
- left: parseFloat(rootStyle.getPropertyValue('--ion-safe-area-left')) || 0,
2242
- right: parseFloat(rootStyle.getPropertyValue('--ion-safe-area-right')) || 0,
2243
- };
2244
- }
2245
- return this.cachedSafeAreas;
2246
- }
2247
- /**
2248
- * Updates safe-area CSS variable overrides based on whether the modal
2249
- * extends into each safe-area region. Called after animation
2250
- * and during gestures to handle dynamic position changes.
2251
- *
2252
- * Optimized to avoid redundant DOM writes by tracking previous state.
2253
- */
2254
- updateSafeAreaOverrides() {
2255
- if (this.skipSafeAreaCoordinateDetection) {
2256
- return;
2257
- }
2258
- const wrapper = this.wrapperEl;
2259
- if (!wrapper) {
2260
- return;
2261
- }
2262
- const rect = wrapper.getBoundingClientRect();
2263
- const safeAreas = this.getSafeAreaValues();
2264
- const extendsIntoTop = rect.top < safeAreas.top;
2265
- const extendsIntoBottom = rect.bottom > window.innerHeight - safeAreas.bottom;
2266
- const extendsIntoLeft = rect.left < safeAreas.left;
2267
- const extendsIntoRight = rect.right > window.innerWidth - safeAreas.right;
2268
- // Only update DOM when state actually changes
2269
- const prev = this.prevSafeAreaState;
2270
- const style = this.el.style;
2271
- if (extendsIntoTop !== prev.top) {
2272
- extendsIntoTop ? style.removeProperty('--ion-safe-area-top') : style.setProperty('--ion-safe-area-top', '0px');
2273
- prev.top = extendsIntoTop;
2274
- }
2275
- if (extendsIntoBottom !== prev.bottom) {
2276
- extendsIntoBottom
2277
- ? style.removeProperty('--ion-safe-area-bottom')
2278
- : style.setProperty('--ion-safe-area-bottom', '0px');
2279
- prev.bottom = extendsIntoBottom;
2280
- }
2281
- if (extendsIntoLeft !== prev.left) {
2282
- extendsIntoLeft ? style.removeProperty('--ion-safe-area-left') : style.setProperty('--ion-safe-area-left', '0px');
2283
- prev.left = extendsIntoLeft;
2284
- }
2285
- if (extendsIntoRight !== prev.right) {
2286
- extendsIntoRight
2287
- ? style.removeProperty('--ion-safe-area-right')
2288
- : style.setProperty('--ion-safe-area-right', '0px');
2289
- prev.right = extendsIntoRight;
2290
- }
2291
- }
2292
2086
  sheetOnDismiss() {
2293
2087
  /**
2294
2088
  * While the gesture animation is finishing
@@ -2381,8 +2175,6 @@ const Modal = /*@__PURE__*/ proxyCustomElement(class Modal extends HTMLElement {
2381
2175
  }
2382
2176
  this.currentBreakpoint = undefined;
2383
2177
  this.animation = undefined;
2384
- // Reset safe-area state for potential re-presentation
2385
- this.resetSafeAreaState();
2386
2178
  unlock();
2387
2179
  return dismissed;
2388
2180
  }
@@ -2632,20 +2424,20 @@ const Modal = /*@__PURE__*/ proxyCustomElement(class Modal extends HTMLElement {
2632
2424
  const isCardModal = presentingElement !== undefined && mode === 'ios';
2633
2425
  const isHandleCycle = handleBehavior === 'cycle';
2634
2426
  const isSheetModalWithHandle = isSheetModal && showHandle;
2635
- return (h(Host, Object.assign({ key: '8f42c71ec9c9270b4218ca7eec57ca998871ac07', "no-router": true,
2427
+ return (h(Host, Object.assign({ key: '87328006ea6c75ebc518ace300438492a567223e', "no-router": true,
2636
2428
  // Allow the modal to be navigable when the handle is focusable
2637
2429
  tabIndex: isHandleCycle && isSheetModalWithHandle ? 0 : -1 }, htmlAttributes, { style: {
2638
2430
  zIndex: `${20000 + this.overlayIndex}`,
2639
- }, 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: '2f7b08b019c66cbfceacafa9a68b91f8da1f4084', ref: (el) => (this.backdropEl = el), visible: this.showBackdrop, tappable: this.backdropDismiss, part: "backdrop" }), mode === 'ios' && h("div", { key: '6b0d1ae90e8483332f74371be5dcbd0a7b2661ba', class: "modal-shadow", ref: (el) => (this.shadowEl = el) }), h("div", Object.assign({ key: 'c96f671fb25e5de45231ea65ac52500547b2e262',
2431
+ }, 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: 'ee94ff8e09b691dd4ad4e4db1720f06bc3c5a469', ref: (el) => (this.backdropEl = el), visible: this.showBackdrop, tappable: this.backdropDismiss, part: "backdrop" }), mode === 'ios' && h("div", { key: 'bffd69b4635c22d9f249725bd952c1e93d5615c7', class: "modal-shadow" }), h("div", Object.assign({ key: '1d394d3c68916e464ff1fbf5242419f4a3d3cca1',
2640
2432
  /*
2641
2433
  role and aria-modal must be used on the
2642
2434
  same element. They must also be set inside the
2643
2435
  shadow DOM otherwise ion-button will not be highlighted
2644
2436
  when using VoiceOver: https://bugs.webkit.org/show_bug.cgi?id=247134
2645
2437
  */
2646
- role: "dialog" }, inheritedAttributes, { "aria-modal": "true", class: "modal-wrapper ion-overlay-wrapper", part: "content", ref: (el) => (this.wrapperEl = el) }), showHandle && (h("button", { key: 'e07419b01a588c0ba62ed9607c843cac7bd26337', class: "modal-handle",
2438
+ role: "dialog" }, inheritedAttributes, { "aria-modal": "true", class: "modal-wrapper ion-overlay-wrapper", part: "content", ref: (el) => (this.wrapperEl = el) }), showHandle && (h("button", { key: '2dcf58792018e557e0c323baad2d672bc99c0bb1', class: "modal-handle",
2647
2439
  // Prevents the handle from receiving keyboard focus when it does not cycle
2648
- 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: '65f35079df8eb8b6cd262e3a08297866715ce7ea', onSlotchange: this.onSlotChange }))));
2440
+ 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: '44164b1e8710c3895400ad9f44ecd99873874ad5', onSlotchange: this.onSlotChange }))));
2649
2441
  }
2650
2442
  get el() { return this; }
2651
2443
  static get watchers() { return {