@ionic/core 9.0.1-dev.11787248963.10a00c73 → 9.0.1-dev.11787589191.1e183b55

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (94) hide show
  1. package/components/index.js +1 -1
  2. package/components/ion-action-sheet.js +1 -1
  3. package/components/ion-alert.js +1 -1
  4. package/components/ion-datetime.js +1 -1
  5. package/components/ion-item-sliding.js +1 -1
  6. package/components/ion-loading.js +1 -1
  7. package/components/ion-menu.js +1 -1
  8. package/components/ion-modal.js +1 -1
  9. package/components/ion-popover.js +1 -1
  10. package/components/ion-segment-button.js +1 -1
  11. package/components/ion-select-modal.js +1 -1
  12. package/components/ion-select-popover.js +1 -1
  13. package/components/ion-select.js +1 -1
  14. package/components/ion-toast.js +1 -1
  15. package/components/p-BPnXVGaS.js +4 -0
  16. package/components/p-BQAiulS1.js +4 -0
  17. package/components/p-Bh2ta0iG.js +4 -0
  18. package/components/{p-CaiZOhfC.js → p-BnUOVmKh.js} +1 -1
  19. package/components/{p-Bnc0m4SW.js → p-D1OCo42s.js} +1 -1
  20. package/components/p-DD57rSP_.js +4 -0
  21. package/components/p-DnXLaaf7.js +4 -0
  22. package/dist/cjs/index.cjs.js +1 -1
  23. package/dist/cjs/ion-action-sheet.cjs.entry.js +35 -20
  24. package/dist/cjs/ion-alert.cjs.entry.js +20 -12
  25. package/dist/cjs/ion-datetime.cjs.entry.js +1 -1
  26. package/dist/cjs/ion-item-option_3.cjs.entry.js +11 -9
  27. package/dist/cjs/ion-loading.cjs.entry.js +7 -3
  28. package/dist/cjs/ion-menu_3.cjs.entry.js +1 -1
  29. package/dist/cjs/ion-modal.cjs.entry.js +75 -22
  30. package/dist/cjs/ion-popover.cjs.entry.js +13 -3
  31. package/dist/cjs/ion-segment_2.cjs.entry.js +7 -11
  32. package/dist/cjs/ion-select-modal.cjs.entry.js +1 -1
  33. package/dist/cjs/ion-select_3.cjs.entry.js +1 -1
  34. package/dist/cjs/ion-toast.cjs.entry.js +1 -1
  35. package/dist/cjs/{overlays-Bg0auTQa.js → overlays-B5JeC8OQ.js} +52 -29
  36. package/dist/collection/components/action-sheet/action-sheet.js +35 -20
  37. package/dist/collection/components/alert/alert.js +20 -12
  38. package/dist/collection/components/item-sliding/item-sliding.js +12 -10
  39. package/dist/collection/components/loading/loading.js +7 -3
  40. package/dist/collection/components/modal/modal.js +75 -22
  41. package/dist/collection/components/popover/popover.js +13 -3
  42. package/dist/collection/components/segment-button/segment-button.js +7 -11
  43. package/dist/collection/utils/overlays.js +51 -29
  44. package/dist/docs.json +1 -1
  45. package/dist/esm/index.js +1 -1
  46. package/dist/esm/ion-action-sheet.entry.js +35 -20
  47. package/dist/esm/ion-alert.entry.js +20 -12
  48. package/dist/esm/ion-datetime.entry.js +1 -1
  49. package/dist/esm/ion-item-option_3.entry.js +12 -10
  50. package/dist/esm/ion-loading.entry.js +7 -3
  51. package/dist/esm/ion-menu_3.entry.js +1 -1
  52. package/dist/esm/ion-modal.entry.js +75 -22
  53. package/dist/esm/ion-popover.entry.js +13 -3
  54. package/dist/esm/ion-segment_2.entry.js +7 -11
  55. package/dist/esm/ion-select-modal.entry.js +1 -1
  56. package/dist/esm/ion-select_3.entry.js +1 -1
  57. package/dist/esm/ion-toast.entry.js +1 -1
  58. package/dist/esm/{overlays-BpnIFlXI.js → overlays-CefdMZgF.js} +52 -30
  59. package/dist/ionic/index.esm.js +1 -1
  60. package/dist/ionic/ionic.esm.js +1 -1
  61. package/dist/ionic/p-36abc1ee.entry.js +4 -0
  62. package/dist/ionic/{p-873a315a.entry.js → p-408973f4.entry.js} +1 -1
  63. package/dist/ionic/{p-4437015c.entry.js → p-46a938a9.entry.js} +1 -1
  64. package/dist/ionic/p-47626333.entry.js +4 -0
  65. package/dist/ionic/p-8f464a8f.entry.js +4 -0
  66. package/dist/ionic/p-9455207b.entry.js +4 -0
  67. package/dist/ionic/p-DLLCmV-y.js +4 -0
  68. package/dist/ionic/{p-05800a02.entry.js → p-a2fa2de2.entry.js} +1 -1
  69. package/dist/ionic/p-a53b0908.entry.js +4 -0
  70. package/dist/ionic/{p-75887ee0.entry.js → p-b875a59e.entry.js} +1 -1
  71. package/dist/ionic/p-f3b671aa.entry.js +4 -0
  72. package/dist/ionic/p-f521b13c.entry.js +4 -0
  73. package/dist/ionic/{p-49b9d405.entry.js → p-f8713b2c.entry.js} +1 -1
  74. package/dist/types/components/action-sheet/action-sheet.d.ts +10 -0
  75. package/dist/types/components/alert/alert.d.ts +7 -0
  76. package/dist/types/components/modal/modal.d.ts +8 -0
  77. package/dist/types/utils/overlays.d.ts +9 -0
  78. package/hydrate/index.js +214 -104
  79. package/hydrate/index.mjs +214 -104
  80. package/package.json +1 -1
  81. package/components/p-Bg4OwDwb.js +0 -4
  82. package/components/p-CQAjyETU.js +0 -4
  83. package/components/p-DqAI6tg7.js +0 -4
  84. package/components/p-DrehWDfv.js +0 -4
  85. package/components/p-eFI3mtEX.js +0 -4
  86. package/dist/collection/utils/test/late-props/late-props.js +0 -69
  87. package/dist/ionic/p-34b9379b.entry.js +0 -4
  88. package/dist/ionic/p-48c859fe.entry.js +0 -4
  89. package/dist/ionic/p-5b906fd6.entry.js +0 -4
  90. package/dist/ionic/p-68507e70.entry.js +0 -4
  91. package/dist/ionic/p-886d9e66.entry.js +0 -4
  92. package/dist/ionic/p-DdhHqKj-.js +0 -4
  93. package/dist/ionic/p-b7a11b58.entry.js +0 -4
  94. package/dist/ionic/p-f7dd1ed9.entry.js +0 -4
package/hydrate/index.js CHANGED
@@ -7961,6 +7961,15 @@ const activeAnimations = new WeakMap();
7961
7961
  const isBackdropAlwaysBlocking = (el) => {
7962
7962
  return el.showBackdrop !== false && !((el.backdropBreakpoint ?? 0) > 0);
7963
7963
  };
7964
+ /**
7965
+ * Whether the overlay takes the app root out of the accessibility tree and
7966
+ * blocks body scroll while presented. Toasts never do, modal and popover can
7967
+ * opt out with `focusTrap={false}`, and a backdrop that does not block
7968
+ * (`showBackdrop={false}`, or a `backdropBreakpoint` above 0) is excluded.
7969
+ */
7970
+ const locksAppRoot = (el) => {
7971
+ return el.tagName !== 'ION-TOAST' && el.focusTrap !== false && isBackdropAlwaysBlocking(el);
7972
+ };
7964
7973
  const createController = (tagName) => {
7965
7974
  return {
7966
7975
  create(options) {
@@ -8329,6 +8338,13 @@ const getPresentedOverlay = (doc, overlayTag, id) => {
8329
8338
  // Otherwise, return the last overlay with the given id
8330
8339
  return (id === undefined ? overlays : overlays.filter((o) => o.id === id)).slice(-1)[0];
8331
8340
  };
8341
+ /**
8342
+ * The element an app nests its views under. Overlays hide this rather than the
8343
+ * whole root, so the overlay itself (a sibling) stays reachable.
8344
+ */
8345
+ const getViewContainer = () => {
8346
+ return getAppRoot(document).querySelector('ion-router-outlet, #ion-view-container-root');
8347
+ };
8332
8348
  /**
8333
8349
  * When an overlay is presented, the main
8334
8350
  * focus is the overlay not the page content.
@@ -8352,8 +8368,7 @@ const getPresentedOverlay = (doc, overlayTag, id) => {
8352
8368
  * for main content.
8353
8369
  */
8354
8370
  const setRootAriaHidden = (hidden = false) => {
8355
- const root = getAppRoot(document);
8356
- const viewContainer = root.querySelector('ion-router-outlet, #ion-view-container-root');
8371
+ const viewContainer = getViewContainer();
8357
8372
  if (!viewContainer) {
8358
8373
  return;
8359
8374
  }
@@ -8378,15 +8393,40 @@ const cleanupRootFocusTrapAccessibility = () => {
8378
8393
  return;
8379
8394
  }
8380
8395
  const remainingOverlays = getPresentedOverlays(document);
8381
- const hasRemainingLocking = remainingOverlays.some((o) => {
8382
- const el = o;
8383
- return el.tagName !== 'ION-TOAST' && el.focusTrap !== false && isBackdropAlwaysBlocking(el);
8384
- });
8396
+ const hasRemainingLocking = remainingOverlays.some((o) => locksAppRoot(o));
8385
8397
  if (!hasRemainingLocking) {
8386
8398
  setRootAriaHidden(false);
8387
8399
  document.body.classList.remove(BACKDROP_NO_SCROLL);
8388
8400
  }
8389
8401
  };
8402
+ /**
8403
+ * Shared by `present()` and the restore below, which have to stay in lockstep.
8404
+ */
8405
+ const applyRootLock = (el) => {
8406
+ // Hiding the container the overlay now sits in would hide the overlay too.
8407
+ if (!getViewContainer()?.contains(el)) {
8408
+ setRootAriaHidden(true);
8409
+ }
8410
+ document.body.classList.add(BACKDROP_NO_SCROLL);
8411
+ };
8412
+ /**
8413
+ * Re-applies the root lock that `cleanupRootFocusTrapAccessibility()` released.
8414
+ * Call from `connectedCallback` when the overlay is still presented.
8415
+ *
8416
+ * A synchronous move keeps the overlay connected, so the lock survives. A
8417
+ * detach with a re-insert in a later task releases it, which is the shape a
8418
+ * framework produces when it takes a subtree out and puts it back.
8419
+ */
8420
+ const restoreRootFocusTrapAccessibility = (overlayEl) => {
8421
+ if (typeof document === 'undefined') {
8422
+ return;
8423
+ }
8424
+ const el = overlayEl;
8425
+ if (!locksAppRoot(el)) {
8426
+ return;
8427
+ }
8428
+ applyRootLock(el);
8429
+ };
8390
8430
  const present = async (overlay, name, iosEnterAnimation, mdEnterAnimation, opts) => {
8391
8431
  if (overlay.presented) {
8392
8432
  return;
@@ -8403,15 +8443,7 @@ const present = async (overlay, name, iosEnterAnimation, mdEnterAnimation, opts)
8403
8443
  restoreElementFocus(overlay.el);
8404
8444
  }
8405
8445
  /**
8406
- * Due to accessibility guidelines, toasts do not have
8407
- * focus traps.
8408
- *
8409
- * All other overlays should have focus traps to prevent
8410
- * the keyboard focus from leaving the overlay unless
8411
- * developers explicitly opt out (for example, sheet
8412
- * modals that should permit background interaction).
8413
- *
8414
- * Note: Some apps move inline overlays to a specific container
8446
+ * Some apps move inline overlays to a specific container
8415
8447
  * during the willPresent lifecycle (e.g., React portals via
8416
8448
  * onWillPresent). Defer applying aria-hidden/inert to the app
8417
8449
  * root until after willPresent so we can detect where the
@@ -8420,18 +8452,11 @@ const present = async (overlay, name, iosEnterAnimation, mdEnterAnimation, opts)
8420
8452
  * to avoid disabling the overlay.
8421
8453
  */
8422
8454
  const overlayEl = overlay.el;
8423
- const shouldTrapFocus = overlayEl.tagName !== 'ION-TOAST' && overlayEl.focusTrap !== false;
8424
- const shouldLockRoot = shouldTrapFocus && isBackdropAlwaysBlocking(overlayEl);
8455
+ const shouldLockRoot = locksAppRoot(overlayEl);
8425
8456
  overlay.presented = true;
8426
8457
  overlay.willPresent.emit();
8427
8458
  if (shouldLockRoot) {
8428
- const root = getAppRoot(document);
8429
- const viewContainer = root.querySelector('ion-router-outlet, #ion-view-container-root');
8430
- const overlayInsideViewContainer = viewContainer ? viewContainer.contains(overlayEl) : false;
8431
- if (!overlayInsideViewContainer) {
8432
- setRootAriaHidden(true);
8433
- }
8434
- document.body.classList.add(BACKDROP_NO_SCROLL);
8459
+ applyRootLock(overlayEl);
8435
8460
  }
8436
8461
  overlay.willPresentShorthand?.emit();
8437
8462
  const mode = getIonMode$1(overlay);
@@ -8557,12 +8582,9 @@ const dismiss = async (overlay, data, role, name, iosLeaveAnimation, mdLeaveAnim
8557
8582
  * from the root element when the last focus-trapping overlay
8558
8583
  * is dismissed.
8559
8584
  */
8560
- const overlaysLockingRoot = presentedOverlays.filter((o) => {
8561
- const el = o;
8562
- return el.tagName !== 'ION-TOAST' && el.focusTrap !== false && isBackdropAlwaysBlocking(el);
8563
- });
8585
+ const overlaysLockingRoot = presentedOverlays.filter((o) => locksAppRoot(o));
8564
8586
  const overlayEl = overlay.el;
8565
- const locksRoot = overlayEl.tagName !== 'ION-TOAST' && overlayEl.focusTrap !== false && isBackdropAlwaysBlocking(overlayEl);
8587
+ const locksRoot = locksAppRoot(overlayEl);
8566
8588
  /**
8567
8589
  * If this is the last visible overlay that is trapping focus
8568
8590
  * then we want to re-add the root to the accessibility tree.
@@ -10558,6 +10580,13 @@ class ActionSheet {
10558
10580
  connectedCallback() {
10559
10581
  prepareOverlay(this.el);
10560
10582
  this.triggerChanged();
10583
+ // `componentDidLoad` only fires once per instance, so a reconnect has to
10584
+ // rebuild the gesture its disconnect destroyed.
10585
+ this.setupButtonActiveGesture();
10586
+ // Re-apply the root lock if moved without dismiss() being called
10587
+ if (this.presented) {
10588
+ restoreRootFocusTrapAccessibility(this.el);
10589
+ }
10561
10590
  }
10562
10591
  disconnectedCallback() {
10563
10592
  if (this.gesture) {
@@ -10577,24 +10606,32 @@ class ActionSheet {
10577
10606
  // Initialize activeRadioId for radio buttons
10578
10607
  this.buttonsChanged();
10579
10608
  }
10580
- componentDidLoad() {
10581
- /**
10582
- * Only create gesture if:
10583
- * 1. A gesture does not already exist
10584
- * 2. App is running in iOS mode
10585
- * 3. A wrapper ref exists
10586
- * 4. A group ref exists
10587
- */
10609
+ /**
10610
+ * Only create gesture if:
10611
+ * 1. A gesture does not already exist
10612
+ * 2. App is running in iOS mode
10613
+ * 3. A wrapper ref exists
10614
+ * 4. A group ref exists
10615
+ * 5. The host is still connected, since a reconnect can schedule this and
10616
+ * disconnect again before the task runs
10617
+ */
10618
+ setupButtonActiveGesture() {
10588
10619
  const { groupEl, wrapperEl } = this;
10589
- if (!this.gesture && getIonMode$1(this) === 'ios' && wrapperEl && groupEl) {
10590
- readTask(() => {
10591
- const isScrollable = groupEl.scrollHeight > groupEl.clientHeight;
10592
- if (!isScrollable) {
10593
- this.gesture = createButtonActiveGesture(wrapperEl, (refEl) => refEl.classList.contains('action-sheet-button'));
10594
- this.gesture.enable(true);
10595
- }
10596
- });
10620
+ if (getIonMode$1(this) !== 'ios' || !wrapperEl || !groupEl) {
10621
+ return;
10597
10622
  }
10623
+ readTask(() => {
10624
+ // Two calls before the first flushes would otherwise both create a
10625
+ // gesture, orphaning the first with its listeners still bound.
10626
+ if (this.gesture || !this.el.isConnected || groupEl.scrollHeight > groupEl.clientHeight) {
10627
+ return;
10628
+ }
10629
+ this.gesture = createButtonActiveGesture(wrapperEl, (refEl) => refEl.classList.contains('action-sheet-button'));
10630
+ this.gesture.enable(true);
10631
+ });
10632
+ }
10633
+ componentDidLoad() {
10634
+ this.setupButtonActiveGesture();
10598
10635
  /**
10599
10636
  * If action sheet was rendered with isOpen="true"
10600
10637
  * then we should open action sheet immediately.
@@ -10687,17 +10724,17 @@ class ActionSheet {
10687
10724
  const cancelButton = allButtons.find((b) => b.role === 'cancel');
10688
10725
  const buttons = allButtons.filter((b) => b.role !== 'cancel');
10689
10726
  const headerID = `action-sheet-${overlayIndex}-header`;
10690
- return (hAsync(Host, { key: '7685831da9a78b73473246a2cea95cefa79a53c3', role: "dialog", "aria-modal": "true", "aria-labelledby": header !== undefined ? headerID : null, tabindex: "-1", ...htmlAttributes, style: {
10727
+ return (hAsync(Host, { key: '326d4af08e832e10e1882fbbf67dba3221095865', role: "dialog", "aria-modal": "true", "aria-labelledby": header !== undefined ? headerID : null, tabindex: "-1", ...htmlAttributes, style: {
10691
10728
  zIndex: `${20000 + this.overlayIndex}`,
10692
10729
  }, class: {
10693
10730
  [mode]: true,
10694
10731
  ...getClassMap(this.cssClass),
10695
10732
  'overlay-hidden': true,
10696
10733
  'action-sheet-translucent': this.translucent,
10697
- }, onIonActionSheetWillDismiss: this.dispatchCancelHandler, onIonBackdropTap: this.onBackdropTap }, hAsync("ion-backdrop", { key: 'c70f00e401cac99b89412d1adb867f35bc855d57', tappable: this.backdropDismiss }), hAsync("div", { key: '3332893ce3098f1435875480b1269b2821d41660', tabindex: "0", "aria-hidden": "true" }), hAsync("div", { key: 'eb406b0a9e303d6f94c5c7aa99c6f4c089bfbd41', class: "action-sheet-wrapper ion-overlay-wrapper", ref: (el) => (this.wrapperEl = el) }, hAsync("div", { key: '92ec855379f10e1e0bfce6ff68b45d3cda0c137c', class: "action-sheet-container" }, hAsync("div", { key: 'bc88a396d75396f574961471bf7e6c4edb513353', class: "action-sheet-group", ref: (el) => (this.groupEl = el), role: hasRadioButtons ? 'radiogroup' : undefined }, header !== undefined && (hAsync("div", { key: '33329e0193818888bdcaa443ff5ea301802e0787', id: headerID, class: {
10734
+ }, onIonActionSheetWillDismiss: this.dispatchCancelHandler, onIonBackdropTap: this.onBackdropTap }, hAsync("ion-backdrop", { key: '8cb6a0d763a60f61f563a1b7d572ad5e9afd6e40', tappable: this.backdropDismiss }), hAsync("div", { key: 'f8b8da0f52ae674a5e313632ee3d049bed3f813f', tabindex: "0", "aria-hidden": "true" }), hAsync("div", { key: '53cf0d1b01a2cda23c27fc8b96edaccf892e61b3', class: "action-sheet-wrapper ion-overlay-wrapper", ref: (el) => (this.wrapperEl = el) }, hAsync("div", { key: '6df261ff946c3b4496535df04cc70e2cfa3cc2da', class: "action-sheet-container" }, hAsync("div", { key: '6f6f2846d19baa738651b990d8613aa0ecac9479', class: "action-sheet-group", ref: (el) => (this.groupEl = el), role: hasRadioButtons ? 'radiogroup' : undefined }, header !== undefined && (hAsync("div", { key: '3f36df8eaaedb5e61a41bbf44134f25f263d1e7e', id: headerID, class: {
10698
10735
  'action-sheet-title': true,
10699
10736
  'action-sheet-has-sub-title': this.subHeader !== undefined,
10700
- } }, header, this.subHeader && hAsync("div", { key: '92ac5a9217a12b7417f7aca9c4fdb7bf6b051364', class: "action-sheet-sub-title" }, this.subHeader))), this.renderActionSheetButtons(buttons)), cancelButton && (hAsync("div", { key: '020463b830fa48fc3ae647ea64f2aaa4d0969305', class: "action-sheet-group action-sheet-group-cancel" }, hAsync("button", { key: 'cefa9c70a2233f6652a81b1a2eae6e717712144d', ...cancelButton.htmlAttributes, type: "button", class: buttonClass$2(cancelButton), onClick: () => this.buttonClick(cancelButton) }, hAsync("span", { key: '56d7e2f8bfb3644e4476895164d334445fda9b2f', class: "action-sheet-button-inner" }, cancelButton.icon && (hAsync("ion-icon", { key: '6a4a49254ec5cd96f4e0dce9447f90d8cac81913', icon: cancelButton.icon, "aria-hidden": "true", lazy: false, class: "action-sheet-icon" })), cancelButton.text), mode === 'md' && hAsync("ion-ripple-effect", { key: '7d3c6e8d70b0922ea0f75520856285ce1005c891' })))))), hAsync("div", { key: '958fc43e603c6a7f5d1e649d3326fce0f163b5d0', tabindex: "0", "aria-hidden": "true" })));
10737
+ } }, header, this.subHeader && hAsync("div", { key: 'a6b2bf51123eaae4ed873e65c00c426e9c511ac0', class: "action-sheet-sub-title" }, this.subHeader))), this.renderActionSheetButtons(buttons)), cancelButton && (hAsync("div", { key: '4dd96553327003b899bc03a815a06a7cce35db29', class: "action-sheet-group action-sheet-group-cancel" }, hAsync("button", { key: 'a1928040a3d20f2e50230b7d6003467d2916f5b4', ...cancelButton.htmlAttributes, type: "button", class: buttonClass$2(cancelButton), onClick: () => this.buttonClick(cancelButton) }, hAsync("span", { key: '2fa9d0e4072f1fd55f08048966495a627a14ef8f', class: "action-sheet-button-inner" }, cancelButton.icon && (hAsync("ion-icon", { key: 'c2eec9967cb9f0b75d4428bb548674199089203c', icon: cancelButton.icon, "aria-hidden": "true", lazy: false, class: "action-sheet-icon" })), cancelButton.text), mode === 'md' && hAsync("ion-ripple-effect", { key: '09e71f28d77ae16481b832863f49b3f7d7dd76f9' })))))), hAsync("div", { key: '386fbe5ca2a88e9b52bd3b9d8f3daddbc630e6f6', tabindex: "0", "aria-hidden": "true" })));
10701
10738
  }
10702
10739
  get el() { return getElement(this); }
10703
10740
  static get watchers() { return {
@@ -11079,10 +11116,15 @@ class Alert {
11079
11116
  this.triggerChanged();
11080
11117
  /**
11081
11118
  * If the alert was previously connected and is being reattached, the
11082
- * ResizeObserver was disconnected. componentDidLoad only fires once per
11083
- * instance, so re-establish the observer here on reconnect.
11119
+ * `ResizeObserver` and the button gesture were torn down. `componentDidLoad`
11120
+ * only fires once per instance, so re-establish both here on reconnect.
11084
11121
  */
11085
11122
  this.setupButtonGroupResizeObserver();
11123
+ this.setupButtonActiveGesture();
11124
+ // Re-apply the root lock if moved without dismiss() being called
11125
+ if (this.presented) {
11126
+ restoreRootFocusTrapAccessibility(this.el);
11127
+ }
11086
11128
  }
11087
11129
  componentWillLoad() {
11088
11130
  if (!this.htmlAttributes?.id) {
@@ -11104,17 +11146,20 @@ class Alert {
11104
11146
  this.buttonGroupResizeObserver?.disconnect();
11105
11147
  this.buttonGroupResizeObserver = undefined;
11106
11148
  }
11107
- componentDidLoad() {
11108
- /**
11109
- * Only create gesture if:
11110
- * 1. A gesture does not already exist
11111
- * 2. App is running in iOS mode
11112
- * 3. A wrapper ref exists
11113
- */
11149
+ /**
11150
+ * Only create gesture if:
11151
+ * 1. A gesture does not already exist
11152
+ * 2. App is running in iOS mode
11153
+ * 3. A wrapper ref exists
11154
+ */
11155
+ setupButtonActiveGesture() {
11114
11156
  if (!this.gesture && getIonMode$1(this) === 'ios' && this.wrapperEl) {
11115
11157
  this.gesture = createButtonActiveGesture(this.wrapperEl, (refEl) => refEl.classList.contains('alert-button'));
11116
11158
  this.gesture.enable(true);
11117
11159
  }
11160
+ }
11161
+ componentDidLoad() {
11162
+ this.setupButtonActiveGesture();
11118
11163
  this.setupButtonGroupResizeObserver();
11119
11164
  /**
11120
11165
  * If alert was rendered with isOpen="true"
@@ -11435,14 +11480,14 @@ class Alert {
11435
11480
  * If neither are defined, do not set aria-labelledby.
11436
11481
  */
11437
11482
  const ariaLabelledBy = header && subHeader ? `${hdrId} ${subHdrId}` : header ? hdrId : subHeader ? subHdrId : null;
11438
- return (hAsync(Host, { key: '022f3463b8e6c52064b90ec304c524847c3d5ad3', tabindex: "-1", style: {
11483
+ return (hAsync(Host, { key: '083b5250dc4c76e85240e0225abcb7ca2b66de2f', tabindex: "-1", style: {
11439
11484
  zIndex: `${20000 + overlayIndex}`,
11440
11485
  }, class: {
11441
11486
  ...getClassMap(this.cssClass),
11442
11487
  [mode]: true,
11443
11488
  'overlay-hidden': true,
11444
11489
  'alert-translucent': this.translucent,
11445
- }, onIonAlertWillDismiss: this.dispatchCancelHandler, onIonBackdropTap: this.onBackdropTap }, hAsync("ion-backdrop", { key: 'c3cd05738bc2834f54707edeb2fae06ec10d6fd2', tappable: this.backdropDismiss }), hAsync("div", { key: 'b44fadd9ba7ddf073854c5035538d11ae8e66bc2', tabindex: "0", "aria-hidden": "true" }), hAsync("div", { key: 'fafea048141a6c7957e62aef31faa8041dd610c1', class: "alert-wrapper ion-overlay-wrapper", role: role, "aria-modal": "true", "aria-labelledby": ariaLabelledBy, "aria-describedby": message !== undefined ? msgId : null, tabindex: "0", ref: (el) => (this.wrapperEl = el), ...htmlAttributes }, hAsync("div", { key: '3ad9d2d4b7cf425eab8293ddc12eff0fe8df1517', class: "alert-head" }, header && (hAsync("h2", { key: '7d9154f5ee595b7e4da6ecf3a20871f104c1256e', id: hdrId, class: "alert-title" }, header)), subHeader && !header && (hAsync("h2", { key: '1f891f38004be6964e9406b84dd580145c42516a', id: subHdrId, class: "alert-sub-title" }, subHeader)), subHeader && header && (hAsync("h3", { key: '2ab4d344ecb7e384e8f6d3d3e59ee5a1bbcc832c', id: subHdrId, class: "alert-sub-title" }, subHeader))), this.renderAlertMessage(msgId), this.renderAlertInputs(), this.renderAlertButtons()), hAsync("div", { key: '78a4ff09aa3aaafcd0dc2a42d036767d83b3cfa2', tabindex: "0", "aria-hidden": "true" })));
11490
+ }, onIonAlertWillDismiss: this.dispatchCancelHandler, onIonBackdropTap: this.onBackdropTap }, hAsync("ion-backdrop", { key: '65c92a956d998ae9016396dd2a29c42ab7376d0e', tappable: this.backdropDismiss }), hAsync("div", { key: 'f2288fa0b7ef9d0bf031c168fe78c48422cf91c8', tabindex: "0", "aria-hidden": "true" }), hAsync("div", { key: 'dbb109435c378f77c6b0231e58756f8a0467732d', class: "alert-wrapper ion-overlay-wrapper", role: role, "aria-modal": "true", "aria-labelledby": ariaLabelledBy, "aria-describedby": message !== undefined ? msgId : null, tabindex: "0", ref: (el) => (this.wrapperEl = el), ...htmlAttributes }, hAsync("div", { key: '075597f94719673cf1f894a8566e1036849afa75', class: "alert-head" }, header && (hAsync("h2", { key: 'f96f4b1db8473c62040beed6e96108c733978d73', id: hdrId, class: "alert-title" }, header)), subHeader && !header && (hAsync("h2", { key: 'dbd824ef19a07bddde4eb928f11de7c7cadf98b8', id: subHdrId, class: "alert-sub-title" }, subHeader)), subHeader && header && (hAsync("h3", { key: '4774fa13700dd23aec7930492acae80de3bdf5d1', id: subHdrId, class: "alert-sub-title" }, subHeader))), this.renderAlertMessage(msgId), this.renderAlertInputs(), this.renderAlertButtons()), hAsync("div", { key: '5c728b7457e231f64294bbec821bdb547c6437dd', tabindex: "0", "aria-hidden": "true" })));
11446
11491
  }
11447
11492
  get el() { return getElement(this); }
11448
11493
  static get watchers() { return {
@@ -22330,17 +22375,19 @@ class ItemSliding {
22330
22375
  }
22331
22376
  }
22332
22377
  async updateOptions() {
22333
- const options = Array.from(this.el.querySelectorAll('ion-item-options'));
22334
- /**
22335
- * Frameworks that assign element props after inserting the element haven't set
22336
- * `side` while `connectedCallback` runs, so reading it any earlier reports every
22337
- * option as `end`.
22338
- */
22339
- await Promise.all(options.map((option) => new Promise((resolve) => componentOnReady(option, resolve))));
22378
+ const options = this.el.querySelectorAll('ion-item-options');
22340
22379
  let sides = 0;
22341
22380
  // Reset left and right options in case they were removed
22342
22381
  this.leftOptions = this.rightOptions = undefined;
22343
- for (const option of options) {
22382
+ for (let i = 0; i < options.length; i++) {
22383
+ const item = options.item(i);
22384
+ /**
22385
+ * We cannot use the componentOnReady helper
22386
+ * util here since we need to wait for all of these items
22387
+ * to be ready before we set `this.sides` and `this.optsDirty`.
22388
+ */
22389
+ // eslint-disable-next-line custom-rules/no-component-on-ready-method
22390
+ const option = item.componentOnReady !== undefined ? await item.componentOnReady() : item;
22344
22391
  const side = isEndSide(option.side ?? option.getAttribute('side')) ? 'end' : 'start';
22345
22392
  if (side === 'start') {
22346
22393
  this.leftOptions = option;
@@ -22539,7 +22586,7 @@ class ItemSliding {
22539
22586
  }
22540
22587
  render() {
22541
22588
  const mode = getIonMode$1(this);
22542
- return (hAsync(Host, { key: '02174ca963753d3a51a4249068f3d436f8acb03d', class: {
22589
+ return (hAsync(Host, { key: '15f6a98f8c888e86c29827cdf55d98ace08699dd', class: {
22543
22590
  [mode]: true,
22544
22591
  'item-sliding-active-slide': this.state !== 2 /* SlidingState.Disabled */,
22545
22592
  'item-sliding-active-options-end': (this.state & 8 /* SlidingState.End */) !== 0,
@@ -22952,6 +22999,10 @@ class Loading {
22952
22999
  connectedCallback() {
22953
23000
  prepareOverlay(this.el);
22954
23001
  this.triggerChanged();
23002
+ // Re-apply the root lock if moved without dismiss() being called
23003
+ if (this.presented) {
23004
+ restoreRootFocusTrapAccessibility(this.el);
23005
+ }
22955
23006
  }
22956
23007
  componentWillLoad() {
22957
23008
  if (this.spinner === undefined) {
@@ -23052,14 +23103,14 @@ class Loading {
23052
23103
  * Otherwise, don't set aria-labelledby.
23053
23104
  */
23054
23105
  const ariaLabelledBy = message !== undefined ? msgId : null;
23055
- return (hAsync(Host, { key: '2d14122ff3081de73631a7fdd4affdd5c73b8618', role: "dialog", "aria-modal": "true", "aria-labelledby": ariaLabelledBy, tabindex: "-1", ...htmlAttributes, style: {
23106
+ return (hAsync(Host, { key: 'b4430bc66aedeca19d5645667cba73c169c4bd76', role: "dialog", "aria-modal": "true", "aria-labelledby": ariaLabelledBy, tabindex: "-1", ...htmlAttributes, style: {
23056
23107
  zIndex: `${40000 + this.overlayIndex}`,
23057
23108
  }, onIonBackdropTap: this.onBackdropTap, class: {
23058
23109
  ...getClassMap(this.cssClass),
23059
23110
  [mode]: true,
23060
23111
  'overlay-hidden': true,
23061
23112
  'loading-translucent': this.translucent,
23062
- } }, hAsync("ion-backdrop", { key: 'b7d5bb0d670a20c159d7f67327bf3b1489449188', visible: this.showBackdrop, tappable: this.backdropDismiss }), hAsync("div", { key: '085ce92bd2004d323ab47eb472b83826e48dc619', tabindex: "0", "aria-hidden": "true" }), hAsync("div", { key: '4ecd5bfc0bbd3da434d32f0f319f867a44c5e1f1', class: "loading-wrapper ion-overlay-wrapper" }, spinner && (hAsync("div", { key: '5a4498e1421e09d01c0ee4312eae5272e95c3127', class: "loading-spinner" }, hAsync("ion-spinner", { key: '1b3bc7d45d775195657ead3535f65e6b79f37e84', name: spinner, "aria-hidden": "true" }))), message !== undefined && this.renderLoadingMessage(msgId)), hAsync("div", { key: 'bc7c5467b9f1c6ab957f79934e97acc713bdec37', tabindex: "0", "aria-hidden": "true" })));
23113
+ } }, hAsync("ion-backdrop", { key: 'dec0df942ae778c99ebd4dbf08d6c2a0a992639d', visible: this.showBackdrop, tappable: this.backdropDismiss }), hAsync("div", { key: '71b2d5fc259666225047fc901648ada1efcd5d4b', tabindex: "0", "aria-hidden": "true" }), hAsync("div", { key: '1d83dc3b57ee70c9e8c0f006c6fa576bd96ecded', class: "loading-wrapper ion-overlay-wrapper" }, spinner && (hAsync("div", { key: 'd1cd127e044b8831e396b53122322c1db7e89904', class: "loading-spinner" }, hAsync("ion-spinner", { key: '38c2580cf5659da612872f01801a5fbdc2c023ba', name: spinner, "aria-hidden": "true" }))), message !== undefined && this.renderLoadingMessage(msgId)), hAsync("div", { key: '90e5e32ffe0df2c691f364149f43374e676bfaa3', tabindex: "0", "aria-hidden": "true" })));
23063
23114
  }
23064
23115
  get el() { return getElement(this); }
23065
23116
  static get watchers() { return {
@@ -26618,6 +26669,9 @@ class Modal {
26618
26669
  this.inline = false;
26619
26670
  // Whether or not modal is being dismissed via gesture
26620
26671
  this.gestureAnimationDismissing = false;
26672
+ // True from the first safe-area write in `present()` until the enter
26673
+ // animation settles. A position-based read in that window is not the rest position.
26674
+ this.isPresenting = false;
26621
26675
  this.presented = false;
26622
26676
  /** @internal */
26623
26677
  this.hasController = false;
@@ -26854,6 +26908,17 @@ class Modal {
26854
26908
  const { el } = this;
26855
26909
  prepareOverlay(el);
26856
26910
  this.triggerChanged();
26911
+ // A disconnect tears down state this presentation still needs and cannot
26912
+ // tell a re-insert from a removal, so put it back.
26913
+ if (this.presented || this.isPresenting) {
26914
+ this.restoreSafeAreaOverrides();
26915
+ }
26916
+ // A relocation from `willPresent` reaches these before `present()` has
26917
+ // applied the lock, so they apply it instead. Both are idempotent.
26918
+ if (this.presented) {
26919
+ restoreRootFocusTrapAccessibility(el);
26920
+ this.initParentRemovalObserver();
26921
+ }
26857
26922
  }
26858
26923
  disconnectedCallback() {
26859
26924
  this.triggerController.removeClickListener();
@@ -27031,25 +27096,33 @@ class Modal {
27031
27096
  // Recalculate isSheetModal before safe-area setup because framework
27032
27097
  // bindings (e.g., Angular) may not have been applied when componentWillLoad ran.
27033
27098
  this.isSheetModal = this.breakpoints !== undefined && this.initialBreakpoint !== undefined;
27034
- // Set initial safe-area overrides before animation
27035
- this.setInitialSafeAreaOverrides();
27099
+ this.isPresenting = true;
27036
27100
  const hasCardModal = presentingElement !== undefined;
27037
- /**
27038
- * We need to change the status bar at the
27039
- * start of the animation so that it completes
27040
- * by the time the card animation is done.
27041
- */
27042
- if (hasCardModal && getIonMode$1(this) === 'ios') {
27043
- // Cache the original status bar color before the modal is presented
27044
- this.statusBarStyle = await StatusBar.getStyle();
27045
- setCardStatusBarDark();
27101
+ // Wrapped so a throw cannot strand `isPresenting`, which would suppress
27102
+ // the position-based correction for the life of this instance.
27103
+ try {
27104
+ // Set initial safe-area overrides before animation
27105
+ this.setInitialSafeAreaOverrides();
27106
+ /**
27107
+ * We need to change the status bar at the
27108
+ * start of the animation so that it completes
27109
+ * by the time the card animation is done.
27110
+ */
27111
+ if (hasCardModal && getIonMode$1(this) === 'ios') {
27112
+ // Cache the original status bar color before the modal is presented
27113
+ this.statusBarStyle = await StatusBar.getStyle();
27114
+ setCardStatusBarDark();
27115
+ }
27116
+ await present(this, 'modalEnter', iosEnterAnimation$2, mdEnterAnimation$2, {
27117
+ presentingEl: presentingElement,
27118
+ currentBreakpoint: this.initialBreakpoint,
27119
+ backdropBreakpoint: this.backdropBreakpoint,
27120
+ expandToScroll: this.expandToScroll,
27121
+ });
27122
+ }
27123
+ finally {
27124
+ this.isPresenting = false;
27046
27125
  }
27047
- await present(this, 'modalEnter', iosEnterAnimation$2, mdEnterAnimation$2, {
27048
- presentingEl: presentingElement,
27049
- currentBreakpoint: this.initialBreakpoint,
27050
- backdropBreakpoint: this.backdropBreakpoint,
27051
- expandToScroll: this.expandToScroll,
27052
- });
27053
27126
  // Update safe-area based on actual position after animation
27054
27127
  this.updateSafeAreaOverrides();
27055
27128
  // Apply fullscreen safe-area padding if needed
@@ -27551,6 +27624,9 @@ class Modal {
27551
27624
  this.cachedOriginalParent.tagName === 'ION-APP') {
27552
27625
  return;
27553
27626
  }
27627
+ // Both `present()` and a reconnect call this, so drop any existing
27628
+ // observer. Below the guards, so a call that bails cannot leave none.
27629
+ this.cleanupParentRemovalObserver();
27554
27630
  this.parentRemovalObserver = new MutationObserver((mutations) => {
27555
27631
  mutations.forEach((mutation) => {
27556
27632
  if (mutation.type === 'childList' && mutation.removedNodes.length > 0) {
@@ -27629,6 +27705,9 @@ class Modal {
27629
27705
  // Set the internal offset property with the resolved root safe-area-top value
27630
27706
  if (context.isSheetModal) {
27631
27707
  this.updateSheetOffsetTop();
27708
+ // A restore after a DOM move runs this a second time for the same
27709
+ // modal, so drop the previous subscription rather than stacking one.
27710
+ this.unsubscribeRootSafeAreaTop?.();
27632
27711
  this.unsubscribeRootSafeAreaTop = onRootSafeAreaTopChange((safeAreaTop) => this.updateSheetOffsetTop(safeAreaTop));
27633
27712
  }
27634
27713
  }
@@ -27747,6 +27826,31 @@ class Modal {
27747
27826
  const { contentEl } = this.findContentAndFooter();
27748
27827
  this.clearContentSafeAreaPadding(contentEl);
27749
27828
  }
27829
+ /**
27830
+ * Re-applies what `cleanupSafeAreaOverrides()` removed for a modal moved
27831
+ * while presented. Anything needing no measurement goes on synchronously so
27832
+ * the modal is never painted without safe-area. The position-based
27833
+ * correction waits a frame for the layout pass it reads.
27834
+ */
27835
+ restoreSafeAreaOverrides() {
27836
+ this.setInitialSafeAreaOverrides();
27837
+ this.applyFullscreenSafeArea();
27838
+ raf(() => {
27839
+ // A dismiss or another move can land first, and a read before the enter
27840
+ // animation settles is not the rest position. `present()` redoes it.
27841
+ if (!this.presented || !this.el.isConnected || this.isPresenting) {
27842
+ return;
27843
+ }
27844
+ // A hidden subtree carries `display: none`, so there is no box and the
27845
+ // read would write the safe-area for a modal touching no edge. The
27846
+ // prediction applied above holds until the modal is shown again.
27847
+ const { width, height } = this.el.getBoundingClientRect();
27848
+ if (width === 0 && height === 0) {
27849
+ return;
27850
+ }
27851
+ this.updateSafeAreaOverrides();
27852
+ });
27853
+ }
27750
27854
  render() {
27751
27855
  const { handle, isSheetModal, presentingElement, htmlAttributes, handleBehavior, inheritedAttributes, focusTrap, expandToScroll, } = this;
27752
27856
  const showHandle = handle !== false && isSheetModal;
@@ -27754,7 +27858,7 @@ class Modal {
27754
27858
  const isCardModal = presentingElement !== undefined && mode === 'ios';
27755
27859
  const isHandleCycle = handleBehavior === 'cycle';
27756
27860
  const isSheetModalWithHandle = isSheetModal && showHandle;
27757
- return (hAsync(Host, { key: 'a471c293319cb6ee5ffb7ffafec0b8413e4289de', "no-router": true,
27861
+ return (hAsync(Host, { key: '7c9c736052c5a788cf31040b6b2386dd9ea7454b', "no-router": true,
27758
27862
  // Allow the modal to be navigable when the handle is focusable
27759
27863
  tabIndex: isHandleCycle && isSheetModalWithHandle ? 0 : -1, ...htmlAttributes, style: {
27760
27864
  zIndex: `${20000 + this.overlayIndex}`,
@@ -27767,7 +27871,7 @@ class Modal {
27767
27871
  'overlay-hidden': true,
27768
27872
  [FOCUS_TRAP_DISABLE_CLASS]: focusTrap === false,
27769
27873
  ...getClassMap(this.cssClass),
27770
- }, onIonBackdropTap: this.onBackdropTap, onIonModalDidPresent: this.onLifecycle, onIonModalWillPresent: this.onLifecycle, onIonModalWillDismiss: this.onLifecycle, onIonModalDidDismiss: this.onLifecycle, onFocus: this.onModalFocus }, hAsync("ion-backdrop", { key: 'f67934afd4ddad64623856fb641cb6db846df428', ref: (el) => (this.backdropEl = el), visible: this.showBackdrop, tappable: this.backdropDismiss, part: "backdrop" }), mode === 'ios' && hAsync("div", { key: 'a23f5cb6cf60c8f717c1dd556bce375829c80a43', class: "modal-shadow" }), hAsync("div", { key: '51eb6cd1070e4b7e49840a78dc7437238c867a01',
27874
+ }, onIonBackdropTap: this.onBackdropTap, onIonModalDidPresent: this.onLifecycle, onIonModalWillPresent: this.onLifecycle, onIonModalWillDismiss: this.onLifecycle, onIonModalDidDismiss: this.onLifecycle, onFocus: this.onModalFocus }, hAsync("ion-backdrop", { key: '01b5b5765fb3a32393c736065c824bf760728823', ref: (el) => (this.backdropEl = el), visible: this.showBackdrop, tappable: this.backdropDismiss, part: "backdrop" }), mode === 'ios' && hAsync("div", { key: '40fa7727a0923f7d7461dd027f1511a6a148d84a', class: "modal-shadow" }), hAsync("div", { key: '9af934b607f60795bd5bff7bee6eacfc9b14fa35',
27771
27875
  /*
27772
27876
  role and aria-modal must be used on the
27773
27877
  same element. They must also be set inside the
@@ -27780,9 +27884,9 @@ class Modal {
27780
27884
  without the tabindex focus() would be a no-op and screen readers
27781
27885
  may not properly announce the dialog and its content when it opens.
27782
27886
  */
27783
- role: "dialog", ...inheritedAttributes, "aria-modal": "true", tabIndex: -1, class: "modal-wrapper ion-overlay-wrapper", part: "content", ref: (el) => (this.wrapperEl = el) }, showHandle && (hAsync("button", { key: 'f49a144642b5c227c0c2b00b33f4c7e37a2bf088', class: "modal-handle",
27887
+ role: "dialog", ...inheritedAttributes, "aria-modal": "true", tabIndex: -1, class: "modal-wrapper ion-overlay-wrapper", part: "content", ref: (el) => (this.wrapperEl = el) }, showHandle && (hAsync("button", { key: 'df84a6806413b13efc5b03c862edde83151579a7', class: "modal-handle",
27784
27888
  // Prevents the handle from receiving keyboard focus when it does not cycle
27785
- tabIndex: !isHandleCycle ? -1 : 0, "aria-label": "Activate to adjust the size of the dialog overlaying the screen", onClick: isHandleCycle ? this.onHandleClick : undefined, part: "handle", ref: (el) => (this.dragHandleEl = el) })), hAsync("slot", { key: 'e781c0d5881762c6b61aa432721a38b49580ff64', onSlotchange: this.onSlotChange }))));
27889
+ tabIndex: !isHandleCycle ? -1 : 0, "aria-label": "Activate to adjust the size of the dialog overlaying the screen", onClick: isHandleCycle ? this.onHandleClick : undefined, part: "handle", ref: (el) => (this.dragHandleEl = el) })), hAsync("slot", { key: '072d3929ec6f25481946b184d8ac24219011e783', onSlotchange: this.onSlotChange }))));
27786
27890
  }
27787
27891
  get el() { return getElement(this); }
27788
27892
  static get watchers() { return {
@@ -31218,6 +31322,13 @@ class Popover {
31218
31322
  const { configureTriggerInteraction, el } = this;
31219
31323
  prepareOverlay(el);
31220
31324
  configureTriggerInteraction();
31325
+ // Re-apply the root lock if moved without dismiss() being called
31326
+ if (this.presented) {
31327
+ restoreRootFocusTrapAccessibility(el);
31328
+ // The disconnect tore down the header observer, and `present()` is its
31329
+ // only other caller, so a move mid-layout would lose the recalculation.
31330
+ this.recalculateContentOnHeaderReady();
31331
+ }
31221
31332
  }
31222
31333
  disconnectedCallback() {
31223
31334
  const { destroyTriggerInteraction } = this;
@@ -31395,6 +31506,9 @@ class Popover {
31395
31506
  if (!header || contentElements.length === 0) {
31396
31507
  return;
31397
31508
  }
31509
+ // Both `present()` and a reconnect call this, so drop any existing
31510
+ // observer. Below the guards, so a call that bails cannot leave none.
31511
+ this.headerResizeObserver?.disconnect();
31398
31512
  this.headerResizeObserver = new ResizeObserver(async () => {
31399
31513
  if (header.offsetHeight > 0) {
31400
31514
  this.headerResizeObserver?.disconnect();
@@ -31467,7 +31581,7 @@ class Popover {
31467
31581
  const { onLifecycle, parentPopover, dismissOnSelect, side, arrow, htmlAttributes, focusTrap } = this;
31468
31582
  const desktop = isPlatform('desktop');
31469
31583
  const enableArrow = arrow && !parentPopover;
31470
- return (hAsync(Host, { key: '52ffc7116969ae1b8b927e67f2acbfe5f5434f70', "aria-modal": "true", "no-router": true, tabindex: "-1", ...htmlAttributes, style: {
31584
+ return (hAsync(Host, { key: '5a41565e6129c73112835aab18b7ae213de040f2', "aria-modal": "true", "no-router": true, tabindex: "-1", ...htmlAttributes, style: {
31471
31585
  zIndex: `${20000 + this.overlayIndex}`,
31472
31586
  }, class: {
31473
31587
  ...getClassMap(this.cssClass),
@@ -31478,7 +31592,7 @@ class Popover {
31478
31592
  [`popover-side-${side}`]: true,
31479
31593
  [FOCUS_TRAP_DISABLE_CLASS]: focusTrap === false,
31480
31594
  'popover-nested': !!parentPopover,
31481
- }, onIonPopoverDidPresent: onLifecycle, onIonPopoverWillPresent: onLifecycle, onIonPopoverWillDismiss: onLifecycle, onIonPopoverDidDismiss: onLifecycle, onIonBackdropTap: this.onBackdropTap }, !parentPopover && hAsync("ion-backdrop", { key: '79a8e851dbd22119e21ffb2f4709c555251045c8', tappable: this.backdropDismiss, visible: this.showBackdrop, part: "backdrop" }), hAsync("div", { key: 'c46c9f62c3ef3f902e23f27404eaa446a5d8cf88', class: "popover-wrapper ion-overlay-wrapper", onClick: dismissOnSelect ? () => this.dismiss() : undefined }, enableArrow && hAsync("div", { key: '9fdcbbc4ea6c7bde74f646d48eb77296b2c9dd83', class: "popover-arrow", part: "arrow" }), hAsync("div", { key: '138e56bb83462ebb0908edb522b45ecf94b82aeb', class: "popover-content", part: "content" }, hAsync("slot", { key: 'daeefcf002e8d89e91d6e0faf7f63f75b68a2dbe' })))));
31595
+ }, onIonPopoverDidPresent: onLifecycle, onIonPopoverWillPresent: onLifecycle, onIonPopoverWillDismiss: onLifecycle, onIonPopoverDidDismiss: onLifecycle, onIonBackdropTap: this.onBackdropTap }, !parentPopover && hAsync("ion-backdrop", { key: '59e724e4a6ce25eae78ccf1668effd988be7232a', tappable: this.backdropDismiss, visible: this.showBackdrop, part: "backdrop" }), hAsync("div", { key: '88d787ca20ac7cbacc4190bd771645dbe6083ad9', class: "popover-wrapper ion-overlay-wrapper", onClick: dismissOnSelect ? () => this.dismiss() : undefined }, enableArrow && hAsync("div", { key: 'f766e6413cc4545f27a43d5931c033261e3daa2c', class: "popover-arrow", part: "arrow" }), hAsync("div", { key: '675bddff0c071378858bb2d07bec91da68c2652a', class: "popover-content", part: "content" }, hAsync("slot", { key: '1c446b867083016b24b1b3baccd19b9fc08e114a' })))));
31482
31596
  }
31483
31597
  get el() { return getElement(this); }
31484
31598
  static get watchers() { return {
@@ -37273,6 +37387,11 @@ class SegmentButton {
37273
37387
  addEventListener$1(segmentEl, 'ionSelect', this.updateState);
37274
37388
  addEventListener$1(segmentEl, 'ionStyle', this.updateStyle);
37275
37389
  }
37390
+ // Prevent buttons from being disabled when associated with segment content
37391
+ if (this.contentId && this.disabled) {
37392
+ printIonWarning(`[ion-segment-button] - Segment buttons cannot be disabled when associated with an <ion-segment-content>.`);
37393
+ this.disabled = false;
37394
+ }
37276
37395
  }
37277
37396
  disconnectedCallback() {
37278
37397
  const segmentEl = this.segmentEl;
@@ -37289,15 +37408,6 @@ class SegmentButton {
37289
37408
  // Return if there is no contentId defined
37290
37409
  if (!this.contentId)
37291
37410
  return;
37292
- /**
37293
- * Checked here rather than in `connectedCallback` so frameworks that assign element
37294
- * props after inserting the element have set `disabled` by now. A disabled ion-segment
37295
- * pushes that onto its buttons too, which this guard should not undo.
37296
- */
37297
- if (this.disabled && this.segmentEl?.disabled !== true) {
37298
- printIonWarning(`[ion-segment-button] - Segment buttons cannot be disabled when associated with an <ion-segment-content>.`);
37299
- this.disabled = false;
37300
- }
37301
37411
  // Attempt to find the Segment Content by its contentId
37302
37412
  const segmentContent = document.getElementById(this.contentId);
37303
37413
  // If no associated Segment Content exists, log an error and return
@@ -37332,7 +37442,7 @@ class SegmentButton {
37332
37442
  const { checked, type, disabled, hasIcon, hasLabel, layout, segmentEl } = this;
37333
37443
  const mode = getIonMode$1(this);
37334
37444
  const hasSegmentColor = () => segmentEl?.color !== undefined;
37335
- return (hAsync(Host, { key: 'd8acc71d87e26b32f20b2d0f9a6acc9f0dab0dee', class: {
37445
+ return (hAsync(Host, { key: '2b4b7ad8b981d2ee39aba5b9c734de8a5bd045ba', class: {
37336
37446
  [mode]: true,
37337
37447
  'in-toolbar': hostContext('ion-toolbar', this.el),
37338
37448
  'in-toolbar-color': hostContext('ion-toolbar[color]', this.el),
@@ -37348,7 +37458,7 @@ class SegmentButton {
37348
37458
  'ion-activatable': true,
37349
37459
  'ion-activatable-instant': true,
37350
37460
  'ion-focusable': true,
37351
- } }, hAsync("button", { key: 'ce65da07b1a012bce353b3c6c24eecfbd4071d54', "aria-selected": checked ? 'true' : 'false', role: "tab", ref: (el) => (this.nativeEl = el), type: type, class: "button-native", part: "native", disabled: disabled, ...this.inheritedAttributes }, hAsync("span", { key: '6c4b4dcd20e407e5dc31674bea23633d8a09187a', class: "button-inner" }, hAsync("slot", { key: '817145ae77a3c5ada88ab95723d881f1bde96b2a' })), mode === 'md' && hAsync("ion-ripple-effect", { key: '054d7e5e2a13013914fac6bbde8efdb28d9b459e' })), hAsync("div", { key: 'c48074881a302510ad4752eeb9383222cd3a54cb', part: "indicator", class: "segment-button-indicator segment-button-indicator-animated" }, hAsync("div", { key: '7672a6b10ee18ad026b798fbd8207dc3cd5683f9', part: "indicator-background", class: "segment-button-indicator-background" }))));
37461
+ } }, hAsync("button", { key: '9cc58cfbe70844a0f5e1a307002e0d04e044be99', "aria-selected": checked ? 'true' : 'false', role: "tab", ref: (el) => (this.nativeEl = el), type: type, class: "button-native", part: "native", disabled: disabled, ...this.inheritedAttributes }, hAsync("span", { key: '6443551951ce589efdb2d0e1fd1a14e35b82ed19', class: "button-inner" }, hAsync("slot", { key: 'c3548b469ae6e5477d8372cb28bc70dff3a24d18' })), mode === 'md' && hAsync("ion-ripple-effect", { key: 'fb176415ca1702766c4d7a5964ec0bb467bdcb55' })), hAsync("div", { key: 'aa22b4752f8336d0e232a1e0894e87023b284a08', part: "indicator", class: "segment-button-indicator segment-button-indicator-animated" }, hAsync("div", { key: '61e29ea52048fa0583fce6c20c81614a4d0199cb', part: "indicator-background", class: "segment-button-indicator-background" }))));
37352
37462
  }
37353
37463
  get el() { return getElement(this); }
37354
37464
  static get watchers() { return {