@ionic/core 8.7.16-dev.11767019759.14b7f2fa → 8.7.16-dev.11767032989.1ae720d0
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-input.js +35 -6
- package/components/modal.js +11 -92
- package/dist/cjs/ion-input.cjs.entry.js +35 -6
- package/dist/cjs/ion-modal.cjs.entry.js +11 -92
- package/dist/collection/components/input/input.js +35 -6
- package/dist/collection/components/modal/gestures/sheet.js +1 -3
- package/dist/collection/components/modal/gestures/swipe-to-close.js +1 -3
- package/dist/collection/components/modal/modal.ios.css +4 -0
- package/dist/collection/components/modal/modal.js +7 -84
- package/dist/collection/components/modal/modal.md.css +4 -0
- package/dist/docs.json +1 -1
- package/dist/esm/ion-input.entry.js +35 -6
- package/dist/esm/ion-modal.entry.js +11 -92
- package/dist/ionic/ionic.esm.js +1 -1
- package/dist/ionic/p-b28af559.entry.js +4 -0
- package/dist/ionic/p-bf1578e9.entry.js +4 -0
- package/dist/types/components/input/input.d.ts +11 -0
- package/dist/types/components/modal/gestures/sheet.d.ts +1 -1
- package/dist/types/components/modal/gestures/swipe-to-close.d.ts +1 -1
- package/dist/types/components/modal/modal.d.ts +0 -12
- package/hydrate/index.js +45 -98
- package/hydrate/index.mjs +45 -98
- package/package.json +1 -1
- package/dist/ionic/p-40c261a3.entry.js +0 -4
- package/dist/ionic/p-88b087a9.entry.js +0 -4
|
@@ -249,7 +249,7 @@ const calculateSpringStep = (t) => {
|
|
|
249
249
|
const SwipeToCloseDefaults = {
|
|
250
250
|
MIN_PRESENTING_SCALE: 0.915,
|
|
251
251
|
};
|
|
252
|
-
const createSwipeToCloseGesture = (el, animation, statusBarStyle, onDismiss
|
|
252
|
+
const createSwipeToCloseGesture = (el, animation, statusBarStyle, onDismiss) => {
|
|
253
253
|
/**
|
|
254
254
|
* The step value at which a card modal
|
|
255
255
|
* is eligible for dismissing via gesture.
|
|
@@ -406,8 +406,6 @@ const createSwipeToCloseGesture = (el, animation, statusBarStyle, onDismiss, onG
|
|
|
406
406
|
const processedStep = isAttemptingDismissWithCanDismiss ? calculateSpringStep(step / maxStep) : step;
|
|
407
407
|
const clampedStep = helpers.clamp(0.0001, processedStep, maxStep);
|
|
408
408
|
animation.progressStep(clampedStep);
|
|
409
|
-
// Notify modal of position change for safe-area updates
|
|
410
|
-
onGestureMove === null || onGestureMove === void 0 ? void 0 : onGestureMove();
|
|
411
409
|
/**
|
|
412
410
|
* When swiping down half way, the status bar style
|
|
413
411
|
* should be reset to its default value.
|
|
@@ -951,7 +949,7 @@ const mdLeaveAnimation = (baseEl, opts) => {
|
|
|
951
949
|
return baseAnimation;
|
|
952
950
|
};
|
|
953
951
|
|
|
954
|
-
const createSheetGesture = (baseEl, backdropEl, wrapperEl, initialBreakpoint, backdropBreakpoint, animation, breakpoints = [], expandToScroll, getCurrentBreakpoint, onDismiss, onBreakpointChange
|
|
952
|
+
const createSheetGesture = (baseEl, backdropEl, wrapperEl, initialBreakpoint, backdropBreakpoint, animation, breakpoints = [], expandToScroll, getCurrentBreakpoint, onDismiss, onBreakpointChange) => {
|
|
955
953
|
// Defaults for the sheet swipe animation
|
|
956
954
|
const defaultBackdrop = [
|
|
957
955
|
{ offset: 0, opacity: 'var(--backdrop-opacity)' },
|
|
@@ -1282,8 +1280,6 @@ const createSheetGesture = (baseEl, backdropEl, wrapperEl, initialBreakpoint, ba
|
|
|
1282
1280
|
: step;
|
|
1283
1281
|
offset = helpers.clamp(0.0001, processedStep, maxStep);
|
|
1284
1282
|
animation.progressStep(offset);
|
|
1285
|
-
// Notify modal of position change for safe-area updates
|
|
1286
|
-
onGestureMove === null || onGestureMove === void 0 ? void 0 : onGestureMove();
|
|
1287
1283
|
};
|
|
1288
1284
|
const onEnd = (detail) => {
|
|
1289
1285
|
/**
|
|
@@ -1478,9 +1474,9 @@ const createSheetGesture = (baseEl, backdropEl, wrapperEl, initialBreakpoint, ba
|
|
|
1478
1474
|
};
|
|
1479
1475
|
};
|
|
1480
1476
|
|
|
1481
|
-
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}";
|
|
1477
|
+
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}";
|
|
1482
1478
|
|
|
1483
|
-
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}";
|
|
1479
|
+
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}";
|
|
1484
1480
|
|
|
1485
1481
|
const Modal = class {
|
|
1486
1482
|
constructor(hostRef) {
|
|
@@ -1693,9 +1689,7 @@ const Modal = class {
|
|
|
1693
1689
|
}
|
|
1694
1690
|
}
|
|
1695
1691
|
onWindowResize() {
|
|
1696
|
-
//
|
|
1697
|
-
this.updateSafeAreaOverrides();
|
|
1698
|
-
// Only handle view transition for iOS card modals when no custom animations are provided
|
|
1692
|
+
// Only handle resize for iOS card modals when no custom animations are provided
|
|
1699
1693
|
if (ionicGlobal.getIonMode(this) !== 'ios' || !this.presentingElement || this.enterAnimation || this.leaveAnimation) {
|
|
1700
1694
|
return;
|
|
1701
1695
|
}
|
|
@@ -1877,8 +1871,6 @@ const Modal = class {
|
|
|
1877
1871
|
else if (!this.keepContentsMounted) {
|
|
1878
1872
|
await index$4.waitForMount();
|
|
1879
1873
|
}
|
|
1880
|
-
// Predict safe-area needs based on modal configuration to avoid visual snap
|
|
1881
|
-
this.setInitialSafeAreaOverrides(presentingElement);
|
|
1882
1874
|
index$3.writeTask(() => this.el.classList.add('show-modal'));
|
|
1883
1875
|
const hasCardModal = presentingElement !== undefined;
|
|
1884
1876
|
/**
|
|
@@ -1940,8 +1932,6 @@ const Modal = class {
|
|
|
1940
1932
|
else if (hasCardModal) {
|
|
1941
1933
|
this.initSwipeToClose();
|
|
1942
1934
|
}
|
|
1943
|
-
// Now that animation is complete, update safe-area based on actual position
|
|
1944
|
-
this.updateSafeAreaOverrides();
|
|
1945
1935
|
// Initialize view transition listener for iOS card modals
|
|
1946
1936
|
this.initViewTransitionListener();
|
|
1947
1937
|
// Initialize parent removal observer
|
|
@@ -1993,7 +1983,7 @@ const Modal = class {
|
|
|
1993
1983
|
await this.dismiss(undefined, overlays.GESTURE);
|
|
1994
1984
|
this.gestureAnimationDismissing = false;
|
|
1995
1985
|
});
|
|
1996
|
-
}
|
|
1986
|
+
});
|
|
1997
1987
|
this.gesture.enable(true);
|
|
1998
1988
|
}
|
|
1999
1989
|
initSheetGesture() {
|
|
@@ -2014,8 +2004,7 @@ const Modal = class {
|
|
|
2014
2004
|
this.currentBreakpoint = breakpoint;
|
|
2015
2005
|
this.ionBreakpointDidChange.emit({ breakpoint });
|
|
2016
2006
|
}
|
|
2017
|
-
|
|
2018
|
-
}, () => this.updateSafeAreaOverrides());
|
|
2007
|
+
});
|
|
2019
2008
|
this.gesture = gesture;
|
|
2020
2009
|
this.moveSheetToBreakpoint = moveSheetToBreakpoint;
|
|
2021
2010
|
this.gesture.enable(true);
|
|
@@ -2093,76 +2082,6 @@ const Modal = class {
|
|
|
2093
2082
|
// Clear the cached reference
|
|
2094
2083
|
this.cachedPageParent = undefined;
|
|
2095
2084
|
}
|
|
2096
|
-
/**
|
|
2097
|
-
* Sets initial safe-area overrides based on modal configuration before
|
|
2098
|
-
* the modal becomes visible. This predicts whether the modal will touch
|
|
2099
|
-
* screen edges to avoid a visual snap after animation completes.
|
|
2100
|
-
*/
|
|
2101
|
-
setInitialSafeAreaOverrides(presentingElement) {
|
|
2102
|
-
const style = this.el.style;
|
|
2103
|
-
const isSheetModal = this.breakpoints !== undefined && this.initialBreakpoint !== undefined;
|
|
2104
|
-
const isCardModal = presentingElement !== undefined;
|
|
2105
|
-
const isTablet = window.innerWidth >= 768;
|
|
2106
|
-
// Sheet modals: always touch bottom, top depends on breakpoint
|
|
2107
|
-
if (isSheetModal) {
|
|
2108
|
-
style.setProperty('--ion-safe-area-top', '0px');
|
|
2109
|
-
// Don't override bottom - sheet always touches bottom
|
|
2110
|
-
style.setProperty('--ion-safe-area-left', '0px');
|
|
2111
|
-
style.setProperty('--ion-safe-area-right', '0px');
|
|
2112
|
-
return;
|
|
2113
|
-
}
|
|
2114
|
-
// Card modals are inset from edges (rounded corners), no safe areas needed
|
|
2115
|
-
if (isCardModal) {
|
|
2116
|
-
style.setProperty('--ion-safe-area-top', '0px');
|
|
2117
|
-
style.setProperty('--ion-safe-area-bottom', '0px');
|
|
2118
|
-
style.setProperty('--ion-safe-area-left', '0px');
|
|
2119
|
-
style.setProperty('--ion-safe-area-right', '0px');
|
|
2120
|
-
return;
|
|
2121
|
-
}
|
|
2122
|
-
// Phone modals are fullscreen, need all safe areas
|
|
2123
|
-
if (!isTablet) {
|
|
2124
|
-
// Don't set any overrides - inherit from :root
|
|
2125
|
-
return;
|
|
2126
|
-
}
|
|
2127
|
-
// Default tablet modal: centered dialog, no safe areas needed
|
|
2128
|
-
// Check for fullscreen override via CSS custom properties
|
|
2129
|
-
const computedStyle = getComputedStyle(this.el);
|
|
2130
|
-
const width = computedStyle.getPropertyValue('--width').trim();
|
|
2131
|
-
const height = computedStyle.getPropertyValue('--height').trim();
|
|
2132
|
-
if (width === '100%' && height === '100%') {
|
|
2133
|
-
// Fullscreen modal - need safe areas, don't override
|
|
2134
|
-
return;
|
|
2135
|
-
}
|
|
2136
|
-
// Centered dialog - zero out all safe areas
|
|
2137
|
-
style.setProperty('--ion-safe-area-top', '0px');
|
|
2138
|
-
style.setProperty('--ion-safe-area-bottom', '0px');
|
|
2139
|
-
style.setProperty('--ion-safe-area-left', '0px');
|
|
2140
|
-
style.setProperty('--ion-safe-area-right', '0px');
|
|
2141
|
-
}
|
|
2142
|
-
/**
|
|
2143
|
-
* Updates safe-area CSS variable overrides based on whether the modal
|
|
2144
|
-
* is touching each edge of the viewport. This is called after animation
|
|
2145
|
-
* and during gestures to handle dynamic position changes.
|
|
2146
|
-
*/
|
|
2147
|
-
updateSafeAreaOverrides() {
|
|
2148
|
-
const wrapper = this.wrapperEl;
|
|
2149
|
-
if (!wrapper)
|
|
2150
|
-
return;
|
|
2151
|
-
const rect = wrapper.getBoundingClientRect();
|
|
2152
|
-
const threshold = 2; // Account for subpixel rendering
|
|
2153
|
-
const touchingTop = rect.top <= threshold;
|
|
2154
|
-
const touchingBottom = rect.bottom >= window.innerHeight - threshold;
|
|
2155
|
-
const touchingLeft = rect.left <= threshold;
|
|
2156
|
-
const touchingRight = rect.right >= window.innerWidth - threshold;
|
|
2157
|
-
// Remove override when touching edge (allow inheritance), set to 0 when not touching
|
|
2158
|
-
const style = this.el.style;
|
|
2159
|
-
touchingTop ? style.removeProperty('--ion-safe-area-top') : style.setProperty('--ion-safe-area-top', '0px');
|
|
2160
|
-
touchingBottom
|
|
2161
|
-
? style.removeProperty('--ion-safe-area-bottom')
|
|
2162
|
-
: style.setProperty('--ion-safe-area-bottom', '0px');
|
|
2163
|
-
touchingLeft ? style.removeProperty('--ion-safe-area-left') : style.setProperty('--ion-safe-area-left', '0px');
|
|
2164
|
-
touchingRight ? style.removeProperty('--ion-safe-area-right') : style.setProperty('--ion-safe-area-right', '0px');
|
|
2165
|
-
}
|
|
2166
2085
|
sheetOnDismiss() {
|
|
2167
2086
|
/**
|
|
2168
2087
|
* While the gesture animation is finishing
|
|
@@ -2500,20 +2419,20 @@ const Modal = class {
|
|
|
2500
2419
|
const isCardModal = presentingElement !== undefined && mode === 'ios';
|
|
2501
2420
|
const isHandleCycle = handleBehavior === 'cycle';
|
|
2502
2421
|
const isSheetModalWithHandle = isSheetModal && showHandle;
|
|
2503
|
-
return (index$3.h(index$3.Host, Object.assign({ key: '
|
|
2422
|
+
return (index$3.h(index$3.Host, Object.assign({ key: '9a75095a13de0cfc96f1fa69fd92777d25da8daa', "no-router": true,
|
|
2504
2423
|
// Allow the modal to be navigable when the handle is focusable
|
|
2505
2424
|
tabIndex: isHandleCycle && isSheetModalWithHandle ? 0 : -1 }, htmlAttributes, { style: {
|
|
2506
2425
|
zIndex: `${20000 + this.overlayIndex}`,
|
|
2507
|
-
}, class: Object.assign({ [mode]: true, ['modal-default']: !isCardModal && !isSheetModal, [`modal-card`]: isCardModal, [`modal-sheet`]: isSheetModal, [`modal-no-expand-scroll`]: isSheetModal && !expandToScroll, 'overlay-hidden': true, [overlays.FOCUS_TRAP_DISABLE_CLASS]: focusTrap === false }, theme.getClassMap(this.cssClass)), onIonBackdropTap: this.onBackdropTap, onIonModalDidPresent: this.onLifecycle, onIonModalWillPresent: this.onLifecycle, onIonModalWillDismiss: this.onLifecycle, onIonModalDidDismiss: this.onLifecycle, onFocus: this.onModalFocus }), index$3.h("ion-backdrop", { key: '
|
|
2426
|
+
}, class: Object.assign({ [mode]: true, ['modal-default']: !isCardModal && !isSheetModal, [`modal-card`]: isCardModal, [`modal-sheet`]: isSheetModal, [`modal-no-expand-scroll`]: isSheetModal && !expandToScroll, 'overlay-hidden': true, [overlays.FOCUS_TRAP_DISABLE_CLASS]: focusTrap === false }, theme.getClassMap(this.cssClass)), onIonBackdropTap: this.onBackdropTap, onIonModalDidPresent: this.onLifecycle, onIonModalWillPresent: this.onLifecycle, onIonModalWillDismiss: this.onLifecycle, onIonModalDidDismiss: this.onLifecycle, onFocus: this.onModalFocus }), index$3.h("ion-backdrop", { key: 'd02612d8063ef20f59f173ff47795f71cdaaf63e', ref: (el) => (this.backdropEl = el), visible: this.showBackdrop, tappable: this.backdropDismiss, part: "backdrop" }), mode === 'ios' && index$3.h("div", { key: '708761b70a93e34c08faae079569f444c7416a4c', class: "modal-shadow" }), index$3.h("div", Object.assign({ key: 'a72226ff1a98229f9bfd9207b98fc57e02baa430',
|
|
2508
2427
|
/*
|
|
2509
2428
|
role and aria-modal must be used on the
|
|
2510
2429
|
same element. They must also be set inside the
|
|
2511
2430
|
shadow DOM otherwise ion-button will not be highlighted
|
|
2512
2431
|
when using VoiceOver: https://bugs.webkit.org/show_bug.cgi?id=247134
|
|
2513
2432
|
*/
|
|
2514
|
-
role: "dialog" }, inheritedAttributes, { "aria-modal": "true", class: "modal-wrapper ion-overlay-wrapper", part: "content", ref: (el) => (this.wrapperEl = el) }), showHandle && (index$3.h("button", { key: '
|
|
2433
|
+
role: "dialog" }, inheritedAttributes, { "aria-modal": "true", class: "modal-wrapper ion-overlay-wrapper", part: "content", ref: (el) => (this.wrapperEl = el) }), showHandle && (index$3.h("button", { key: '0547f32323882660221385d84d492929caa77c6b', class: "modal-handle",
|
|
2515
2434
|
// Prevents the handle from receiving keyboard focus when it does not cycle
|
|
2516
|
-
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) })), index$3.h("slot", { key: '
|
|
2435
|
+
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) })), index$3.h("slot", { key: 'fccbd64518b6fa22f9e874deb6b4ba55d8d89c3b', onSlotchange: this.onSlotChange }))));
|
|
2517
2436
|
}
|
|
2518
2437
|
get el() { return index$3.getElement(this); }
|
|
2519
2438
|
static get watchers() { return {
|
|
@@ -21,6 +21,7 @@ export class Input {
|
|
|
21
21
|
this.inputId = `ion-input-${inputIds++}`;
|
|
22
22
|
this.helperTextId = `${this.inputId}-helper-text`;
|
|
23
23
|
this.errorTextId = `${this.inputId}-error-text`;
|
|
24
|
+
this.labelTextId = `${this.inputId}-label`;
|
|
24
25
|
this.inheritedAttributes = {};
|
|
25
26
|
this.isComposing = false;
|
|
26
27
|
/**
|
|
@@ -229,7 +230,11 @@ export class Input {
|
|
|
229
230
|
}
|
|
230
231
|
connectedCallback() {
|
|
231
232
|
const { el } = this;
|
|
232
|
-
this.slotMutationController = createSlotMutationController(el, ['label', 'start', 'end'], () =>
|
|
233
|
+
this.slotMutationController = createSlotMutationController(el, ['label', 'start', 'end'], () => {
|
|
234
|
+
this.setSlottedLabelId();
|
|
235
|
+
forceUpdate(this);
|
|
236
|
+
});
|
|
237
|
+
this.setSlottedLabelId();
|
|
233
238
|
this.notchController = createNotchController(el, () => this.notchSpacerEl, () => this.labelSlot);
|
|
234
239
|
// Watch for class changes to update validation state
|
|
235
240
|
if (Build.isBrowser && typeof MutationObserver !== 'undefined') {
|
|
@@ -432,11 +437,11 @@ export class Input {
|
|
|
432
437
|
return (h("div", { class: "input-bottom" }, this.renderHintText(), this.renderCounter()));
|
|
433
438
|
}
|
|
434
439
|
renderLabel() {
|
|
435
|
-
const { label } = this;
|
|
440
|
+
const { label, labelTextId } = this;
|
|
436
441
|
return (h("div", { class: {
|
|
437
442
|
'label-text-wrapper': true,
|
|
438
443
|
'label-text-wrapper-hidden': !this.hasLabel,
|
|
439
|
-
} }, label === undefined ? h("slot", { name: "label" }) : h("div", { class: "label-text" }, label)));
|
|
444
|
+
}, "aria-hidden": this.hasLabel ? 'true' : null }, label === undefined ? (h("slot", { name: "label" })) : (h("div", { class: "label-text", id: labelTextId }, label))));
|
|
440
445
|
}
|
|
441
446
|
/**
|
|
442
447
|
* Gets any content passed into the `label` slot,
|
|
@@ -445,6 +450,30 @@ export class Input {
|
|
|
445
450
|
get labelSlot() {
|
|
446
451
|
return this.el.querySelector('[slot="label"]');
|
|
447
452
|
}
|
|
453
|
+
/**
|
|
454
|
+
* Ensures the slotted label element has an ID for aria-labelledby.
|
|
455
|
+
* If no ID exists, we assign one using our generated labelTextId.
|
|
456
|
+
*/
|
|
457
|
+
setSlottedLabelId() {
|
|
458
|
+
const slottedLabel = this.labelSlot;
|
|
459
|
+
if (slottedLabel && !slottedLabel.id) {
|
|
460
|
+
slottedLabel.id = this.labelTextId;
|
|
461
|
+
}
|
|
462
|
+
}
|
|
463
|
+
/**
|
|
464
|
+
* Returns the ID to use for aria-labelledby on the native input,
|
|
465
|
+
* or undefined if aria-label is explicitly set (to avoid conflicts).
|
|
466
|
+
*/
|
|
467
|
+
getLabelledById() {
|
|
468
|
+
var _a;
|
|
469
|
+
if (this.inheritedAttributes['aria-label']) {
|
|
470
|
+
return undefined;
|
|
471
|
+
}
|
|
472
|
+
if (this.label !== undefined) {
|
|
473
|
+
return this.labelTextId;
|
|
474
|
+
}
|
|
475
|
+
return ((_a = this.labelSlot) === null || _a === void 0 ? void 0 : _a.id) || undefined;
|
|
476
|
+
}
|
|
448
477
|
/**
|
|
449
478
|
* Returns `true` if label content is provided
|
|
450
479
|
* either by a prop or a content. If you want
|
|
@@ -511,7 +540,7 @@ export class Input {
|
|
|
511
540
|
* TODO(FW-5592): Remove hasStartEndSlots condition
|
|
512
541
|
*/
|
|
513
542
|
const labelShouldFloat = labelPlacement === 'stacked' || (labelPlacement === 'floating' && (hasValue || hasFocus || hasStartEndSlots));
|
|
514
|
-
return (h(Host, { key: '
|
|
543
|
+
return (h(Host, { key: '9ba9cf425b573d2ca9ac34455a0e6b8474c4de6d', class: createColorClasses(this.color, {
|
|
515
544
|
[mode]: true,
|
|
516
545
|
'has-value': hasValue,
|
|
517
546
|
'has-focus': hasFocus,
|
|
@@ -522,14 +551,14 @@ export class Input {
|
|
|
522
551
|
'in-item': inItem,
|
|
523
552
|
'in-item-color': hostContext('ion-item.ion-color', this.el),
|
|
524
553
|
'input-disabled': disabled,
|
|
525
|
-
}) }, h("label", { key: '
|
|
554
|
+
}) }, h("label", { key: '74b989d0aa5ab38f29f952519868f05119df6005', class: "input-wrapper", htmlFor: inputId, onClick: this.onLabelClick }, this.renderLabelContainer(), h("div", { key: '47f2b42e2f74ea866b4f871026e08ab375d7a726', class: "native-wrapper", onClick: this.onLabelClick }, h("slot", { key: 'eaabe5a4a329a356cac3294d15c087d0d131fff2', name: "start" }), h("input", Object.assign({ key: 'c821a984a8a9b7f96f30892c06d8deda093ff24b', class: "native-input", ref: (input) => (this.nativeInput = input), id: inputId, disabled: disabled, autoCapitalize: this.autocapitalize, autoComplete: this.autocomplete, autoCorrect: this.autocorrect, autoFocus: this.autofocus, enterKeyHint: this.enterkeyhint, inputMode: this.inputmode, min: this.min, max: this.max, minLength: this.minlength, maxLength: this.maxlength, multiple: this.multiple, name: this.name, pattern: this.pattern, placeholder: this.placeholder || '', readOnly: readonly, required: this.required, spellcheck: this.spellcheck, step: this.step, type: this.type, value: value, onInput: this.onInput, onChange: this.onChange, onBlur: this.onBlur, onFocus: this.onFocus, onKeyDown: this.onKeydown, onCompositionstart: this.onCompositionStart, onCompositionend: this.onCompositionEnd, "aria-describedby": this.getHintTextID(), "aria-invalid": this.isInvalid ? 'true' : undefined, "aria-labelledby": this.getLabelledById() }, this.inheritedAttributes)), this.clearInput && !readonly && !disabled && (h("button", { key: '62069c11016ee190dc46ab941372e1c4ad8a36ed', "aria-label": "reset", type: "button", class: "input-clear-icon", onPointerDown: (ev) => {
|
|
526
555
|
/**
|
|
527
556
|
* This prevents mobile browsers from
|
|
528
557
|
* blurring the input when the clear
|
|
529
558
|
* button is activated.
|
|
530
559
|
*/
|
|
531
560
|
ev.preventDefault();
|
|
532
|
-
}, onClick: this.clearTextInput }, h("ion-icon", { key: '
|
|
561
|
+
}, onClick: this.clearTextInput }, h("ion-icon", { key: 'dd75a516d32110d85382b664c663bd41f177ce12', "aria-hidden": "true", icon: clearIconData }))), h("slot", { key: '330d4b9389f2c62223a5ee24003e96ef3e6b2473', name: "end" })), shouldRenderHighlight && h("div", { key: '8e442bed130ddc84976ab70fd3f8578d6bcc6316', class: "input-highlight" })), this.renderBottomContent()));
|
|
533
562
|
}
|
|
534
563
|
static get is() { return "ion-input"; }
|
|
535
564
|
static get encapsulation() { return "scoped"; }
|
|
@@ -7,7 +7,7 @@ import { clamp, getElementRoot, raf } from "../../../utils/helpers";
|
|
|
7
7
|
import { FOCUS_TRAP_DISABLE_CLASS } from "../../../utils/overlays";
|
|
8
8
|
import { getBackdropValueForSheet } from "../utils";
|
|
9
9
|
import { calculateSpringStep, handleCanDismiss } from "./utils";
|
|
10
|
-
export const createSheetGesture = (baseEl, backdropEl, wrapperEl, initialBreakpoint, backdropBreakpoint, animation, breakpoints = [], expandToScroll, getCurrentBreakpoint, onDismiss, onBreakpointChange
|
|
10
|
+
export const createSheetGesture = (baseEl, backdropEl, wrapperEl, initialBreakpoint, backdropBreakpoint, animation, breakpoints = [], expandToScroll, getCurrentBreakpoint, onDismiss, onBreakpointChange) => {
|
|
11
11
|
// Defaults for the sheet swipe animation
|
|
12
12
|
const defaultBackdrop = [
|
|
13
13
|
{ offset: 0, opacity: 'var(--backdrop-opacity)' },
|
|
@@ -338,8 +338,6 @@ export const createSheetGesture = (baseEl, backdropEl, wrapperEl, initialBreakpo
|
|
|
338
338
|
: step;
|
|
339
339
|
offset = clamp(0.0001, processedStep, maxStep);
|
|
340
340
|
animation.progressStep(offset);
|
|
341
|
-
// Notify modal of position change for safe-area updates
|
|
342
|
-
onGestureMove === null || onGestureMove === void 0 ? void 0 : onGestureMove();
|
|
343
341
|
};
|
|
344
342
|
const onEnd = (detail) => {
|
|
345
343
|
/**
|
|
@@ -12,7 +12,7 @@ import { calculateSpringStep, handleCanDismiss } from "./utils";
|
|
|
12
12
|
export const SwipeToCloseDefaults = {
|
|
13
13
|
MIN_PRESENTING_SCALE: 0.915,
|
|
14
14
|
};
|
|
15
|
-
export const createSwipeToCloseGesture = (el, animation, statusBarStyle, onDismiss
|
|
15
|
+
export const createSwipeToCloseGesture = (el, animation, statusBarStyle, onDismiss) => {
|
|
16
16
|
/**
|
|
17
17
|
* The step value at which a card modal
|
|
18
18
|
* is eligible for dismissing via gesture.
|
|
@@ -169,8 +169,6 @@ export const createSwipeToCloseGesture = (el, animation, statusBarStyle, onDismi
|
|
|
169
169
|
const processedStep = isAttemptingDismissWithCanDismiss ? calculateSpringStep(step / maxStep) : step;
|
|
170
170
|
const clampedStep = clamp(0.0001, processedStep, maxStep);
|
|
171
171
|
animation.progressStep(clampedStep);
|
|
172
|
-
// Notify modal of position change for safe-area updates
|
|
173
|
-
onGestureMove === null || onGestureMove === void 0 ? void 0 : onGestureMove();
|
|
174
172
|
/**
|
|
175
173
|
* When swiping down half way, the status bar style
|
|
176
174
|
* should be reset to its default value.
|
|
@@ -135,6 +135,10 @@ ion-backdrop {
|
|
|
135
135
|
:host {
|
|
136
136
|
--width: 600px;
|
|
137
137
|
--height: 500px;
|
|
138
|
+
--ion-safe-area-top: 0px;
|
|
139
|
+
--ion-safe-area-bottom: 0px;
|
|
140
|
+
--ion-safe-area-right: 0px;
|
|
141
|
+
--ion-safe-area-left: 0px;
|
|
138
142
|
}
|
|
139
143
|
}
|
|
140
144
|
@media only screen and (min-width: 768px) and (min-height: 768px) {
|
|
@@ -232,9 +232,7 @@ export class Modal {
|
|
|
232
232
|
}
|
|
233
233
|
}
|
|
234
234
|
onWindowResize() {
|
|
235
|
-
//
|
|
236
|
-
this.updateSafeAreaOverrides();
|
|
237
|
-
// Only handle view transition for iOS card modals when no custom animations are provided
|
|
235
|
+
// Only handle resize for iOS card modals when no custom animations are provided
|
|
238
236
|
if (getIonMode(this) !== 'ios' || !this.presentingElement || this.enterAnimation || this.leaveAnimation) {
|
|
239
237
|
return;
|
|
240
238
|
}
|
|
@@ -416,8 +414,6 @@ export class Modal {
|
|
|
416
414
|
else if (!this.keepContentsMounted) {
|
|
417
415
|
await waitForMount();
|
|
418
416
|
}
|
|
419
|
-
// Predict safe-area needs based on modal configuration to avoid visual snap
|
|
420
|
-
this.setInitialSafeAreaOverrides(presentingElement);
|
|
421
417
|
writeTask(() => this.el.classList.add('show-modal'));
|
|
422
418
|
const hasCardModal = presentingElement !== undefined;
|
|
423
419
|
/**
|
|
@@ -479,8 +475,6 @@ export class Modal {
|
|
|
479
475
|
else if (hasCardModal) {
|
|
480
476
|
this.initSwipeToClose();
|
|
481
477
|
}
|
|
482
|
-
// Now that animation is complete, update safe-area based on actual position
|
|
483
|
-
this.updateSafeAreaOverrides();
|
|
484
478
|
// Initialize view transition listener for iOS card modals
|
|
485
479
|
this.initViewTransitionListener();
|
|
486
480
|
// Initialize parent removal observer
|
|
@@ -532,7 +526,7 @@ export class Modal {
|
|
|
532
526
|
await this.dismiss(undefined, GESTURE);
|
|
533
527
|
this.gestureAnimationDismissing = false;
|
|
534
528
|
});
|
|
535
|
-
}
|
|
529
|
+
});
|
|
536
530
|
this.gesture.enable(true);
|
|
537
531
|
}
|
|
538
532
|
initSheetGesture() {
|
|
@@ -553,8 +547,7 @@ export class Modal {
|
|
|
553
547
|
this.currentBreakpoint = breakpoint;
|
|
554
548
|
this.ionBreakpointDidChange.emit({ breakpoint });
|
|
555
549
|
}
|
|
556
|
-
|
|
557
|
-
}, () => this.updateSafeAreaOverrides());
|
|
550
|
+
});
|
|
558
551
|
this.gesture = gesture;
|
|
559
552
|
this.moveSheetToBreakpoint = moveSheetToBreakpoint;
|
|
560
553
|
this.gesture.enable(true);
|
|
@@ -632,76 +625,6 @@ export class Modal {
|
|
|
632
625
|
// Clear the cached reference
|
|
633
626
|
this.cachedPageParent = undefined;
|
|
634
627
|
}
|
|
635
|
-
/**
|
|
636
|
-
* Sets initial safe-area overrides based on modal configuration before
|
|
637
|
-
* the modal becomes visible. This predicts whether the modal will touch
|
|
638
|
-
* screen edges to avoid a visual snap after animation completes.
|
|
639
|
-
*/
|
|
640
|
-
setInitialSafeAreaOverrides(presentingElement) {
|
|
641
|
-
const style = this.el.style;
|
|
642
|
-
const isSheetModal = this.breakpoints !== undefined && this.initialBreakpoint !== undefined;
|
|
643
|
-
const isCardModal = presentingElement !== undefined;
|
|
644
|
-
const isTablet = window.innerWidth >= 768;
|
|
645
|
-
// Sheet modals: always touch bottom, top depends on breakpoint
|
|
646
|
-
if (isSheetModal) {
|
|
647
|
-
style.setProperty('--ion-safe-area-top', '0px');
|
|
648
|
-
// Don't override bottom - sheet always touches bottom
|
|
649
|
-
style.setProperty('--ion-safe-area-left', '0px');
|
|
650
|
-
style.setProperty('--ion-safe-area-right', '0px');
|
|
651
|
-
return;
|
|
652
|
-
}
|
|
653
|
-
// Card modals are inset from edges (rounded corners), no safe areas needed
|
|
654
|
-
if (isCardModal) {
|
|
655
|
-
style.setProperty('--ion-safe-area-top', '0px');
|
|
656
|
-
style.setProperty('--ion-safe-area-bottom', '0px');
|
|
657
|
-
style.setProperty('--ion-safe-area-left', '0px');
|
|
658
|
-
style.setProperty('--ion-safe-area-right', '0px');
|
|
659
|
-
return;
|
|
660
|
-
}
|
|
661
|
-
// Phone modals are fullscreen, need all safe areas
|
|
662
|
-
if (!isTablet) {
|
|
663
|
-
// Don't set any overrides - inherit from :root
|
|
664
|
-
return;
|
|
665
|
-
}
|
|
666
|
-
// Default tablet modal: centered dialog, no safe areas needed
|
|
667
|
-
// Check for fullscreen override via CSS custom properties
|
|
668
|
-
const computedStyle = getComputedStyle(this.el);
|
|
669
|
-
const width = computedStyle.getPropertyValue('--width').trim();
|
|
670
|
-
const height = computedStyle.getPropertyValue('--height').trim();
|
|
671
|
-
if (width === '100%' && height === '100%') {
|
|
672
|
-
// Fullscreen modal - need safe areas, don't override
|
|
673
|
-
return;
|
|
674
|
-
}
|
|
675
|
-
// Centered dialog - zero out all safe areas
|
|
676
|
-
style.setProperty('--ion-safe-area-top', '0px');
|
|
677
|
-
style.setProperty('--ion-safe-area-bottom', '0px');
|
|
678
|
-
style.setProperty('--ion-safe-area-left', '0px');
|
|
679
|
-
style.setProperty('--ion-safe-area-right', '0px');
|
|
680
|
-
}
|
|
681
|
-
/**
|
|
682
|
-
* Updates safe-area CSS variable overrides based on whether the modal
|
|
683
|
-
* is touching each edge of the viewport. This is called after animation
|
|
684
|
-
* and during gestures to handle dynamic position changes.
|
|
685
|
-
*/
|
|
686
|
-
updateSafeAreaOverrides() {
|
|
687
|
-
const wrapper = this.wrapperEl;
|
|
688
|
-
if (!wrapper)
|
|
689
|
-
return;
|
|
690
|
-
const rect = wrapper.getBoundingClientRect();
|
|
691
|
-
const threshold = 2; // Account for subpixel rendering
|
|
692
|
-
const touchingTop = rect.top <= threshold;
|
|
693
|
-
const touchingBottom = rect.bottom >= window.innerHeight - threshold;
|
|
694
|
-
const touchingLeft = rect.left <= threshold;
|
|
695
|
-
const touchingRight = rect.right >= window.innerWidth - threshold;
|
|
696
|
-
// Remove override when touching edge (allow inheritance), set to 0 when not touching
|
|
697
|
-
const style = this.el.style;
|
|
698
|
-
touchingTop ? style.removeProperty('--ion-safe-area-top') : style.setProperty('--ion-safe-area-top', '0px');
|
|
699
|
-
touchingBottom
|
|
700
|
-
? style.removeProperty('--ion-safe-area-bottom')
|
|
701
|
-
: style.setProperty('--ion-safe-area-bottom', '0px');
|
|
702
|
-
touchingLeft ? style.removeProperty('--ion-safe-area-left') : style.setProperty('--ion-safe-area-left', '0px');
|
|
703
|
-
touchingRight ? style.removeProperty('--ion-safe-area-right') : style.setProperty('--ion-safe-area-right', '0px');
|
|
704
|
-
}
|
|
705
628
|
sheetOnDismiss() {
|
|
706
629
|
/**
|
|
707
630
|
* While the gesture animation is finishing
|
|
@@ -1047,20 +970,20 @@ export class Modal {
|
|
|
1047
970
|
const isCardModal = presentingElement !== undefined && mode === 'ios';
|
|
1048
971
|
const isHandleCycle = handleBehavior === 'cycle';
|
|
1049
972
|
const isSheetModalWithHandle = isSheetModal && showHandle;
|
|
1050
|
-
return (h(Host, Object.assign({ key: '
|
|
973
|
+
return (h(Host, Object.assign({ key: '9a75095a13de0cfc96f1fa69fd92777d25da8daa', "no-router": true,
|
|
1051
974
|
// Allow the modal to be navigable when the handle is focusable
|
|
1052
975
|
tabIndex: isHandleCycle && isSheetModalWithHandle ? 0 : -1 }, htmlAttributes, { style: {
|
|
1053
976
|
zIndex: `${20000 + this.overlayIndex}`,
|
|
1054
|
-
}, 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: '
|
|
977
|
+
}, 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: 'd02612d8063ef20f59f173ff47795f71cdaaf63e', ref: (el) => (this.backdropEl = el), visible: this.showBackdrop, tappable: this.backdropDismiss, part: "backdrop" }), mode === 'ios' && h("div", { key: '708761b70a93e34c08faae079569f444c7416a4c', class: "modal-shadow" }), h("div", Object.assign({ key: 'a72226ff1a98229f9bfd9207b98fc57e02baa430',
|
|
1055
978
|
/*
|
|
1056
979
|
role and aria-modal must be used on the
|
|
1057
980
|
same element. They must also be set inside the
|
|
1058
981
|
shadow DOM otherwise ion-button will not be highlighted
|
|
1059
982
|
when using VoiceOver: https://bugs.webkit.org/show_bug.cgi?id=247134
|
|
1060
983
|
*/
|
|
1061
|
-
role: "dialog" }, inheritedAttributes, { "aria-modal": "true", class: "modal-wrapper ion-overlay-wrapper", part: "content", ref: (el) => (this.wrapperEl = el) }), showHandle && (h("button", { key: '
|
|
984
|
+
role: "dialog" }, inheritedAttributes, { "aria-modal": "true", class: "modal-wrapper ion-overlay-wrapper", part: "content", ref: (el) => (this.wrapperEl = el) }), showHandle && (h("button", { key: '0547f32323882660221385d84d492929caa77c6b', class: "modal-handle",
|
|
1062
985
|
// Prevents the handle from receiving keyboard focus when it does not cycle
|
|
1063
|
-
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: '
|
|
986
|
+
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: 'fccbd64518b6fa22f9e874deb6b4ba55d8d89c3b', onSlotchange: this.onSlotChange }))));
|
|
1064
987
|
}
|
|
1065
988
|
static get is() { return "ion-modal"; }
|
|
1066
989
|
static get encapsulation() { return "shadow"; }
|
|
@@ -135,6 +135,10 @@ ion-backdrop {
|
|
|
135
135
|
:host {
|
|
136
136
|
--width: 600px;
|
|
137
137
|
--height: 500px;
|
|
138
|
+
--ion-safe-area-top: 0px;
|
|
139
|
+
--ion-safe-area-bottom: 0px;
|
|
140
|
+
--ion-safe-area-right: 0px;
|
|
141
|
+
--ion-safe-area-left: 0px;
|
|
138
142
|
}
|
|
139
143
|
}
|
|
140
144
|
@media only screen and (min-width: 768px) and (min-height: 768px) {
|
package/dist/docs.json
CHANGED