@ionic/core 8.7.17-dev.11768239180.18ee1069 → 8.7.17-dev.11769628168.11eca7cd

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 (39) hide show
  1. package/components/content.js +4 -3
  2. package/components/ion-range.js +12 -4
  3. package/components/modal.js +12 -213
  4. package/components/popover.js +11 -83
  5. package/dist/cjs/ion-app_8.cjs.entry.js +4 -3
  6. package/dist/cjs/ion-modal.cjs.entry.js +12 -213
  7. package/dist/cjs/ion-popover.cjs.entry.js +11 -83
  8. package/dist/cjs/ion-range.cjs.entry.js +12 -4
  9. package/dist/collection/components/content/content.js +4 -3
  10. package/dist/collection/components/modal/gestures/sheet.js +1 -3
  11. package/dist/collection/components/modal/gestures/swipe-to-close.js +1 -3
  12. package/dist/collection/components/modal/modal.ios.css +4 -0
  13. package/dist/collection/components/modal/modal.js +7 -205
  14. package/dist/collection/components/modal/modal.md.css +4 -0
  15. package/dist/collection/components/popover/animations/ios.enter.js +5 -21
  16. package/dist/collection/components/popover/animations/md.enter.js +5 -30
  17. package/dist/collection/components/popover/utils.js +1 -32
  18. package/dist/collection/components/range/range.js +12 -4
  19. package/dist/docs.json +1 -1
  20. package/dist/esm/ion-app_8.entry.js +4 -3
  21. package/dist/esm/ion-modal.entry.js +12 -213
  22. package/dist/esm/ion-popover.entry.js +11 -83
  23. package/dist/esm/ion-range.entry.js +12 -4
  24. package/dist/ionic/ionic.esm.js +1 -1
  25. package/dist/ionic/p-012212e4.entry.js +4 -0
  26. package/dist/ionic/p-91840a80.entry.js +4 -0
  27. package/dist/ionic/p-c73627c8.entry.js +4 -0
  28. package/dist/ionic/p-f9061316.entry.js +4 -0
  29. package/dist/types/components/modal/gestures/sheet.d.ts +1 -1
  30. package/dist/types/components/modal/gestures/swipe-to-close.d.ts +1 -1
  31. package/dist/types/components/modal/modal.d.ts +0 -45
  32. package/dist/types/components/popover/utils.d.ts +0 -2
  33. package/hydrate/index.js +38 -302
  34. package/hydrate/index.mjs +38 -302
  35. package/package.json +1 -1
  36. package/dist/ionic/p-1647c46c.entry.js +0 -4
  37. package/dist/ionic/p-732b2fd6.entry.js +0 -4
  38. package/dist/ionic/p-968a55d1.entry.js +0 -4
  39. package/dist/ionic/p-ec9ca3fe.entry.js +0 -4
package/hydrate/index.js CHANGED
@@ -10849,20 +10849,21 @@ class Content {
10849
10849
  const forceOverscroll = this.shouldForceOverscroll();
10850
10850
  const transitionShadow = mode === 'ios';
10851
10851
  this.resize();
10852
- return (hAsync(Host, Object.assign({ key: 'cd8781f848d8dc926fe66f43d43c49564425a507', role: isMainContent ? 'main' : undefined, class: createColorClasses$1(this.color, {
10852
+ return (hAsync(Host, Object.assign({ key: '212b1438f044061887984e02e1c8943ee1d33c20', role: isMainContent ? 'main' : undefined, class: createColorClasses$1(this.color, {
10853
10853
  [mode]: true,
10854
+ 'content-fullscreen': this.fullscreen,
10854
10855
  'content-sizing': hostContext('ion-popover', this.el),
10855
10856
  overscroll: forceOverscroll,
10856
10857
  [`content-${rtl}`]: true,
10857
10858
  }), style: {
10858
10859
  '--offset-top': `${this.cTop}px`,
10859
10860
  '--offset-bottom': `${this.cBottom}px`,
10860
- } }, inheritedAttributes), hAsync("div", { key: '95b112d7cae30f22ef778ceffb88edb4d941c170', ref: (el) => (this.backgroundContentEl = el), id: "background-content", part: "background" }), fixedSlotPlacement === 'before' ? hAsync("slot", { name: "fixed" }) : null, hAsync("div", { key: '2fdfcbc39fb66f11b6191911f2941c660f4c12e5', class: {
10861
+ } }, inheritedAttributes), hAsync("div", { key: 'ea46641492eef8cc7b08fc398d0285115b5a7100', ref: (el) => (this.backgroundContentEl = el), id: "background-content", part: "background" }), fixedSlotPlacement === 'before' ? hAsync("slot", { name: "fixed" }) : null, hAsync("div", { key: 'dc9096f0b97ab6145fb46cf065cd244f4af1cab5', class: {
10861
10862
  'inner-scroll': true,
10862
10863
  'scroll-x': scrollX,
10863
10864
  'scroll-y': scrollY,
10864
10865
  overscroll: (scrollX || scrollY) && forceOverscroll,
10865
- }, ref: (scrollEl) => (this.scrollEl = scrollEl), onScroll: this.scrollEvents ? (ev) => this.onScroll(ev) : undefined, part: "scroll" }, hAsync("slot", { key: '6bc77e0054ec8e21635a7f2abfe0ca46e0962e03' })), transitionShadow ? (hAsync("div", { class: "transition-effect" }, hAsync("div", { class: "transition-cover" }), hAsync("div", { class: "transition-shadow" }))) : null, fixedSlotPlacement === 'after' ? hAsync("slot", { name: "fixed" }) : null));
10866
+ }, ref: (scrollEl) => (this.scrollEl = scrollEl), onScroll: this.scrollEvents ? (ev) => this.onScroll(ev) : undefined, part: "scroll" }, hAsync("slot", { key: '4b13fd5b7e124353d43b47a30e975400ae2a0341' })), transitionShadow ? (hAsync("div", { class: "transition-effect" }, hAsync("div", { class: "transition-cover" }), hAsync("div", { class: "transition-shadow" }))) : null, fixedSlotPlacement === 'after' ? hAsync("slot", { name: "fixed" }) : null));
10866
10867
  }
10867
10868
  get el() { return getElement(this); }
10868
10869
  static get style() { return contentCss; }
@@ -21533,7 +21534,7 @@ const calculateSpringStep = (t) => {
21533
21534
  const SwipeToCloseDefaults = {
21534
21535
  MIN_PRESENTING_SCALE: 0.915,
21535
21536
  };
21536
- const createSwipeToCloseGesture = (el, animation, statusBarStyle, onDismiss, onGestureMove) => {
21537
+ const createSwipeToCloseGesture = (el, animation, statusBarStyle, onDismiss) => {
21537
21538
  /**
21538
21539
  * The step value at which a card modal
21539
21540
  * is eligible for dismissing via gesture.
@@ -21690,8 +21691,6 @@ const createSwipeToCloseGesture = (el, animation, statusBarStyle, onDismiss, onG
21690
21691
  const processedStep = isAttemptingDismissWithCanDismiss ? calculateSpringStep(step / maxStep) : step;
21691
21692
  const clampedStep = clamp(0.0001, processedStep, maxStep);
21692
21693
  animation.progressStep(clampedStep);
21693
- // Notify modal of position change for safe-area updates
21694
- onGestureMove === null || onGestureMove === void 0 ? void 0 : onGestureMove();
21695
21694
  /**
21696
21695
  * When swiping down half way, the status bar style
21697
21696
  * should be reset to its default value.
@@ -22235,7 +22234,7 @@ const mdLeaveAnimation$2 = (baseEl, opts) => {
22235
22234
  return baseAnimation;
22236
22235
  };
22237
22236
 
22238
- const createSheetGesture = (baseEl, backdropEl, wrapperEl, initialBreakpoint, backdropBreakpoint, animation, breakpoints = [], expandToScroll, getCurrentBreakpoint, onDismiss, onBreakpointChange, onGestureMove) => {
22237
+ const createSheetGesture = (baseEl, backdropEl, wrapperEl, initialBreakpoint, backdropBreakpoint, animation, breakpoints = [], expandToScroll, getCurrentBreakpoint, onDismiss, onBreakpointChange) => {
22239
22238
  // Defaults for the sheet swipe animation
22240
22239
  const defaultBackdrop = [
22241
22240
  { offset: 0, opacity: 'var(--backdrop-opacity)' },
@@ -22566,8 +22565,6 @@ const createSheetGesture = (baseEl, backdropEl, wrapperEl, initialBreakpoint, ba
22566
22565
  : step;
22567
22566
  offset = clamp(0.0001, processedStep, maxStep);
22568
22567
  animation.progressStep(offset);
22569
- // Notify modal of position change for safe-area updates
22570
- onGestureMove === null || onGestureMove === void 0 ? void 0 : onGestureMove();
22571
22568
  };
22572
22569
  const onEnd = (detail) => {
22573
22570
  /**
@@ -22762,9 +22759,9 @@ const createSheetGesture = (baseEl, backdropEl, wrapperEl, initialBreakpoint, ba
22762
22759
  };
22763
22760
  };
22764
22761
 
22765
- 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}";
22762
+ 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}";
22766
22763
 
22767
- 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}";
22764
+ 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}";
22768
22765
 
22769
22766
  // TODO(FW-2832): types
22770
22767
  /**
@@ -22797,10 +22794,6 @@ class Modal {
22797
22794
  this.inline = false;
22798
22795
  // Whether or not modal is being dismissed via gesture
22799
22796
  this.gestureAnimationDismissing = false;
22800
- // Whether to skip coordinate-based safe-area detection (for fullscreen phone modals)
22801
- this.skipSafeAreaCoordinateDetection = false;
22802
- // Track previous safe-area state to avoid redundant DOM writes
22803
- this.prevSafeAreaState = { top: false, bottom: false, left: false, right: false };
22804
22797
  this.presented = false;
22805
22798
  /** @internal */
22806
22799
  this.hasController = false;
@@ -22991,10 +22984,7 @@ class Modal {
22991
22984
  }
22992
22985
  }
22993
22986
  onWindowResize() {
22994
- // Invalidate safe-area cache on resize (device rotation may change values)
22995
- this.cachedSafeAreas = undefined;
22996
- this.updateSafeAreaOverrides();
22997
- // Only handle view transition for iOS card modals when no custom animations are provided
22987
+ // Only handle resize for iOS card modals when no custom animations are provided
22998
22988
  if (getIonMode$1(this) !== 'ios' || !this.presentingElement || this.enterAnimation || this.leaveAnimation) {
22999
22989
  return;
23000
22990
  }
@@ -23017,8 +23007,6 @@ class Modal {
23017
23007
  this.triggerController.removeClickListener();
23018
23008
  this.cleanupViewTransitionListener();
23019
23009
  this.cleanupParentRemovalObserver();
23020
- // Reset safe-area state to handle removal without dismiss (e.g., framework unmount)
23021
- this.resetSafeAreaState();
23022
23010
  }
23023
23011
  componentWillLoad() {
23024
23012
  var _a;
@@ -23178,8 +23166,6 @@ class Modal {
23178
23166
  else if (!this.keepContentsMounted) {
23179
23167
  await waitForMount();
23180
23168
  }
23181
- // Predict safe-area needs based on modal configuration to avoid visual snap
23182
- this.setInitialSafeAreaOverrides(presentingElement);
23183
23169
  writeTask(() => this.el.classList.add('show-modal'));
23184
23170
  const hasCardModal = presentingElement !== undefined;
23185
23171
  /**
@@ -23241,8 +23227,6 @@ class Modal {
23241
23227
  else if (hasCardModal) {
23242
23228
  this.initSwipeToClose();
23243
23229
  }
23244
- // Now that animation is complete, update safe-area based on actual position
23245
- this.updateSafeAreaOverrides();
23246
23230
  // Initialize view transition listener for iOS card modals
23247
23231
  this.initViewTransitionListener();
23248
23232
  // Initialize parent removal observer
@@ -23294,7 +23278,7 @@ class Modal {
23294
23278
  await this.dismiss(undefined, GESTURE);
23295
23279
  this.gestureAnimationDismissing = false;
23296
23280
  });
23297
- }, () => this.updateSafeAreaOverrides());
23281
+ });
23298
23282
  this.gesture.enable(true);
23299
23283
  }
23300
23284
  initSheetGesture() {
@@ -23315,8 +23299,7 @@ class Modal {
23315
23299
  this.currentBreakpoint = breakpoint;
23316
23300
  this.ionBreakpointDidChange.emit({ breakpoint });
23317
23301
  }
23318
- this.updateSafeAreaOverrides();
23319
- }, () => this.updateSafeAreaOverrides());
23302
+ });
23320
23303
  this.gesture = gesture;
23321
23304
  this.moveSheetToBreakpoint = moveSheetToBreakpoint;
23322
23305
  this.gesture.enable(true);
@@ -23394,187 +23377,6 @@ class Modal {
23394
23377
  // Clear the cached reference
23395
23378
  this.cachedPageParent = undefined;
23396
23379
  }
23397
- /**
23398
- * Sets initial safe-area overrides based on modal configuration before
23399
- * the modal becomes visible. This predicts whether the modal will touch
23400
- * screen edges to avoid a visual snap after animation completes.
23401
- */
23402
- setInitialSafeAreaOverrides(presentingElement) {
23403
- const style = this.el.style;
23404
- const mode = getIonMode$1(this);
23405
- const isSheetModal = this.breakpoints !== undefined && this.initialBreakpoint !== undefined;
23406
- // Card modals only exist in iOS mode - in MD mode, presentingElement is ignored
23407
- const isCardModal = presentingElement !== undefined && mode === 'ios';
23408
- const isTablet = window.innerWidth >= 768;
23409
- // Sheet modals always touch bottom edge, never top/left/right
23410
- if (isSheetModal) {
23411
- style.setProperty('--ion-safe-area-top', '0px');
23412
- style.setProperty('--ion-safe-area-left', '0px');
23413
- style.setProperty('--ion-safe-area-right', '0px');
23414
- return;
23415
- }
23416
- // Card modals have rounded top corners
23417
- if (isCardModal) {
23418
- style.setProperty('--ion-safe-area-top', '0px');
23419
- if (isTablet) {
23420
- // On tablets, card modals are inset from all edges
23421
- this.zeroAllSafeAreas();
23422
- }
23423
- else {
23424
- // On phones, card modals still extend to the bottom edge
23425
- style.setProperty('--ion-safe-area-left', '0px');
23426
- style.setProperty('--ion-safe-area-right', '0px');
23427
- this.applyFullscreenSafeArea();
23428
- }
23429
- return;
23430
- }
23431
- // Phone-sized fullscreen modals inherit safe areas and use wrapper padding
23432
- if (!isTablet) {
23433
- this.applyFullscreenSafeArea();
23434
- return;
23435
- }
23436
- // Check if tablet modal is fullscreen via CSS custom properties
23437
- const computedStyle = getComputedStyle(this.el);
23438
- const width = computedStyle.getPropertyValue('--width').trim();
23439
- const height = computedStyle.getPropertyValue('--height').trim();
23440
- const isFullscreen = width === '100%' && height === '100%';
23441
- if (isFullscreen) {
23442
- this.applyFullscreenSafeArea();
23443
- }
23444
- else {
23445
- // Centered dialog doesn't touch edges
23446
- this.zeroAllSafeAreas();
23447
- }
23448
- }
23449
- /**
23450
- * Applies safe-area handling for fullscreen modals.
23451
- * Adds wrapper padding when no footer is present to prevent
23452
- * content from overlapping system navigation areas.
23453
- */
23454
- applyFullscreenSafeArea() {
23455
- this.skipSafeAreaCoordinateDetection = true;
23456
- this.updateFooterPadding();
23457
- // Watch for dynamic footer additions/removals (e.g., async data loading)
23458
- // Use subtree:true to support wrapped footers in framework components
23459
- // (e.g., <my-footer><ion-footer>...</ion-footer></my-footer>)
23460
- if (!this.footerObserver && win$1 !== undefined && 'MutationObserver' in win$1) {
23461
- this.footerObserver = new MutationObserver(() => this.updateFooterPadding());
23462
- this.footerObserver.observe(this.el, { childList: true, subtree: true });
23463
- }
23464
- }
23465
- /**
23466
- * Updates wrapper padding based on footer presence.
23467
- * Called initially and when footer is dynamically added/removed.
23468
- */
23469
- updateFooterPadding() {
23470
- if (!this.wrapperEl)
23471
- return;
23472
- const hasFooter = this.el.querySelector('ion-footer') !== null;
23473
- if (hasFooter) {
23474
- this.wrapperEl.style.removeProperty('padding-bottom');
23475
- this.wrapperEl.style.removeProperty('box-sizing');
23476
- }
23477
- else {
23478
- this.wrapperEl.style.setProperty('padding-bottom', 'var(--ion-safe-area-bottom, 0px)');
23479
- this.wrapperEl.style.setProperty('box-sizing', 'border-box');
23480
- }
23481
- }
23482
- /**
23483
- * Sets all safe-area CSS variables to 0px for modals that
23484
- * don't touch screen edges.
23485
- */
23486
- zeroAllSafeAreas() {
23487
- const style = this.el.style;
23488
- style.setProperty('--ion-safe-area-top', '0px');
23489
- style.setProperty('--ion-safe-area-bottom', '0px');
23490
- style.setProperty('--ion-safe-area-left', '0px');
23491
- style.setProperty('--ion-safe-area-right', '0px');
23492
- }
23493
- /**
23494
- * Resets all safe-area related state and styles.
23495
- * Called during dismiss and disconnectedCallback to ensure clean state
23496
- * for re-presentation of inline modals.
23497
- */
23498
- resetSafeAreaState() {
23499
- var _a;
23500
- this.skipSafeAreaCoordinateDetection = false;
23501
- this.cachedSafeAreas = undefined;
23502
- this.prevSafeAreaState = { top: false, bottom: false, left: false, right: false };
23503
- (_a = this.footerObserver) === null || _a === void 0 ? void 0 : _a.disconnect();
23504
- this.footerObserver = undefined;
23505
- // Clear wrapper styles that may have been set for safe-area handling
23506
- if (this.wrapperEl) {
23507
- this.wrapperEl.style.removeProperty('padding-bottom');
23508
- this.wrapperEl.style.removeProperty('box-sizing');
23509
- }
23510
- // Clear safe-area CSS variable overrides
23511
- const style = this.el.style;
23512
- style.removeProperty('--ion-safe-area-top');
23513
- style.removeProperty('--ion-safe-area-bottom');
23514
- style.removeProperty('--ion-safe-area-left');
23515
- style.removeProperty('--ion-safe-area-right');
23516
- }
23517
- /**
23518
- * Gets the root safe-area values from the document element.
23519
- * Uses cached values during gestures to avoid getComputedStyle calls.
23520
- */
23521
- getSafeAreaValues() {
23522
- if (!this.cachedSafeAreas) {
23523
- const rootStyle = getComputedStyle(document.documentElement);
23524
- this.cachedSafeAreas = {
23525
- top: parseFloat(rootStyle.getPropertyValue('--ion-safe-area-top')) || 0,
23526
- bottom: parseFloat(rootStyle.getPropertyValue('--ion-safe-area-bottom')) || 0,
23527
- left: parseFloat(rootStyle.getPropertyValue('--ion-safe-area-left')) || 0,
23528
- right: parseFloat(rootStyle.getPropertyValue('--ion-safe-area-right')) || 0,
23529
- };
23530
- }
23531
- return this.cachedSafeAreas;
23532
- }
23533
- /**
23534
- * Updates safe-area CSS variable overrides based on whether the modal
23535
- * extends into each safe-area region. Called after animation
23536
- * and during gestures to handle dynamic position changes.
23537
- *
23538
- * Optimized to avoid redundant DOM writes by tracking previous state.
23539
- */
23540
- updateSafeAreaOverrides() {
23541
- if (this.skipSafeAreaCoordinateDetection) {
23542
- return;
23543
- }
23544
- const wrapper = this.wrapperEl;
23545
- if (!wrapper) {
23546
- return;
23547
- }
23548
- const rect = wrapper.getBoundingClientRect();
23549
- const safeAreas = this.getSafeAreaValues();
23550
- const extendsIntoTop = rect.top < safeAreas.top;
23551
- const extendsIntoBottom = rect.bottom > window.innerHeight - safeAreas.bottom;
23552
- const extendsIntoLeft = rect.left < safeAreas.left;
23553
- const extendsIntoRight = rect.right > window.innerWidth - safeAreas.right;
23554
- // Only update DOM when state actually changes
23555
- const prev = this.prevSafeAreaState;
23556
- const style = this.el.style;
23557
- if (extendsIntoTop !== prev.top) {
23558
- extendsIntoTop ? style.removeProperty('--ion-safe-area-top') : style.setProperty('--ion-safe-area-top', '0px');
23559
- prev.top = extendsIntoTop;
23560
- }
23561
- if (extendsIntoBottom !== prev.bottom) {
23562
- extendsIntoBottom
23563
- ? style.removeProperty('--ion-safe-area-bottom')
23564
- : style.setProperty('--ion-safe-area-bottom', '0px');
23565
- prev.bottom = extendsIntoBottom;
23566
- }
23567
- if (extendsIntoLeft !== prev.left) {
23568
- extendsIntoLeft ? style.removeProperty('--ion-safe-area-left') : style.setProperty('--ion-safe-area-left', '0px');
23569
- prev.left = extendsIntoLeft;
23570
- }
23571
- if (extendsIntoRight !== prev.right) {
23572
- extendsIntoRight
23573
- ? style.removeProperty('--ion-safe-area-right')
23574
- : style.setProperty('--ion-safe-area-right', '0px');
23575
- prev.right = extendsIntoRight;
23576
- }
23577
- }
23578
23380
  sheetOnDismiss() {
23579
23381
  /**
23580
23382
  * While the gesture animation is finishing
@@ -23667,8 +23469,6 @@ class Modal {
23667
23469
  }
23668
23470
  this.currentBreakpoint = undefined;
23669
23471
  this.animation = undefined;
23670
- // Reset safe-area state for potential re-presentation
23671
- this.resetSafeAreaState();
23672
23472
  unlock();
23673
23473
  return dismissed;
23674
23474
  }
@@ -23918,20 +23718,20 @@ class Modal {
23918
23718
  const isCardModal = presentingElement !== undefined && mode === 'ios';
23919
23719
  const isHandleCycle = handleBehavior === 'cycle';
23920
23720
  const isSheetModalWithHandle = isSheetModal && showHandle;
23921
- return (hAsync(Host, Object.assign({ key: '44022099fcaf047b97d1c2cb45b9b51c930e707c', "no-router": true,
23721
+ return (hAsync(Host, Object.assign({ key: '87328006ea6c75ebc518ace300438492a567223e', "no-router": true,
23922
23722
  // Allow the modal to be navigable when the handle is focusable
23923
23723
  tabIndex: isHandleCycle && isSheetModalWithHandle ? 0 : -1 }, htmlAttributes, { style: {
23924
23724
  zIndex: `${20000 + this.overlayIndex}`,
23925
- }, class: Object.assign({ [mode]: true, ['modal-default']: !isCardModal && !isSheetModal, [`modal-card`]: isCardModal, [`modal-sheet`]: isSheetModal, [`modal-no-expand-scroll`]: isSheetModal && !expandToScroll, 'overlay-hidden': true, [FOCUS_TRAP_DISABLE_CLASS]: focusTrap === false }, getClassMap(this.cssClass)), onIonBackdropTap: this.onBackdropTap, onIonModalDidPresent: this.onLifecycle, onIonModalWillPresent: this.onLifecycle, onIonModalWillDismiss: this.onLifecycle, onIonModalDidDismiss: this.onLifecycle, onFocus: this.onModalFocus }), hAsync("ion-backdrop", { key: 'ddd7e4f6eef51ac1f62ac70e0af10fb01e707f07', ref: (el) => (this.backdropEl = el), visible: this.showBackdrop, tappable: this.backdropDismiss, part: "backdrop" }), mode === 'ios' && hAsync("div", { key: '58620980e3e4ec273c6787bde026e1c010b904b7', class: "modal-shadow" }), hAsync("div", Object.assign({ key: '3fb7f6218644ba898fc504467775593eb89426a0',
23725
+ }, class: Object.assign({ [mode]: true, ['modal-default']: !isCardModal && !isSheetModal, [`modal-card`]: isCardModal, [`modal-sheet`]: isSheetModal, [`modal-no-expand-scroll`]: isSheetModal && !expandToScroll, 'overlay-hidden': true, [FOCUS_TRAP_DISABLE_CLASS]: focusTrap === false }, getClassMap(this.cssClass)), onIonBackdropTap: this.onBackdropTap, onIonModalDidPresent: this.onLifecycle, onIonModalWillPresent: this.onLifecycle, onIonModalWillDismiss: this.onLifecycle, onIonModalDidDismiss: this.onLifecycle, onFocus: this.onModalFocus }), hAsync("ion-backdrop", { key: 'ee94ff8e09b691dd4ad4e4db1720f06bc3c5a469', ref: (el) => (this.backdropEl = el), visible: this.showBackdrop, tappable: this.backdropDismiss, part: "backdrop" }), mode === 'ios' && hAsync("div", { key: 'bffd69b4635c22d9f249725bd952c1e93d5615c7', class: "modal-shadow" }), hAsync("div", Object.assign({ key: '1d394d3c68916e464ff1fbf5242419f4a3d3cca1',
23926
23726
  /*
23927
23727
  role and aria-modal must be used on the
23928
23728
  same element. They must also be set inside the
23929
23729
  shadow DOM otherwise ion-button will not be highlighted
23930
23730
  when using VoiceOver: https://bugs.webkit.org/show_bug.cgi?id=247134
23931
23731
  */
23932
- role: "dialog" }, inheritedAttributes, { "aria-modal": "true", class: "modal-wrapper ion-overlay-wrapper", part: "content", ref: (el) => (this.wrapperEl = el) }), showHandle && (hAsync("button", { key: '9745cd590fdaa9d023a14b487ec2c87ddbafd7f7', class: "modal-handle",
23732
+ role: "dialog" }, inheritedAttributes, { "aria-modal": "true", class: "modal-wrapper ion-overlay-wrapper", part: "content", ref: (el) => (this.wrapperEl = el) }), showHandle && (hAsync("button", { key: '2dcf58792018e557e0c323baad2d672bc99c0bb1', class: "modal-handle",
23933
23733
  // Prevents the handle from receiving keyboard focus when it does not cycle
23934
- tabIndex: !isHandleCycle ? -1 : 0, "aria-label": "Activate to adjust the size of the dialog overlaying the screen", onClick: isHandleCycle ? this.onHandleClick : undefined, part: "handle", ref: (el) => (this.dragHandleEl = el) })), hAsync("slot", { key: 'b9a8b5d2d3d3c9b06f99179f496c9f08907d0bad', onSlotchange: this.onSlotChange }))));
23734
+ tabIndex: !isHandleCycle ? -1 : 0, "aria-label": "Activate to adjust the size of the dialog overlaying the screen", onClick: isHandleCycle ? this.onHandleClick : undefined, part: "handle", ref: (el) => (this.dragHandleEl = el) })), hAsync("slot", { key: '44164b1e8710c3895400ad9f44ecd99873874ad5', onSlotchange: this.onSlotChange }))));
23935
23735
  }
23936
23736
  get el() { return getElement(this); }
23937
23737
  static get watchers() { return {
@@ -27509,8 +27309,6 @@ const calculateWindowAdjustment = (side, coordTop, coordLeft, bodyPadding, bodyW
27509
27309
  let bottom;
27510
27310
  let originX = contentOriginX;
27511
27311
  let originY = contentOriginY;
27512
- let checkSafeAreaTop = false;
27513
- let checkSafeAreaBottom = false;
27514
27312
  let checkSafeAreaLeft = false;
27515
27313
  let checkSafeAreaRight = false;
27516
27314
  const triggerTop = triggerCoordinates
@@ -27555,18 +27353,10 @@ const calculateWindowAdjustment = (side, coordTop, coordLeft, bodyPadding, bodyW
27555
27353
  * We chose 12 here so that the popover position looks a bit nicer as
27556
27354
  * it is not right up against the edge of the screen.
27557
27355
  */
27558
- top = Math.max(bodyPadding, triggerTop - contentHeight - triggerHeight - (arrowHeight - 1));
27356
+ top = Math.max(12, triggerTop - contentHeight - triggerHeight - (arrowHeight - 1));
27559
27357
  arrowTop = top + contentHeight;
27560
27358
  originY = 'bottom';
27561
27359
  addPopoverBottomClass = true;
27562
- /**
27563
- * If the popover is positioned near the top edge, account for safe area.
27564
- * This ensures the popover doesn't overlap with status bars or notches.
27565
- */
27566
- if (top <= bodyPadding + safeAreaMargin) {
27567
- checkSafeAreaTop = true;
27568
- top = bodyPadding;
27569
- }
27570
27360
  /**
27571
27361
  * If not enough room for popover to appear
27572
27362
  * above trigger, then cut it off.
@@ -27574,35 +27364,14 @@ const calculateWindowAdjustment = (side, coordTop, coordLeft, bodyPadding, bodyW
27574
27364
  }
27575
27365
  else {
27576
27366
  bottom = bodyPadding;
27577
- /**
27578
- * When the popover is pinned to the bottom, account for safe area.
27579
- * This ensures the popover doesn't overlap with home indicators
27580
- * or navigation bars (e.g., Android API 36+ edge-to-edge).
27581
- */
27582
- checkSafeAreaBottom = true;
27583
27367
  }
27584
27368
  }
27585
- /**
27586
- * Final check: If the popover extends into any safe-area region,
27587
- * ensure the corresponding flag is set regardless of side.
27588
- * This handles cases where a side-positioned popover (left/right)
27589
- * still needs bottom safe-area padding because it extends into that region.
27590
- */
27591
- const popoverBottom = bottom !== undefined ? bodyHeight - bottom : top + contentHeight;
27592
- if (popoverBottom + safeAreaMargin > bodyHeight) {
27593
- checkSafeAreaBottom = true;
27594
- }
27595
- if (top < safeAreaMargin) {
27596
- checkSafeAreaTop = true;
27597
- }
27598
27369
  return {
27599
27370
  top,
27600
27371
  left,
27601
27372
  bottom,
27602
27373
  originX,
27603
27374
  originY,
27604
- checkSafeAreaTop,
27605
- checkSafeAreaBottom,
27606
27375
  checkSafeAreaLeft,
27607
27376
  checkSafeAreaRight,
27608
27377
  arrowTop,
@@ -27663,7 +27432,7 @@ const iosEnterAnimation$1 = (baseEl, opts) => {
27663
27432
  const results = getPopoverPosition(isRTL, contentWidth, contentHeight, arrowWidth, arrowHeight, reference, side, align, defaultPosition, trigger, ev);
27664
27433
  const padding = size === 'cover' ? 0 : POPOVER_IOS_BODY_PADDING;
27665
27434
  const margin = size === 'cover' ? 0 : 25;
27666
- const { originX, originY, top, left, bottom, checkSafeAreaTop, checkSafeAreaBottom, checkSafeAreaLeft, checkSafeAreaRight, arrowTop, arrowLeft, addPopoverBottomClass, } = calculateWindowAdjustment(side, results.top, results.left, padding, bodyWidth, bodyHeight, contentWidth, contentHeight, margin, results.originX, results.originY, results.referenceCoordinates, results.arrowTop, results.arrowLeft, arrowHeight);
27435
+ const { originX, originY, top, left, bottom, checkSafeAreaLeft, checkSafeAreaRight, arrowTop, arrowLeft, addPopoverBottomClass, } = calculateWindowAdjustment(side, results.top, results.left, padding, bodyWidth, bodyHeight, contentWidth, contentHeight, margin, results.originX, results.originY, results.referenceCoordinates, results.arrowTop, results.arrowLeft, arrowHeight);
27667
27436
  const baseAnimation = createAnimation();
27668
27437
  const backdropAnimation = createAnimation();
27669
27438
  const contentAnimation = createAnimation();
@@ -27693,35 +27462,19 @@ const iosEnterAnimation$1 = (baseEl, opts) => {
27693
27462
  if (addPopoverBottomClass) {
27694
27463
  baseEl.classList.add('popover-bottom');
27695
27464
  }
27696
- /**
27697
- * Safe area CSS variable adjustments.
27698
- * When the popover is positioned near an edge, we add the corresponding
27699
- * safe-area inset to ensure the popover doesn't overlap with system UI
27700
- * (status bars, home indicators, navigation bars on Android API 36+, etc.)
27701
- */
27702
- const safeAreaTop = ' + var(--ion-safe-area-top, 0)';
27703
- const safeAreaBottom = ' + var(--ion-safe-area-bottom, 0)';
27465
+ if (bottom !== undefined) {
27466
+ contentEl.style.setProperty('bottom', `${bottom}px`);
27467
+ }
27704
27468
  const safeAreaLeft = ' + var(--ion-safe-area-left, 0)';
27705
27469
  const safeAreaRight = ' - var(--ion-safe-area-right, 0)';
27706
- let topValue = `${top}px`;
27707
- let bottomValue = bottom !== undefined ? `${bottom}px` : undefined;
27708
27470
  let leftValue = `${left}px`;
27709
- if (checkSafeAreaTop) {
27710
- topValue = `${top}px${safeAreaTop}`;
27711
- }
27712
- if (checkSafeAreaBottom && bottomValue !== undefined) {
27713
- bottomValue = `${bottom}px${safeAreaBottom}`;
27714
- }
27715
27471
  if (checkSafeAreaLeft) {
27716
27472
  leftValue = `${left}px${safeAreaLeft}`;
27717
27473
  }
27718
27474
  if (checkSafeAreaRight) {
27719
27475
  leftValue = `${left}px${safeAreaRight}`;
27720
27476
  }
27721
- if (bottomValue !== undefined) {
27722
- contentEl.style.setProperty('bottom', `calc(${bottomValue})`);
27723
- }
27724
- contentEl.style.setProperty('top', `calc(${topValue} + var(--offset-y, 0))`);
27477
+ contentEl.style.setProperty('top', `calc(${top}px + var(--offset-y, 0))`);
27725
27478
  contentEl.style.setProperty('left', `calc(${leftValue} + var(--offset-x, 0))`);
27726
27479
  contentEl.style.setProperty('transform-origin', `${originY} ${originX}`);
27727
27480
  if (arrowEl !== null) {
@@ -27797,32 +27550,7 @@ const mdEnterAnimation$1 = (baseEl, opts) => {
27797
27550
  };
27798
27551
  const results = getPopoverPosition(isRTL, contentWidth, contentHeight, 0, 0, reference, side, align, defaultPosition, trigger, ev);
27799
27552
  const padding = size === 'cover' ? 0 : POPOVER_MD_BODY_PADDING;
27800
- const { originX, originY, top, left, bottom, checkSafeAreaTop, checkSafeAreaBottom, checkSafeAreaLeft, checkSafeAreaRight, } = calculateWindowAdjustment(side, results.top, results.left, padding, bodyWidth, bodyHeight, contentWidth, contentHeight, 0, results.originX, results.originY, results.referenceCoordinates);
27801
- /**
27802
- * Safe area CSS variable adjustments.
27803
- * When the popover is positioned near an edge, we add the corresponding
27804
- * safe-area inset to ensure the popover doesn't overlap with system UI
27805
- * (status bars, home indicators, navigation bars on Android API 36+, etc.)
27806
- */
27807
- const safeAreaTop = ' + var(--ion-safe-area-top, 0)';
27808
- const safeAreaBottom = ' + var(--ion-safe-area-bottom, 0)';
27809
- const safeAreaLeft = ' + var(--ion-safe-area-left, 0)';
27810
- const safeAreaRight = ' - var(--ion-safe-area-right, 0)';
27811
- let topValue = `${top}px`;
27812
- let bottomValue = bottom !== undefined ? `${bottom}px` : undefined;
27813
- let leftValue = `${left}px`;
27814
- if (checkSafeAreaTop) {
27815
- topValue = `${top}px${safeAreaTop}`;
27816
- }
27817
- if (checkSafeAreaBottom && bottomValue !== undefined) {
27818
- bottomValue = `${bottom}px${safeAreaBottom}`;
27819
- }
27820
- if (checkSafeAreaLeft) {
27821
- leftValue = `${left}px${safeAreaLeft}`;
27822
- }
27823
- if (checkSafeAreaRight) {
27824
- leftValue = `${left}px${safeAreaRight}`;
27825
- }
27553
+ const { originX, originY, top, left, bottom } = calculateWindowAdjustment(side, results.top, results.left, padding, bodyWidth, bodyHeight, contentWidth, contentHeight, 0, results.originX, results.originY, results.referenceCoordinates);
27826
27554
  const baseAnimation = createAnimation();
27827
27555
  const backdropAnimation = createAnimation();
27828
27556
  const wrapperAnimation = createAnimation();
@@ -27839,13 +27567,13 @@ const mdEnterAnimation$1 = (baseEl, opts) => {
27839
27567
  contentAnimation
27840
27568
  .addElement(contentEl)
27841
27569
  .beforeStyles({
27842
- top: `calc(${topValue} + var(--offset-y, 0px))`,
27843
- left: `calc(${leftValue} + var(--offset-x, 0px))`,
27570
+ top: `calc(${top}px + var(--offset-y, 0px))`,
27571
+ left: `calc(${left}px + var(--offset-x, 0px))`,
27844
27572
  'transform-origin': `${originY} ${originX}`,
27845
27573
  })
27846
27574
  .beforeAddWrite(() => {
27847
- if (bottomValue !== undefined) {
27848
- contentEl.style.setProperty('bottom', `calc(${bottomValue})`);
27575
+ if (bottom !== undefined) {
27576
+ contentEl.style.setProperty('bottom', `${bottom}px`);
27849
27577
  }
27850
27578
  })
27851
27579
  .fromTo('transform', 'scale(0.8)', 'scale(1)');
@@ -29642,7 +29370,7 @@ class Range {
29642
29370
  })));
29643
29371
  }
29644
29372
  render() {
29645
- const { disabled, el, hasLabel, rangeId, pin, pressedKnob, labelPlacement, label } = this;
29373
+ const { disabled, el, hasLabel, rangeId, pin, pressedKnob, labelPlacement, label, dualKnobs, min, max } = this;
29646
29374
  const inItem = hostContext('ion-item', el);
29647
29375
  /**
29648
29376
  * If there is no start content then the knob at
@@ -29657,8 +29385,14 @@ class Range {
29657
29385
  const hasEndContent = (hasLabel && labelPlacement === 'end') || this.hasEndSlotContent;
29658
29386
  const needsEndAdjustment = inItem && !hasEndContent;
29659
29387
  const mode = getIonMode$1(this);
29388
+ /**
29389
+ * Determine if any knob is at the min or max value to
29390
+ * apply Host classes for styling.
29391
+ */
29392
+ const valueAtMin = dualKnobs ? this.valA === min || this.valB === min : this.valA === min;
29393
+ const valueAtMax = dualKnobs ? this.valA === max || this.valB === max : this.valA === max;
29660
29394
  renderHiddenInput(true, el, this.name, JSON.stringify(this.getValue()), disabled);
29661
- return (hAsync(Host, { key: 'ef7b01f80515bcaeb2983934ad7f10a6bd5d13ec', onFocusin: this.onFocus, onFocusout: this.onBlur, id: rangeId, class: createColorClasses$1(this.color, {
29395
+ return (hAsync(Host, { key: 'ed646a42d51b8fe22012198c354cbcf5a389c108', onFocusin: this.onFocus, onFocusout: this.onBlur, id: rangeId, class: createColorClasses$1(this.color, {
29662
29396
  [mode]: true,
29663
29397
  'in-item': inItem,
29664
29398
  'range-disabled': disabled,
@@ -29667,10 +29401,12 @@ class Range {
29667
29401
  [`range-label-placement-${labelPlacement}`]: true,
29668
29402
  'range-item-start-adjustment': needsStartAdjustment,
29669
29403
  'range-item-end-adjustment': needsEndAdjustment,
29670
- }) }, hAsync("label", { key: 'fd8aa90a9d52be9da024b907e68858dae424449d', class: "range-wrapper", id: "range-label" }, hAsync("div", { key: '2172b4f329c22017dd23475c80aac25ba6e753eb', class: {
29404
+ 'range-value-min': valueAtMin,
29405
+ 'range-value-max': valueAtMax,
29406
+ }) }, hAsync("label", { key: '3083e4f2a624e3b268396acb4415f7c6ac44d851', class: "range-wrapper", id: "range-label" }, hAsync("div", { key: '47b92f94d2a0381dd7c5cd3dda54ed2942096715', class: {
29671
29407
  'label-text-wrapper': true,
29672
29408
  'label-text-wrapper-hidden': !hasLabel,
29673
- }, part: "label" }, label !== undefined ? hAsync("div", { class: "label-text" }, label) : hAsync("slot", { name: "label" })), hAsync("div", { key: '3c318bf2ea0576646d4c010bf44573fd0f483186', class: "native-wrapper" }, hAsync("slot", { key: '6586fd6fc96271e73f8a86c202d1913ad1a26f96', name: "start" }), this.renderRangeSlider(), hAsync("slot", { key: '74ac0bc2d2cb66ef708bb729f88b6ecbc1b2155d', name: "end" })))));
29409
+ }, part: "label" }, label !== undefined ? hAsync("div", { class: "label-text" }, label) : hAsync("slot", { name: "label" })), hAsync("div", { key: '5341da8d19eb29091df680978a0e20cc8f2eec65', class: "native-wrapper" }, hAsync("slot", { key: '09f1437078032676695442d8c827a16faa7dffe2', name: "start" }), this.renderRangeSlider(), hAsync("slot", { key: '02b7781970ea4d44f10b5f4627a2ca36eca45f85', name: "end" })))));
29674
29410
  }
29675
29411
  get el() { return getElement(this); }
29676
29412
  static get watchers() { return {