@ionic/core 8.7.18-dev.11771365900.125bf49c → 8.7.18-dev.11772217280.122eed89
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-app.js +17 -12
- package/components/ion-checkbox.js +1 -1
- package/components/ion-content.js +1 -1
- package/components/ion-datetime.js +7 -4
- package/components/ion-fab-list.js +10 -3
- package/components/ion-img.js +11 -2
- package/components/ion-label.js +1 -1
- package/components/ion-modal.js +1 -1
- package/components/ion-popover.js +1 -1
- package/components/ion-radio-group.js +1 -1
- package/components/ion-searchbar.js +17 -6
- package/components/ion-select-modal.js +1 -1
- package/components/ion-select-popover.js +1 -1
- package/components/ion-select.js +8 -8
- package/components/{p-CJrGvZ1Z.js → p-51c2oSfC.js} +3 -3
- package/components/{p-BnpDIASH.js → p-BANeLH_G.js} +2 -2
- package/components/{p-D3KEyQ8e.js → p-BRLve2EP.js} +3 -3
- package/components/{p-DRHwNkVo.js → p-C6dkQWq2.js} +152 -30
- package/components/{p-CUfY9DTD.js → p-Cdm3dKWf.js} +8 -3
- package/components/{p-DyFBFrV7.js → p-D--b4514.js} +4 -4
- package/components/{p-DPm73mCi.js → p-DGOrLIyS.js} +7 -3
- package/components/{p-IHgAGzvW.js → p-iyo0Toaz.js} +326 -17
- package/dist/cjs/ion-app_8.cjs.entry.js +22 -13
- package/dist/cjs/ion-checkbox.cjs.entry.js +3 -3
- package/dist/cjs/ion-datetime_3.cjs.entry.js +6 -3
- package/dist/cjs/ion-fab_3.cjs.entry.js +10 -3
- package/dist/cjs/ion-img.cjs.entry.js +11 -2
- package/dist/cjs/ion-item_8.cjs.entry.js +8 -3
- package/dist/cjs/ion-modal.cjs.entry.js +326 -17
- package/dist/cjs/ion-popover.cjs.entry.js +152 -30
- package/dist/cjs/ion-radio_2.cjs.entry.js +2 -2
- package/dist/cjs/ion-searchbar.cjs.entry.js +17 -6
- package/dist/collection/components/app/app.js +15 -10
- package/dist/collection/components/checkbox/checkbox.js +4 -4
- package/dist/collection/components/content/content.js +7 -3
- package/dist/collection/components/datetime/datetime.js +6 -3
- package/dist/collection/components/fab-list/fab-list.js +10 -3
- package/dist/collection/components/img/img.js +11 -2
- package/dist/collection/components/label/label.js +8 -3
- package/dist/collection/components/modal/modal.ios.css +6 -5
- package/dist/collection/components/modal/modal.js +164 -15
- package/dist/collection/components/modal/modal.md.css +6 -5
- package/dist/collection/components/modal/safe-area-utils.js +165 -0
- package/dist/collection/components/popover/animations/ios.enter.js +33 -8
- package/dist/collection/components/popover/animations/md.enter.js +26 -6
- package/dist/collection/components/popover/utils.js +96 -19
- package/dist/collection/components/radio-group/radio-group.ios.css +0 -4
- package/dist/collection/components/radio-group/radio-group.md.css +0 -4
- package/dist/collection/components/searchbar/searchbar.js +17 -6
- package/dist/docs.json +1 -1
- package/dist/esm/ion-app_8.entry.js +24 -15
- package/dist/esm/ion-checkbox.entry.js +4 -4
- package/dist/esm/ion-datetime_3.entry.js +6 -3
- package/dist/esm/ion-fab_3.entry.js +10 -3
- package/dist/esm/ion-img.entry.js +11 -2
- package/dist/esm/ion-item_8.entry.js +8 -3
- package/dist/esm/ion-modal.entry.js +326 -17
- package/dist/esm/ion-popover.entry.js +152 -30
- package/dist/esm/ion-radio_2.entry.js +2 -2
- package/dist/esm/ion-searchbar.entry.js +17 -6
- package/dist/ionic/ionic.esm.js +1 -1
- package/dist/ionic/{p-72af946b.entry.js → p-2ac254dc.entry.js} +1 -1
- package/dist/ionic/p-7cad388a.entry.js +4 -0
- package/dist/ionic/p-7d218555.entry.js +4 -0
- package/dist/ionic/p-8303e3fc.entry.js +4 -0
- package/dist/ionic/p-915b3e3d.entry.js +4 -0
- package/dist/ionic/{p-eaf3f5ff.entry.js → p-b0ebf9f8.entry.js} +1 -1
- package/dist/ionic/p-e4c57008.entry.js +4 -0
- package/dist/ionic/p-e5d6d0f0.entry.js +4 -0
- package/dist/ionic/p-f1dfee25.entry.js +4 -0
- package/dist/ionic/{p-6444c606.entry.js → p-f9f7b9db.entry.js} +1 -1
- package/dist/types/components/app/app.d.ts +3 -0
- package/dist/types/components/datetime/datetime.d.ts +1 -0
- package/dist/types/components/fab-list/fab-list.d.ts +2 -0
- package/dist/types/components/img/img.d.ts +2 -0
- package/dist/types/components/label/label.d.ts +2 -0
- package/dist/types/components/modal/modal.d.ts +35 -0
- package/dist/types/components/modal/safe-area-utils.d.ts +66 -0
- package/dist/types/components/popover/utils.d.ts +23 -1
- package/dist/types/components/searchbar/searchbar.d.ts +3 -0
- package/hydrate/index.js +556 -73
- package/hydrate/index.mjs +556 -73
- package/package.json +1 -1
- package/dist/ionic/p-01e27965.entry.js +0 -4
- package/dist/ionic/p-3ec563c1.entry.js +0 -4
- package/dist/ionic/p-42db6404.entry.js +0 -4
- package/dist/ionic/p-46d74291.entry.js +0 -4
- package/dist/ionic/p-bc293244.entry.js +0 -4
- package/dist/ionic/p-d1f54e28.entry.js +0 -4
- package/dist/ionic/p-e338f669.entry.js +0 -4
|
@@ -1470,9 +1470,170 @@ const createSheetGesture = (baseEl, backdropEl, wrapperEl, initialBreakpoint, ba
|
|
|
1470
1470
|
};
|
|
1471
1471
|
};
|
|
1472
1472
|
|
|
1473
|
-
|
|
1473
|
+
/**
|
|
1474
|
+
* These thresholds match the SCSS media query breakpoints in modal.vars.scss
|
|
1475
|
+
* that trigger the centered dialog layout (non-fullscreen modal).
|
|
1476
|
+
*
|
|
1477
|
+
* SCSS defines two height breakpoints: $modal-inset-min-height-small (600px)
|
|
1478
|
+
* and $modal-inset-min-height-large (768px). We use the smaller one because
|
|
1479
|
+
* that's the threshold where the modal transitions from fullscreen to centered
|
|
1480
|
+
* dialog — the larger breakpoint only increases the dialog's height.
|
|
1481
|
+
*/
|
|
1482
|
+
const MODAL_INSET_MIN_WIDTH = 768;
|
|
1483
|
+
const MODAL_INSET_MIN_HEIGHT = 600;
|
|
1484
|
+
const EDGE_THRESHOLD = 5;
|
|
1485
|
+
/**
|
|
1486
|
+
* Cache for resolved root safe-area-top value, invalidated once per frame.
|
|
1487
|
+
*/
|
|
1488
|
+
let cachedRootSafeAreaTop = null;
|
|
1489
|
+
let cacheInvalidationScheduled = false;
|
|
1490
|
+
/**
|
|
1491
|
+
* Determines if the current viewport meets the CSS media query conditions
|
|
1492
|
+
* that cause regular modals to render as centered dialogs instead of fullscreen.
|
|
1493
|
+
* Matches: @media (min-width: 768px) and (min-height: 600px)
|
|
1494
|
+
*/
|
|
1495
|
+
const isCenteredDialogViewport = () => {
|
|
1496
|
+
if (!win)
|
|
1497
|
+
return false;
|
|
1498
|
+
return win.matchMedia(`(min-width: ${MODAL_INSET_MIN_WIDTH}px) and (min-height: ${MODAL_INSET_MIN_HEIGHT}px)`)
|
|
1499
|
+
.matches;
|
|
1500
|
+
};
|
|
1501
|
+
/**
|
|
1502
|
+
* Resolves the current root --ion-safe-area-top value to pixels.
|
|
1503
|
+
* Uses a temporary element because getComputedStyle on :root returns
|
|
1504
|
+
* the declared value of custom properties (e.g. "env(safe-area-inset-top)")
|
|
1505
|
+
* rather than a resolved number.
|
|
1506
|
+
*
|
|
1507
|
+
* Results are cached for the current frame to avoid repeated reflows.
|
|
1508
|
+
*/
|
|
1509
|
+
const getRootSafeAreaTop = () => {
|
|
1510
|
+
if (cachedRootSafeAreaTop !== null) {
|
|
1511
|
+
return cachedRootSafeAreaTop;
|
|
1512
|
+
}
|
|
1513
|
+
const doc = win === null || win === void 0 ? void 0 : win.document;
|
|
1514
|
+
if (!(doc === null || doc === void 0 ? void 0 : doc.body)) {
|
|
1515
|
+
return 0;
|
|
1516
|
+
}
|
|
1517
|
+
const el = doc.createElement('div');
|
|
1518
|
+
el.style.cssText =
|
|
1519
|
+
'position:fixed;visibility:hidden;pointer-events:none;top:0;left:0;' + 'padding-top:var(--ion-safe-area-top,0px);';
|
|
1520
|
+
doc.body.appendChild(el);
|
|
1521
|
+
const value = parseFloat(getComputedStyle(el).paddingTop) || 0;
|
|
1522
|
+
el.remove();
|
|
1523
|
+
cachedRootSafeAreaTop = value;
|
|
1524
|
+
if (!cacheInvalidationScheduled) {
|
|
1525
|
+
cacheInvalidationScheduled = true;
|
|
1526
|
+
raf(() => {
|
|
1527
|
+
cachedRootSafeAreaTop = null;
|
|
1528
|
+
cacheInvalidationScheduled = false;
|
|
1529
|
+
});
|
|
1530
|
+
}
|
|
1531
|
+
return value;
|
|
1532
|
+
};
|
|
1533
|
+
/**
|
|
1534
|
+
* Returns the initial safe-area configuration based on modal type.
|
|
1535
|
+
* This is called before animation starts and uses configuration-based prediction.
|
|
1536
|
+
*
|
|
1537
|
+
* @param context - Modal context information
|
|
1538
|
+
* @returns SafeAreaConfig with initial safe-area values
|
|
1539
|
+
*/
|
|
1540
|
+
const getInitialSafeAreaConfig = (context) => {
|
|
1541
|
+
const { isSheetModal, isCardModal } = context;
|
|
1542
|
+
// Sheet modals always zero top safe-area. The sheet height offset from the
|
|
1543
|
+
// top edge is handled by --ion-modal-offset-top (set in modal.tsx) using
|
|
1544
|
+
// the resolved root value, so --ion-safe-area-top is never needed for
|
|
1545
|
+
// height calculation. Keeping it at 0px prevents header content from
|
|
1546
|
+
// getting double-offset padding.
|
|
1547
|
+
if (isSheetModal) {
|
|
1548
|
+
return {
|
|
1549
|
+
top: '0px',
|
|
1550
|
+
bottom: 'inherit',
|
|
1551
|
+
left: '0px',
|
|
1552
|
+
right: '0px',
|
|
1553
|
+
};
|
|
1554
|
+
}
|
|
1555
|
+
// Card modals need safe-area for height calculation.
|
|
1556
|
+
// Note: isCardModal is already gated on mode === 'ios' by the caller.
|
|
1557
|
+
if (isCardModal) {
|
|
1558
|
+
return {
|
|
1559
|
+
top: 'inherit',
|
|
1560
|
+
bottom: 'inherit',
|
|
1561
|
+
left: '0px',
|
|
1562
|
+
right: '0px',
|
|
1563
|
+
};
|
|
1564
|
+
}
|
|
1565
|
+
// On viewports that meet the centered dialog media query breakpoints,
|
|
1566
|
+
// regular modals render as centered dialogs (not fullscreen), so they
|
|
1567
|
+
// don't touch any screen edges and don't need safe-area insets.
|
|
1568
|
+
if (isCenteredDialogViewport()) {
|
|
1569
|
+
return {
|
|
1570
|
+
top: '0px',
|
|
1571
|
+
bottom: '0px',
|
|
1572
|
+
left: '0px',
|
|
1573
|
+
right: '0px',
|
|
1574
|
+
};
|
|
1575
|
+
}
|
|
1576
|
+
// Fullscreen modals on phone - inherit all safe areas
|
|
1577
|
+
return {
|
|
1578
|
+
top: 'inherit',
|
|
1579
|
+
bottom: 'inherit',
|
|
1580
|
+
left: 'inherit',
|
|
1581
|
+
right: 'inherit',
|
|
1582
|
+
};
|
|
1583
|
+
};
|
|
1584
|
+
/**
|
|
1585
|
+
* Returns safe-area configuration based on actual modal position.
|
|
1586
|
+
* Detects which edges the modal overlaps with and only applies safe-area to those edges.
|
|
1587
|
+
*
|
|
1588
|
+
* Note: On Android edge-to-edge (API 36+), getBoundingClientRect() may report
|
|
1589
|
+
* inconsistent values. Sheet and card modals avoid this by using configuration-based
|
|
1590
|
+
* prediction instead. Regular modals use coordinate detection which works reliably
|
|
1591
|
+
* on web and iOS; Android edge-to-edge may need a configuration-based fallback
|
|
1592
|
+
* once a reliable detection mechanism is available.
|
|
1593
|
+
*
|
|
1594
|
+
* @param wrapperEl - The modal wrapper element to measure
|
|
1595
|
+
* @returns SafeAreaConfig based on position
|
|
1596
|
+
*/
|
|
1597
|
+
const getPositionBasedSafeAreaConfig = (wrapperEl) => {
|
|
1598
|
+
var _a, _b;
|
|
1599
|
+
const rect = wrapperEl.getBoundingClientRect();
|
|
1600
|
+
const vh = (_a = win === null || win === void 0 ? void 0 : win.innerHeight) !== null && _a !== void 0 ? _a : 0;
|
|
1601
|
+
const vw = (_b = win === null || win === void 0 ? void 0 : win.innerWidth) !== null && _b !== void 0 ? _b : 0;
|
|
1602
|
+
// Only apply safe-area to sides where modal overlaps with screen edge
|
|
1603
|
+
return {
|
|
1604
|
+
top: rect.top <= EDGE_THRESHOLD ? 'inherit' : '0px',
|
|
1605
|
+
bottom: rect.bottom >= vh - EDGE_THRESHOLD ? 'inherit' : '0px',
|
|
1606
|
+
left: rect.left <= EDGE_THRESHOLD ? 'inherit' : '0px',
|
|
1607
|
+
right: rect.right >= vw - EDGE_THRESHOLD ? 'inherit' : '0px',
|
|
1608
|
+
};
|
|
1609
|
+
};
|
|
1610
|
+
/**
|
|
1611
|
+
* Applies safe-area CSS custom property overrides to the modal host element.
|
|
1612
|
+
*
|
|
1613
|
+
* @param hostEl - The modal host element (ion-modal)
|
|
1614
|
+
* @param config - Safe-area configuration to apply
|
|
1615
|
+
*/
|
|
1616
|
+
const applySafeAreaOverrides = (hostEl, config) => {
|
|
1617
|
+
hostEl.style.setProperty('--ion-safe-area-top', config.top);
|
|
1618
|
+
hostEl.style.setProperty('--ion-safe-area-bottom', config.bottom);
|
|
1619
|
+
hostEl.style.setProperty('--ion-safe-area-left', config.left);
|
|
1620
|
+
hostEl.style.setProperty('--ion-safe-area-right', config.right);
|
|
1621
|
+
};
|
|
1622
|
+
/**
|
|
1623
|
+
* Clears safe-area CSS custom property overrides from the modal host element.
|
|
1624
|
+
*
|
|
1625
|
+
* @param hostEl - The modal host element (ion-modal)
|
|
1626
|
+
*/
|
|
1627
|
+
const clearSafeAreaOverrides = (hostEl) => {
|
|
1628
|
+
hostEl.style.removeProperty('--ion-safe-area-top');
|
|
1629
|
+
hostEl.style.removeProperty('--ion-safe-area-bottom');
|
|
1630
|
+
hostEl.style.removeProperty('--ion-safe-area-left');
|
|
1631
|
+
hostEl.style.removeProperty('--ion-safe-area-right');
|
|
1632
|
+
};
|
|
1633
|
+
|
|
1634
|
+
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-modal-offset-top, 0px) + 10px))}:host(.modal-sheet) .modal-wrapper,:host(.modal-sheet) .modal-shadow{position:absolute;bottom:0}:host(.modal-sheet.modal-no-expand-scroll) ion-footer{position:absolute;bottom:0;width:var(--width)}:host{--backdrop-opacity:var(--ion-backdrop-opacity, 0.4)}:host(.modal-card),:host(.modal-sheet){--border-radius:10px}@media only screen and (min-width: 768px) and (min-height: 600px){:host{--border-radius:10px}}.modal-wrapper{-webkit-transform:translate3d(0, 100%, 0);transform:translate3d(0, 100%, 0)}@media screen and (max-width: 767px){@supports (width: max(0px, 1px)){:host(.modal-card){--height:calc(100% - max(30px, var(--ion-safe-area-top)) - 10px)}}@supports not (width: max(0px, 1px)){:host(.modal-card){--height:calc(100% - 40px)}}:host(.modal-card) .modal-wrapper{border-start-start-radius:var(--border-radius);border-start-end-radius:var(--border-radius);border-end-end-radius:0;border-end-start-radius:0}:host(.modal-card){--backdrop-opacity:0;--width:100%;-ms-flex-align:end;align-items:flex-end}:host(.modal-card) .modal-shadow{display:none}:host(.modal-card) ion-backdrop{pointer-events:none}}@media screen and (min-width: 768px){:host(.modal-card){--width:calc(100% - 120px);--height:calc(100% - (120px + var(--ion-safe-area-top) + var(--ion-safe-area-bottom)));--max-width:720px;--max-height:1000px;--backdrop-opacity:0;--box-shadow:0px 0px 30px 10px rgba(0, 0, 0, 0.1);-webkit-transition:all 0.5s ease-in-out;transition:all 0.5s ease-in-out}:host(.modal-card) .modal-wrapper{-webkit-box-shadow:none;box-shadow:none}:host(.modal-card) .modal-shadow{-webkit-box-shadow:var(--box-shadow);box-shadow:var(--box-shadow)}}:host(.modal-sheet) .modal-wrapper{border-start-start-radius:var(--border-radius);border-start-end-radius:var(--border-radius);border-end-end-radius:0;border-end-start-radius:0}";
|
|
1474
1635
|
|
|
1475
|
-
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
|
|
1636
|
+
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-modal-offset-top, 0px) + 10px))}:host(.modal-sheet) .modal-wrapper,:host(.modal-sheet) .modal-shadow{position:absolute;bottom:0}:host(.modal-sheet.modal-no-expand-scroll) ion-footer{position:absolute;bottom:0;width:var(--width)}:host{--backdrop-opacity:var(--ion-backdrop-opacity, 0.32)}@media only screen and (min-width: 768px) and (min-height: 600px){:host{--border-radius:2px;--box-shadow:0 28px 48px rgba(0, 0, 0, 0.4)}}.modal-wrapper{-webkit-transform:translate3d(0, 40px, 0);transform:translate3d(0, 40px, 0);opacity:0.01}";
|
|
1476
1637
|
|
|
1477
1638
|
const Modal = /*@__PURE__*/ proxyCustomElement(class Modal extends H {
|
|
1478
1639
|
constructor(registerHost) {
|
|
@@ -1689,13 +1850,31 @@ const Modal = /*@__PURE__*/ proxyCustomElement(class Modal extends H {
|
|
|
1689
1850
|
}
|
|
1690
1851
|
}
|
|
1691
1852
|
onWindowResize() {
|
|
1692
|
-
|
|
1693
|
-
if (getIonMode(this) !== 'ios' || !this.presentingElement || this.enterAnimation || this.leaveAnimation) {
|
|
1853
|
+
if (!this.presented)
|
|
1694
1854
|
return;
|
|
1695
|
-
}
|
|
1696
1855
|
clearTimeout(this.resizeTimeout);
|
|
1697
1856
|
this.resizeTimeout = setTimeout(() => {
|
|
1698
|
-
this.
|
|
1857
|
+
const context = this.getSafeAreaContext();
|
|
1858
|
+
// iOS card modals: handle portrait/landscape view transitions
|
|
1859
|
+
if (context.isCardModal && !this.enterAnimation && !this.leaveAnimation) {
|
|
1860
|
+
this.handleViewTransition();
|
|
1861
|
+
}
|
|
1862
|
+
// Sheet modals: re-compute the internal offset property since safe-area
|
|
1863
|
+
// values may change on device rotation (e.g., portrait notch vs landscape).
|
|
1864
|
+
if (context.isSheetModal) {
|
|
1865
|
+
this.updateSheetOffsetTop();
|
|
1866
|
+
}
|
|
1867
|
+
// Regular (non-sheet, non-card) modals: update safe-area overrides
|
|
1868
|
+
// since the viewport may have crossed the centered-dialog breakpoint.
|
|
1869
|
+
if (!context.isSheetModal && !context.isCardModal) {
|
|
1870
|
+
this.updateSafeAreaOverrides();
|
|
1871
|
+
// Re-evaluate fullscreen safe-area padding: clear first, then re-apply
|
|
1872
|
+
if (this.wrapperEl) {
|
|
1873
|
+
this.wrapperEl.style.removeProperty('height');
|
|
1874
|
+
this.wrapperEl.style.removeProperty('padding-bottom');
|
|
1875
|
+
}
|
|
1876
|
+
this.applyFullscreenSafeArea();
|
|
1877
|
+
}
|
|
1699
1878
|
}, 50); // Debounce to avoid excessive calls during active resizing
|
|
1700
1879
|
}
|
|
1701
1880
|
breakpointsChanged(breakpoints) {
|
|
@@ -1712,6 +1891,9 @@ const Modal = /*@__PURE__*/ proxyCustomElement(class Modal extends H {
|
|
|
1712
1891
|
this.triggerController.removeClickListener();
|
|
1713
1892
|
this.cleanupViewTransitionListener();
|
|
1714
1893
|
this.cleanupParentRemovalObserver();
|
|
1894
|
+
// Also called in dismiss() — intentional dual cleanup covers both
|
|
1895
|
+
// dismiss-then-remove and direct DOM removal without dismiss.
|
|
1896
|
+
this.cleanupSafeAreaOverrides();
|
|
1715
1897
|
}
|
|
1716
1898
|
componentWillLoad() {
|
|
1717
1899
|
var _a;
|
|
@@ -1872,6 +2054,11 @@ const Modal = /*@__PURE__*/ proxyCustomElement(class Modal extends H {
|
|
|
1872
2054
|
await waitForMount();
|
|
1873
2055
|
}
|
|
1874
2056
|
writeTask(() => this.el.classList.add('show-modal'));
|
|
2057
|
+
// Recalculate isSheetModal before safe-area setup because framework
|
|
2058
|
+
// bindings (e.g., Angular) may not have been applied when componentWillLoad ran.
|
|
2059
|
+
this.isSheetModal = this.breakpoints !== undefined && this.initialBreakpoint !== undefined;
|
|
2060
|
+
// Set initial safe-area overrides before animation
|
|
2061
|
+
this.setInitialSafeAreaOverrides();
|
|
1875
2062
|
const hasCardModal = presentingElement !== undefined;
|
|
1876
2063
|
/**
|
|
1877
2064
|
* We need to change the status bar at the
|
|
@@ -1889,6 +2076,10 @@ const Modal = /*@__PURE__*/ proxyCustomElement(class Modal extends H {
|
|
|
1889
2076
|
backdropBreakpoint: this.backdropBreakpoint,
|
|
1890
2077
|
expandToScroll: this.expandToScroll,
|
|
1891
2078
|
});
|
|
2079
|
+
// Update safe-area based on actual position after animation
|
|
2080
|
+
this.updateSafeAreaOverrides();
|
|
2081
|
+
// Apply fullscreen safe-area padding if needed
|
|
2082
|
+
this.applyFullscreenSafeArea();
|
|
1892
2083
|
/* tslint:disable-next-line */
|
|
1893
2084
|
if (typeof window !== 'undefined') {
|
|
1894
2085
|
/**
|
|
@@ -1920,13 +2111,7 @@ const Modal = /*@__PURE__*/ proxyCustomElement(class Modal extends H {
|
|
|
1920
2111
|
};
|
|
1921
2112
|
window.addEventListener(KEYBOARD_DID_OPEN, this.keyboardOpenCallback);
|
|
1922
2113
|
}
|
|
1923
|
-
|
|
1924
|
-
* Recalculate isSheetModal because framework bindings (e.g., Angular)
|
|
1925
|
-
* may not have been applied when componentWillLoad ran.
|
|
1926
|
-
*/
|
|
1927
|
-
const isSheetModal = this.breakpoints !== undefined && this.initialBreakpoint !== undefined;
|
|
1928
|
-
this.isSheetModal = isSheetModal;
|
|
1929
|
-
if (isSheetModal) {
|
|
2114
|
+
if (this.isSheetModal) {
|
|
1930
2115
|
this.initSheetGesture();
|
|
1931
2116
|
}
|
|
1932
2117
|
else if (hasCardModal) {
|
|
@@ -2116,6 +2301,9 @@ const Modal = /*@__PURE__*/ proxyCustomElement(class Modal extends H {
|
|
|
2116
2301
|
if (this.gestureAnimationDismissing && role !== GESTURE) {
|
|
2117
2302
|
return false;
|
|
2118
2303
|
}
|
|
2304
|
+
// Cancel any pending resize timeout to prevent stale updates during dismiss
|
|
2305
|
+
clearTimeout(this.resizeTimeout);
|
|
2306
|
+
this.resizeTimeout = undefined;
|
|
2119
2307
|
/**
|
|
2120
2308
|
* Because the canDismiss check below is async,
|
|
2121
2309
|
* we need to claim a lock before the check happens,
|
|
@@ -2170,6 +2358,7 @@ const Modal = /*@__PURE__*/ proxyCustomElement(class Modal extends H {
|
|
|
2170
2358
|
}
|
|
2171
2359
|
this.cleanupViewTransitionListener();
|
|
2172
2360
|
this.cleanupParentRemovalObserver();
|
|
2361
|
+
this.cleanupSafeAreaOverrides();
|
|
2173
2362
|
this.cleanupChildRoutePassthrough();
|
|
2174
2363
|
}
|
|
2175
2364
|
this.currentBreakpoint = undefined;
|
|
@@ -2290,6 +2479,9 @@ const Modal = /*@__PURE__*/ proxyCustomElement(class Modal extends H {
|
|
|
2290
2479
|
this.viewTransitionAnimation = transitionAnimation;
|
|
2291
2480
|
transitionAnimation.play().then(() => {
|
|
2292
2481
|
this.viewTransitionAnimation = undefined;
|
|
2482
|
+
// Wait for a layout pass after the transition so getBoundingClientRect()
|
|
2483
|
+
// in getPositionBasedSafeAreaConfig() reflects the new dimensions.
|
|
2484
|
+
raf(() => this.updateSafeAreaOverrides());
|
|
2293
2485
|
// After orientation transition, recreate the swipe-to-close gesture
|
|
2294
2486
|
// with updated animation that reflects the new presenting element state
|
|
2295
2487
|
this.reinitSwipeToClose();
|
|
@@ -2416,6 +2608,123 @@ const Modal = /*@__PURE__*/ proxyCustomElement(class Modal extends H {
|
|
|
2416
2608
|
(_a = this.parentRemovalObserver) === null || _a === void 0 ? void 0 : _a.disconnect();
|
|
2417
2609
|
this.parentRemovalObserver = undefined;
|
|
2418
2610
|
}
|
|
2611
|
+
/**
|
|
2612
|
+
* Creates the context object for safe-area utilities.
|
|
2613
|
+
*/
|
|
2614
|
+
getSafeAreaContext() {
|
|
2615
|
+
return {
|
|
2616
|
+
isSheetModal: this.isSheetModal,
|
|
2617
|
+
isCardModal: this.presentingElement !== undefined && getIonMode(this) === 'ios',
|
|
2618
|
+
presentingElement: this.presentingElement,
|
|
2619
|
+
breakpoints: this.breakpoints,
|
|
2620
|
+
currentBreakpoint: this.currentBreakpoint,
|
|
2621
|
+
};
|
|
2622
|
+
}
|
|
2623
|
+
/**
|
|
2624
|
+
* Sets initial safe-area overrides before modal animation.
|
|
2625
|
+
* Called in present() before animation starts.
|
|
2626
|
+
*
|
|
2627
|
+
* For sheet modals, the SCSS --height formula uses --ion-modal-offset-top
|
|
2628
|
+
* (an internal property) instead of --ion-safe-area-top. We resolve the
|
|
2629
|
+
* root safe-area-top to pixels and set --ion-modal-offset-top, decoupling
|
|
2630
|
+
* the height calculation from --ion-safe-area-top (which is zeroed for
|
|
2631
|
+
* sheets to prevent header content from getting double-offset padding).
|
|
2632
|
+
*/
|
|
2633
|
+
setInitialSafeAreaOverrides() {
|
|
2634
|
+
const context = this.getSafeAreaContext();
|
|
2635
|
+
const safeAreaConfig = getInitialSafeAreaConfig(context);
|
|
2636
|
+
applySafeAreaOverrides(this.el, safeAreaConfig);
|
|
2637
|
+
// Set the internal offset property with the resolved root safe-area-top value
|
|
2638
|
+
if (context.isSheetModal) {
|
|
2639
|
+
this.updateSheetOffsetTop();
|
|
2640
|
+
}
|
|
2641
|
+
}
|
|
2642
|
+
/**
|
|
2643
|
+
* Resolves the current root --ion-safe-area-top value and sets the
|
|
2644
|
+
* internal --ion-modal-offset-top property on the host element.
|
|
2645
|
+
* Called on present and on resize (e.g., device rotation changes safe-area).
|
|
2646
|
+
*/
|
|
2647
|
+
updateSheetOffsetTop() {
|
|
2648
|
+
const safeAreaTop = getRootSafeAreaTop();
|
|
2649
|
+
this.el.style.setProperty('--ion-modal-offset-top', `${safeAreaTop}px`);
|
|
2650
|
+
}
|
|
2651
|
+
/**
|
|
2652
|
+
* Updates safe-area overrides during dynamic state changes.
|
|
2653
|
+
* Called after animations, during gestures, and on orientation changes.
|
|
2654
|
+
*/
|
|
2655
|
+
updateSafeAreaOverrides() {
|
|
2656
|
+
const { wrapperEl, el } = this;
|
|
2657
|
+
const context = this.getSafeAreaContext();
|
|
2658
|
+
// Sheet modals: safe-area is fully determined at presentation time
|
|
2659
|
+
// (top is always 0px, height is frozen). Nothing to update.
|
|
2660
|
+
if (context.isSheetModal)
|
|
2661
|
+
return;
|
|
2662
|
+
// Card modals have fixed safe-area requirements set by initial prediction.
|
|
2663
|
+
if (context.isCardModal)
|
|
2664
|
+
return;
|
|
2665
|
+
// wrapperEl is required for position-based detection below
|
|
2666
|
+
if (!wrapperEl)
|
|
2667
|
+
return;
|
|
2668
|
+
// Regular modals: use position-based detection to correctly handle both
|
|
2669
|
+
// fullscreen modals and centered dialogs with custom dimensions.
|
|
2670
|
+
const safeAreaConfig = getPositionBasedSafeAreaConfig(wrapperEl);
|
|
2671
|
+
applySafeAreaOverrides(el, safeAreaConfig);
|
|
2672
|
+
}
|
|
2673
|
+
/**
|
|
2674
|
+
* Applies padding-bottom to fullscreen modal wrapper to prevent
|
|
2675
|
+
* content from overlapping system navigation bar.
|
|
2676
|
+
*/
|
|
2677
|
+
applyFullscreenSafeArea() {
|
|
2678
|
+
const { wrapperEl, el } = this;
|
|
2679
|
+
if (!wrapperEl)
|
|
2680
|
+
return;
|
|
2681
|
+
const context = this.getSafeAreaContext();
|
|
2682
|
+
if (context.isSheetModal || context.isCardModal)
|
|
2683
|
+
return;
|
|
2684
|
+
// Check for standard Ionic layout children (ion-content, ion-footer),
|
|
2685
|
+
// searching one level deep for wrapped components (e.g.,
|
|
2686
|
+
// <app-footer><ion-footer>...</ion-footer></app-footer>).
|
|
2687
|
+
// Note: uses a manual loop instead of querySelector(':scope > ...') because
|
|
2688
|
+
// Stencil's mock-doc (used in spec tests) does not support :scope.
|
|
2689
|
+
let hasContent = false;
|
|
2690
|
+
let hasFooter = false;
|
|
2691
|
+
for (const child of Array.from(el.children)) {
|
|
2692
|
+
if (child.tagName === 'ION-CONTENT')
|
|
2693
|
+
hasContent = true;
|
|
2694
|
+
if (child.tagName === 'ION-FOOTER')
|
|
2695
|
+
hasFooter = true;
|
|
2696
|
+
for (const grandchild of Array.from(child.children)) {
|
|
2697
|
+
if (grandchild.tagName === 'ION-CONTENT')
|
|
2698
|
+
hasContent = true;
|
|
2699
|
+
if (grandchild.tagName === 'ION-FOOTER')
|
|
2700
|
+
hasFooter = true;
|
|
2701
|
+
}
|
|
2702
|
+
}
|
|
2703
|
+
// Only apply wrapper padding for standard Ionic layouts (has ion-content
|
|
2704
|
+
// but no ion-footer). Custom modals with raw HTML are fully
|
|
2705
|
+
// developer-controlled and should not be modified.
|
|
2706
|
+
if (!hasContent || hasFooter)
|
|
2707
|
+
return;
|
|
2708
|
+
// Reduce wrapper height by safe-area and add equivalent padding so the
|
|
2709
|
+
// total visual size stays the same but the flex content area shrinks.
|
|
2710
|
+
// Using height + padding instead of box-sizing: border-box avoids
|
|
2711
|
+
// breaking custom modals that set --border-width (border-box would
|
|
2712
|
+
// include the border inside the height, changing the layout).
|
|
2713
|
+
wrapperEl.style.setProperty('height', 'calc(var(--height) - var(--ion-safe-area-bottom, 0px))');
|
|
2714
|
+
wrapperEl.style.setProperty('padding-bottom', 'var(--ion-safe-area-bottom, 0px)');
|
|
2715
|
+
}
|
|
2716
|
+
/**
|
|
2717
|
+
* Clears all safe-area overrides and padding from wrapper.
|
|
2718
|
+
*/
|
|
2719
|
+
cleanupSafeAreaOverrides() {
|
|
2720
|
+
clearSafeAreaOverrides(this.el);
|
|
2721
|
+
// Remove internal sheet offset property
|
|
2722
|
+
this.el.style.removeProperty('--ion-modal-offset-top');
|
|
2723
|
+
if (this.wrapperEl) {
|
|
2724
|
+
this.wrapperEl.style.removeProperty('height');
|
|
2725
|
+
this.wrapperEl.style.removeProperty('padding-bottom');
|
|
2726
|
+
}
|
|
2727
|
+
}
|
|
2419
2728
|
render() {
|
|
2420
2729
|
const { handle, isSheetModal, presentingElement, htmlAttributes, handleBehavior, inheritedAttributes, focusTrap, expandToScroll, } = this;
|
|
2421
2730
|
const showHandle = handle !== false && isSheetModal;
|
|
@@ -2423,20 +2732,20 @@ const Modal = /*@__PURE__*/ proxyCustomElement(class Modal extends H {
|
|
|
2423
2732
|
const isCardModal = presentingElement !== undefined && mode === 'ios';
|
|
2424
2733
|
const isHandleCycle = handleBehavior === 'cycle';
|
|
2425
2734
|
const isSheetModalWithHandle = isSheetModal && showHandle;
|
|
2426
|
-
return (h(Host, Object.assign({ key: '
|
|
2735
|
+
return (h(Host, Object.assign({ key: '952cbd52d1fc737332a23d523b02d5fa60abf30a', "no-router": true,
|
|
2427
2736
|
// Allow the modal to be navigable when the handle is focusable
|
|
2428
2737
|
tabIndex: isHandleCycle && isSheetModalWithHandle ? 0 : -1 }, htmlAttributes, { style: {
|
|
2429
2738
|
zIndex: `${20000 + this.overlayIndex}`,
|
|
2430
|
-
}, 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: '
|
|
2739
|
+
}, 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: '66e3658cfcc2961d99ecc1174f26b1794ceb65e9', ref: (el) => (this.backdropEl = el), visible: this.showBackdrop, tappable: this.backdropDismiss, part: "backdrop" }), mode === 'ios' && h("div", { key: '3d1b9b26daf87374e2029d0e0a7fc09b9257fd77', class: "modal-shadow" }), h("div", Object.assign({ key: 'e652c2b3eb66afa8367d94c3b14ba0e825877a82',
|
|
2431
2740
|
/*
|
|
2432
2741
|
role and aria-modal must be used on the
|
|
2433
2742
|
same element. They must also be set inside the
|
|
2434
2743
|
shadow DOM otherwise ion-button will not be highlighted
|
|
2435
2744
|
when using VoiceOver: https://bugs.webkit.org/show_bug.cgi?id=247134
|
|
2436
2745
|
*/
|
|
2437
|
-
role: "dialog" }, inheritedAttributes, { "aria-modal": "true", class: "modal-wrapper ion-overlay-wrapper", part: "content", ref: (el) => (this.wrapperEl = el) }), showHandle && (h("button", { key: '
|
|
2746
|
+
role: "dialog" }, inheritedAttributes, { "aria-modal": "true", class: "modal-wrapper ion-overlay-wrapper", part: "content", ref: (el) => (this.wrapperEl = el) }), showHandle && (h("button", { key: '41662183450e8ef2f7d96dac2bea5952bad8b7a5', class: "modal-handle",
|
|
2438
2747
|
// Prevents the handle from receiving keyboard focus when it does not cycle
|
|
2439
|
-
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: '
|
|
2748
|
+
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: '4aac4e2928929b9e5e59b33c83395182105da529', onSlotchange: this.onSlotChange }))));
|
|
2440
2749
|
}
|
|
2441
2750
|
get el() { return this; }
|
|
2442
2751
|
static get watchers() { return {
|
|
@@ -27,7 +27,7 @@ const App = class {
|
|
|
27
27
|
}
|
|
28
28
|
componentDidLoad() {
|
|
29
29
|
{
|
|
30
|
-
rIC(async () => {
|
|
30
|
+
this.rIC(async () => {
|
|
31
31
|
const isHybrid = ionicGlobal.isPlatform(window, 'hybrid');
|
|
32
32
|
if (!index.config.getBoolean('_testing')) {
|
|
33
33
|
Promise.resolve().then(function () { return require('./index-C534ULug.js'); }).then((module) => module.startTapClick(index.config));
|
|
@@ -65,6 +65,11 @@ const App = class {
|
|
|
65
65
|
});
|
|
66
66
|
}
|
|
67
67
|
}
|
|
68
|
+
disconnectedCallback() {
|
|
69
|
+
if (this.loadTimeout) {
|
|
70
|
+
clearTimeout(this.loadTimeout);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
68
73
|
/**
|
|
69
74
|
* Used to set focus on an element that uses `ion-focusable`.
|
|
70
75
|
* Do not use this if focusing the element as a result of a keyboard
|
|
@@ -81,9 +86,17 @@ const App = class {
|
|
|
81
86
|
this.focusVisible.setFocus(elements);
|
|
82
87
|
}
|
|
83
88
|
}
|
|
89
|
+
rIC(callback) {
|
|
90
|
+
if ('requestIdleCallback' in window) {
|
|
91
|
+
window.requestIdleCallback(callback);
|
|
92
|
+
}
|
|
93
|
+
else {
|
|
94
|
+
this.loadTimeout = setTimeout(callback, 32);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
84
97
|
render() {
|
|
85
98
|
const mode = ionicGlobal.getIonMode(this);
|
|
86
|
-
return (index.h(index.Host, { key: '
|
|
99
|
+
return (index.h(index.Host, { key: '77a7459d3e42b3715a5a7e1cf468e2ebc99e54bb', class: {
|
|
87
100
|
[mode]: true,
|
|
88
101
|
'ion-page': true,
|
|
89
102
|
'force-statusbar-padding': index.config.getBoolean('_forceStatusbarPadding'),
|
|
@@ -110,14 +123,6 @@ const needInputShims = () => {
|
|
|
110
123
|
}
|
|
111
124
|
return false;
|
|
112
125
|
};
|
|
113
|
-
const rIC = (callback) => {
|
|
114
|
-
if ('requestIdleCallback' in window) {
|
|
115
|
-
window.requestIdleCallback(callback);
|
|
116
|
-
}
|
|
117
|
-
else {
|
|
118
|
-
setTimeout(callback, 32);
|
|
119
|
-
}
|
|
120
|
-
};
|
|
121
126
|
App.style = appCss;
|
|
122
127
|
|
|
123
128
|
const buttonsIosCss = ".sc-ion-buttons-ios-h{display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center;-webkit-transform:translateZ(0);transform:translateZ(0);z-index:99}.sc-ion-buttons-ios-s ion-button{--padding-top:0;--padding-bottom:0;margin-left:0;margin-right:0;margin-top:0;margin-bottom:0}.sc-ion-buttons-ios-s ion-button{--padding-top:3px;--padding-bottom:3px;--padding-start:5px;--padding-end:5px;-webkit-margin-start:2px;margin-inline-start:2px;-webkit-margin-end:2px;margin-inline-end:2px;min-height:32px}.sc-ion-buttons-ios-s .button-has-icon-only{--padding-top:0;--padding-bottom:0}.sc-ion-buttons-ios-s ion-button:not(.button-round){--border-radius:4px}.sc-ion-buttons-ios-h.ion-color.sc-ion-buttons-ios-s .button,.ion-color .sc-ion-buttons-ios-h.sc-ion-buttons-ios-s .button{--color:initial;--border-color:initial;--background-focused:var(--ion-color-contrast)}.sc-ion-buttons-ios-h.ion-color.sc-ion-buttons-ios-s .button-solid,.ion-color .sc-ion-buttons-ios-h.sc-ion-buttons-ios-s .button-solid{--background:var(--ion-color-contrast);--background-focused:#000;--background-focused-opacity:.12;--background-activated:#000;--background-activated-opacity:.12;--background-hover:var(--ion-color-base);--background-hover-opacity:0.45;--color:var(--ion-color-base);--color-focused:var(--ion-color-base)}.sc-ion-buttons-ios-h.ion-color.sc-ion-buttons-ios-s .button-clear,.ion-color .sc-ion-buttons-ios-h.sc-ion-buttons-ios-s .button-clear{--color-activated:var(--ion-color-contrast);--color-focused:var(--ion-color-contrast)}.sc-ion-buttons-ios-h.ion-color.sc-ion-buttons-ios-s .button-outline,.ion-color .sc-ion-buttons-ios-h.sc-ion-buttons-ios-s .button-outline{--color-activated:var(--ion-color-base);--color-focused:var(--ion-color-contrast);--background-activated:var(--ion-color-contrast)}.sc-ion-buttons-ios-s .button-clear,.sc-ion-buttons-ios-s .button-outline{--background-activated:transparent;--background-focused:currentColor;--background-hover:transparent}.sc-ion-buttons-ios-s .button-solid:not(.ion-color){--background-focused:#000;--background-focused-opacity:.12;--background-activated:#000;--background-activated-opacity:.12}.sc-ion-buttons-ios-s ion-icon[slot=start]{margin-left:0;margin-right:0;margin-top:0;margin-bottom:0;-webkit-margin-end:0.3em;margin-inline-end:0.3em;font-size:1.41em;line-height:0.67}.sc-ion-buttons-ios-s ion-icon[slot=end]{margin-left:0;margin-right:0;margin-top:0;margin-bottom:0;-webkit-margin-start:0.4em;margin-inline-start:0.4em;font-size:1.41em;line-height:0.67}.sc-ion-buttons-ios-s ion-icon[slot=icon-only]{padding-left:0;padding-right:0;padding-top:0;padding-bottom:0;margin-left:0;margin-right:0;margin-top:0;margin-bottom:0;font-size:1.65em;line-height:0.67}";
|
|
@@ -277,6 +282,10 @@ const Content = class {
|
|
|
277
282
|
this.tabsElement = null;
|
|
278
283
|
this.tabsLoadCallback = undefined;
|
|
279
284
|
}
|
|
285
|
+
if (this.resizeTimeout) {
|
|
286
|
+
clearTimeout(this.resizeTimeout);
|
|
287
|
+
this.resizeTimeout = null;
|
|
288
|
+
}
|
|
280
289
|
}
|
|
281
290
|
/**
|
|
282
291
|
* Rotating certain devices can update
|
|
@@ -515,7 +524,7 @@ const Content = class {
|
|
|
515
524
|
const forceOverscroll = this.shouldForceOverscroll();
|
|
516
525
|
const transitionShadow = mode === 'ios';
|
|
517
526
|
this.resize();
|
|
518
|
-
return (index.h(index.Host, Object.assign({ key: '
|
|
527
|
+
return (index.h(index.Host, Object.assign({ key: '287f5bb78888b0f66394a35ba2a3ad636d8f3412', role: isMainContent ? 'main' : undefined, class: theme.createColorClasses(this.color, {
|
|
519
528
|
[mode]: true,
|
|
520
529
|
'content-sizing': theme.hostContext('ion-popover', this.el),
|
|
521
530
|
overscroll: forceOverscroll,
|
|
@@ -523,12 +532,12 @@ const Content = class {
|
|
|
523
532
|
}), style: {
|
|
524
533
|
'--offset-top': `${this.cTop}px`,
|
|
525
534
|
'--offset-bottom': `${this.cBottom}px`,
|
|
526
|
-
} }, inheritedAttributes), index.h("div", { key: '
|
|
535
|
+
} }, inheritedAttributes), index.h("div", { key: '2e70e5e0ab4209478ea711a630058fa0e83af7f8', ref: (el) => (this.backgroundContentEl = el), id: "background-content", part: "background" }), fixedSlotPlacement === 'before' ? index.h("slot", { name: "fixed" }) : null, index.h("div", { key: '018a83406173ec7f7725f09b4bd1c0d964874ee4', class: {
|
|
527
536
|
'inner-scroll': true,
|
|
528
537
|
'scroll-x': scrollX,
|
|
529
538
|
'scroll-y': scrollY,
|
|
530
539
|
overscroll: (scrollX || scrollY) && forceOverscroll,
|
|
531
|
-
}, ref: (scrollEl) => (this.scrollEl = scrollEl), onScroll: this.scrollEvents ? (ev) => this.onScroll(ev) : undefined, part: "scroll" }, index.h("slot", { key: '
|
|
540
|
+
}, ref: (scrollEl) => (this.scrollEl = scrollEl), onScroll: this.scrollEvents ? (ev) => this.onScroll(ev) : undefined, part: "scroll" }, index.h("slot", { key: '6f028eeb7c9dc7e1b82a8e549e1dd8aaf1d15fca' })), transitionShadow ? (index.h("div", { class: "transition-effect" }, index.h("div", { class: "transition-cover" }), index.h("div", { class: "transition-shadow" }))) : null, fixedSlotPlacement === 'after' ? index.h("slot", { name: "fixed" }) : null));
|
|
532
541
|
}
|
|
533
542
|
get el() { return index.getElement(this); }
|
|
534
543
|
};
|
|
@@ -200,7 +200,7 @@ const Checkbox = class {
|
|
|
200
200
|
helpers.renderHiddenInput(true, el, name, checked ? value : '', disabled);
|
|
201
201
|
// The host element must have a checkbox role to ensure proper VoiceOver
|
|
202
202
|
// support in Safari for accessibility.
|
|
203
|
-
return (index.h(index.Host, { key: '
|
|
203
|
+
return (index.h(index.Host, { key: 'fca2e80987d5e2e7f9138eeac3314d883ea1252b', role: "checkbox", "aria-checked": indeterminate ? 'mixed' : `${checked}`, "aria-describedby": this.hintTextId, "aria-invalid": this.isInvalid ? 'true' : undefined, "aria-labelledby": hasLabelContent ? this.inputLabelId : null, "aria-label": inheritedAttributes['aria-label'] || null, "aria-disabled": disabled ? 'true' : null, "aria-required": required ? 'true' : undefined, tabindex: disabled ? undefined : 0, onKeyDown: this.onKeyDown, onFocus: this.onFocus, onBlur: this.onBlur, onClick: this.onClick, class: theme.createColorClasses(color, {
|
|
204
204
|
[mode]: true,
|
|
205
205
|
'in-item': theme.hostContext('ion-item', el),
|
|
206
206
|
'checkbox-checked': checked,
|
|
@@ -210,10 +210,10 @@ const Checkbox = class {
|
|
|
210
210
|
[`checkbox-justify-${justify}`]: justify !== undefined,
|
|
211
211
|
[`checkbox-alignment-${alignment}`]: alignment !== undefined,
|
|
212
212
|
[`checkbox-label-placement-${labelPlacement}`]: true,
|
|
213
|
-
}) }, index.h("label", { key: '
|
|
213
|
+
}) }, index.h("label", { key: '5cf50b6abdb9a3ae1f846f18bd8d5345de0ea2e9', class: "checkbox-wrapper", htmlFor: inputId }, index.h("input", Object.assign({ key: 'b8c3c6b01f65ff1b723c0de4b5d6f1b62940f481', type: "checkbox", checked: checked ? true : undefined, disabled: disabled, id: inputId, onChange: this.toggleChecked, required: required }, inheritedAttributes)), index.h("div", { key: '7b29b18b97b8151f454760d73aca1543c8325e41', class: {
|
|
214
214
|
'label-text-wrapper': true,
|
|
215
215
|
'label-text-wrapper-hidden': !hasLabelContent,
|
|
216
|
-
}, part: "label", id: this.inputLabelId, onClick: this.onDivLabelClick }, index.h("slot", { key: '
|
|
216
|
+
}, part: "label", id: this.inputLabelId, onClick: this.onDivLabelClick }, index.h("slot", { key: 'ffbce8010274a68b8e67f9c0f19ec012944df484', onSlotchange: () => index.forceUpdate(this) }), this.renderHintText()), index.h("div", { key: '8e21fb89c72fbd52df70fa1916367ab5a543f281', class: "native-wrapper" }, index.h("svg", { key: 'c2519ff1a5c7f69e03ab26197ccfa8718b0951c6', class: "checkbox-icon", viewBox: "0 0 24 24", part: "container", "aria-hidden": "true" }, path)))));
|
|
217
217
|
}
|
|
218
218
|
getSVGPath(mode, indeterminate) {
|
|
219
219
|
let path = indeterminate ? (index.h("path", { d: "M6 12L18 12", part: "mark" })) : (index.h("path", { d: "M5.9,12.5l3.8,3.8l8.8-8.8", part: "mark" }));
|
|
@@ -1085,6 +1085,9 @@ const Datetime = class {
|
|
|
1085
1085
|
this.clearFocusVisible();
|
|
1086
1086
|
this.clearFocusVisible = undefined;
|
|
1087
1087
|
}
|
|
1088
|
+
if (this.loadTimeout) {
|
|
1089
|
+
clearTimeout(this.loadTimeout);
|
|
1090
|
+
}
|
|
1088
1091
|
}
|
|
1089
1092
|
initializeListeners() {
|
|
1090
1093
|
this.initializeCalendarListener();
|
|
@@ -1133,7 +1136,7 @@ const Datetime = class {
|
|
|
1133
1136
|
*
|
|
1134
1137
|
* We schedule this after everything has had a chance to run.
|
|
1135
1138
|
*/
|
|
1136
|
-
setTimeout(() => {
|
|
1139
|
+
this.loadTimeout = setTimeout(() => {
|
|
1137
1140
|
this.ensureReadyIfVisible();
|
|
1138
1141
|
}, 100);
|
|
1139
1142
|
/**
|
|
@@ -1891,7 +1894,7 @@ const Datetime = class {
|
|
|
1891
1894
|
const hasDatePresentation = presentation === 'date' || presentation === 'date-time' || presentation === 'time-date';
|
|
1892
1895
|
const hasWheelVariant = hasDatePresentation && preferWheel;
|
|
1893
1896
|
helpers.renderHiddenInput(true, el, name, data.formatValue(value), disabled);
|
|
1894
|
-
return (index.h(index.Host, { key: '
|
|
1897
|
+
return (index.h(index.Host, { key: 'b81c3531f4654be3f6948df5f790c0f6ab488000', "aria-disabled": disabled ? 'true' : null, onFocus: this.onFocus, onBlur: this.onBlur, class: Object.assign({}, theme.createColorClasses(color, {
|
|
1895
1898
|
[mode]: true,
|
|
1896
1899
|
['datetime-readonly']: readonly,
|
|
1897
1900
|
['datetime-disabled']: disabled,
|
|
@@ -1901,7 +1904,7 @@ const Datetime = class {
|
|
|
1901
1904
|
[`datetime-size-${size}`]: true,
|
|
1902
1905
|
[`datetime-prefer-wheel`]: hasWheelVariant,
|
|
1903
1906
|
[`datetime-grid`]: isGridStyle,
|
|
1904
|
-
})) }, index.h("div", { key: '
|
|
1907
|
+
})) }, index.h("div", { key: 'f7f39f8e56146186210d0ab70ae95e829573e549', class: "intersection-tracker", ref: (el) => (this.intersectionTrackerRef = el) }), this.renderDatetime(mode)));
|
|
1905
1908
|
}
|
|
1906
1909
|
get el() { return index.getElement(this); }
|
|
1907
1910
|
static get watchers() { return {
|