@ionic/core 8.7.6-dev.11759345401.165fca78 → 8.7.6-dev.11759412372.1f332f62

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 (64) hide show
  1. package/components/ion-tab-bar.js +7 -20
  2. package/components/ion-tabs.js +22 -21
  3. package/components/modal.js +25 -11
  4. package/components/overlays.js +23 -10
  5. package/components/popover.js +3 -2
  6. package/dist/cjs/index.cjs.js +1 -1
  7. package/dist/cjs/ion-action-sheet.cjs.entry.js +1 -1
  8. package/dist/cjs/ion-alert.cjs.entry.js +1 -1
  9. package/dist/cjs/ion-datetime_3.cjs.entry.js +1 -1
  10. package/dist/cjs/ion-loading.cjs.entry.js +1 -1
  11. package/dist/cjs/ion-menu_3.cjs.entry.js +1 -1
  12. package/dist/cjs/ion-modal.cjs.entry.js +26 -12
  13. package/dist/cjs/ion-popover.cjs.entry.js +4 -3
  14. package/dist/cjs/ion-select-modal.cjs.entry.js +1 -1
  15. package/dist/cjs/ion-select_3.cjs.entry.js +1 -1
  16. package/dist/cjs/ion-tab-bar_2.cjs.entry.js +7 -20
  17. package/dist/cjs/ion-tab_2.cjs.entry.js +22 -21
  18. package/dist/cjs/ion-toast.cjs.entry.js +1 -1
  19. package/dist/cjs/{overlays-czPyT6xP.js → overlays-CnXxzdUE.js} +23 -10
  20. package/dist/collection/components/modal/gestures/sheet.js +20 -7
  21. package/dist/collection/components/modal/modal.js +5 -4
  22. package/dist/collection/components/popover/popover.js +3 -2
  23. package/dist/collection/components/tab-bar/tab-bar.js +7 -20
  24. package/dist/collection/components/tabs/tabs.js +22 -21
  25. package/dist/collection/utils/overlays.js +23 -10
  26. package/dist/docs.json +1 -1
  27. package/dist/esm/index.js +1 -1
  28. package/dist/esm/ion-action-sheet.entry.js +1 -1
  29. package/dist/esm/ion-alert.entry.js +1 -1
  30. package/dist/esm/ion-datetime_3.entry.js +1 -1
  31. package/dist/esm/ion-loading.entry.js +1 -1
  32. package/dist/esm/ion-menu_3.entry.js +1 -1
  33. package/dist/esm/ion-modal.entry.js +26 -12
  34. package/dist/esm/ion-popover.entry.js +4 -3
  35. package/dist/esm/ion-select-modal.entry.js +1 -1
  36. package/dist/esm/ion-select_3.entry.js +1 -1
  37. package/dist/esm/ion-tab-bar_2.entry.js +7 -20
  38. package/dist/esm/ion-tab_2.entry.js +22 -21
  39. package/dist/esm/ion-toast.entry.js +1 -1
  40. package/dist/esm/{overlays-BYcYBCrx.js → overlays-C6lqoZ8M.js} +23 -10
  41. package/dist/ionic/index.esm.js +1 -1
  42. package/dist/ionic/ionic.esm.js +1 -1
  43. package/dist/ionic/{p-0793aea6.entry.js → p-24cfbd94.entry.js} +1 -1
  44. package/dist/ionic/{p-746cd400.entry.js → p-2d199573.entry.js} +1 -1
  45. package/dist/ionic/{p-117e7a3f.entry.js → p-37074de0.entry.js} +1 -1
  46. package/dist/ionic/{p-568efea2.entry.js → p-3ea6a927.entry.js} +1 -1
  47. package/dist/ionic/{p-90f4cc71.entry.js → p-4cc97550.entry.js} +1 -1
  48. package/dist/ionic/p-55ea7dfc.entry.js +4 -0
  49. package/dist/ionic/{p-25e5e5cc.entry.js → p-56a91276.entry.js} +1 -1
  50. package/dist/ionic/{p-1f68cb59.entry.js → p-5a1f919a.entry.js} +1 -1
  51. package/dist/ionic/p-BW3pge-V.js +4 -0
  52. package/dist/ionic/{p-63852736.entry.js → p-b21fce9d.entry.js} +1 -1
  53. package/dist/ionic/{p-0e1904a0.entry.js → p-b7c1a16e.entry.js} +1 -1
  54. package/dist/ionic/p-e6c3214c.entry.js +4 -0
  55. package/dist/ionic/p-ec76fec4.entry.js +4 -0
  56. package/dist/types/components/tab-bar/tab-bar.d.ts +2 -2
  57. package/dist/types/components/tabs/tabs.d.ts +1 -3
  58. package/hydrate/index.js +80 -64
  59. package/hydrate/index.mjs +80 -64
  60. package/package.json +1 -1
  61. package/dist/ionic/p-2135be78.entry.js +0 -4
  62. package/dist/ionic/p-6e43c86a.entry.js +0 -4
  63. package/dist/ionic/p-Cnh7O81W.js +0 -4
  64. package/dist/ionic/p-e3cacac2.entry.js +0 -4
package/hydrate/index.js CHANGED
@@ -6173,7 +6173,7 @@ const setRootAriaHidden = (hidden = false) => {
6173
6173
  }
6174
6174
  };
6175
6175
  const present = async (overlay, name, iosEnterAnimation, mdEnterAnimation, opts) => {
6176
- var _a, _b;
6176
+ var _a, _b, _c, _d;
6177
6177
  if (overlay.presented) {
6178
6178
  return;
6179
6179
  }
@@ -6206,10 +6206,14 @@ const present = async (overlay, name, iosEnterAnimation, mdEnterAnimation, opts)
6206
6206
  * to avoid disabling the overlay.
6207
6207
  */
6208
6208
  const overlayEl = overlay.el;
6209
- const shouldTrapFocus = overlayEl.tagName !== 'ION-TOAST' && overlayEl.focusTrap !== false;
6209
+ const focusTrapAttr = (_a = overlayEl.getAttribute) === null || _a === void 0 ? void 0 : _a.call(overlayEl, 'focus-trap');
6210
+ const showBackdropAttr = (_b = overlayEl.getAttribute) === null || _b === void 0 ? void 0 : _b.call(overlayEl, 'show-backdrop');
6211
+ const focusTrapDisabled = overlayEl.focusTrap === false || focusTrapAttr === 'false';
6212
+ const backdropDisabled = overlayEl.showBackdrop === false || showBackdropAttr === 'false';
6213
+ const shouldTrapFocus = overlayEl.tagName !== 'ION-TOAST' && !focusTrapDisabled;
6210
6214
  // Only lock out root content when backdrop is active. Developers relying on showBackdrop=false
6211
6215
  // expect background interaction to remain enabled.
6212
- const shouldLockRoot = shouldTrapFocus && overlayEl.showBackdrop !== false;
6216
+ const shouldLockRoot = shouldTrapFocus && !backdropDisabled;
6213
6217
  overlay.presented = true;
6214
6218
  overlay.willPresent.emit();
6215
6219
  if (shouldLockRoot) {
@@ -6221,7 +6225,7 @@ const present = async (overlay, name, iosEnterAnimation, mdEnterAnimation, opts)
6221
6225
  }
6222
6226
  document.body.classList.add(BACKDROP_NO_SCROLL);
6223
6227
  }
6224
- (_a = overlay.willPresentShorthand) === null || _a === void 0 ? void 0 : _a.emit();
6228
+ (_c = overlay.willPresentShorthand) === null || _c === void 0 ? void 0 : _c.emit();
6225
6229
  const mode = getIonMode$1(overlay);
6226
6230
  // get the user's animation fn if one was provided
6227
6231
  const animationBuilder = overlay.enterAnimation
@@ -6230,7 +6234,7 @@ const present = async (overlay, name, iosEnterAnimation, mdEnterAnimation, opts)
6230
6234
  const completed = await overlayAnimation(overlay, animationBuilder, overlay.el, opts);
6231
6235
  if (completed) {
6232
6236
  overlay.didPresent.emit();
6233
- (_b = overlay.didPresentShorthand) === null || _b === void 0 ? void 0 : _b.emit();
6237
+ (_d = overlay.didPresentShorthand) === null || _d === void 0 ? void 0 : _d.emit();
6234
6238
  }
6235
6239
  /**
6236
6240
  * If the focused element is already
@@ -6308,7 +6312,7 @@ const restoreElementFocus = async (overlayEl) => {
6308
6312
  }
6309
6313
  };
6310
6314
  const dismiss = async (overlay, data, role, name, iosLeaveAnimation, mdLeaveAnimation, opts) => {
6311
- var _a, _b;
6315
+ var _a, _b, _c, _d;
6312
6316
  if (!overlay.presented) {
6313
6317
  return false;
6314
6318
  }
@@ -6324,11 +6328,20 @@ const dismiss = async (overlay, data, role, name, iosLeaveAnimation, mdLeaveAnim
6324
6328
  * is dismissed.
6325
6329
  */
6326
6330
  const overlaysLockingRoot = presentedOverlays.filter((o) => {
6331
+ var _a, _b;
6327
6332
  const el = o;
6328
- return el.tagName !== 'ION-TOAST' && el.focusTrap !== false && el.showBackdrop !== false;
6333
+ const focusTrapAttr = (_a = el.getAttribute) === null || _a === void 0 ? void 0 : _a.call(el, 'focus-trap');
6334
+ const showBackdropAttr = (_b = el.getAttribute) === null || _b === void 0 ? void 0 : _b.call(el, 'show-backdrop');
6335
+ const focusTrapDisabled = el.focusTrap === false || focusTrapAttr === 'false';
6336
+ const backdropDisabled = el.showBackdrop === false || showBackdropAttr === 'false';
6337
+ return el.tagName !== 'ION-TOAST' && !focusTrapDisabled && !backdropDisabled;
6329
6338
  });
6330
6339
  const overlayEl = overlay.el;
6331
- const locksRoot = overlayEl.tagName !== 'ION-TOAST' && overlayEl.focusTrap !== false && overlayEl.showBackdrop !== false;
6340
+ const focusTrapAttr = (_a = overlayEl.getAttribute) === null || _a === void 0 ? void 0 : _a.call(overlayEl, 'focus-trap');
6341
+ const showBackdropAttr = (_b = overlayEl.getAttribute) === null || _b === void 0 ? void 0 : _b.call(overlayEl, 'show-backdrop');
6342
+ const focusTrapDisabled = overlayEl.focusTrap === false || focusTrapAttr === 'false';
6343
+ const backdropDisabled = overlayEl.showBackdrop === false || showBackdropAttr === 'false';
6344
+ const locksRoot = overlayEl.tagName !== 'ION-TOAST' && !focusTrapDisabled && !backdropDisabled;
6332
6345
  /**
6333
6346
  * If this is the last visible overlay that is trapping focus
6334
6347
  * then we want to re-add the root to the accessibility tree.
@@ -6343,7 +6356,7 @@ const dismiss = async (overlay, data, role, name, iosLeaveAnimation, mdLeaveAnim
6343
6356
  // Overlay contents should not be clickable during dismiss
6344
6357
  overlay.el.style.setProperty('pointer-events', 'none');
6345
6358
  overlay.willDismiss.emit({ data, role });
6346
- (_a = overlay.willDismissShorthand) === null || _a === void 0 ? void 0 : _a.emit({ data, role });
6359
+ (_c = overlay.willDismissShorthand) === null || _c === void 0 ? void 0 : _c.emit({ data, role });
6347
6360
  const mode = getIonMode$1(overlay);
6348
6361
  const animationBuilder = overlay.leaveAnimation
6349
6362
  ? overlay.leaveAnimation
@@ -6353,7 +6366,7 @@ const dismiss = async (overlay, data, role, name, iosLeaveAnimation, mdLeaveAnim
6353
6366
  await overlayAnimation(overlay, animationBuilder, overlay.el, opts);
6354
6367
  }
6355
6368
  overlay.didDismiss.emit({ data, role });
6356
- (_b = overlay.didDismissShorthand) === null || _b === void 0 ? void 0 : _b.emit({ data, role });
6369
+ (_d = overlay.didDismissShorthand) === null || _d === void 0 ? void 0 : _d.emit({ data, role });
6357
6370
  // Get a reference to all animations currently assigned to this overlay
6358
6371
  // Then tear them down to return the overlay to its initial visual state
6359
6372
  const animations = activeAnimations.get(overlay) || [];
@@ -21792,6 +21805,7 @@ const mdLeaveAnimation$2 = (baseEl, opts) => {
21792
21805
  };
21793
21806
 
21794
21807
  const createSheetGesture = (baseEl, backdropEl, wrapperEl, initialBreakpoint, backdropBreakpoint, animation, breakpoints = [], expandToScroll, getCurrentBreakpoint, onDismiss, onBreakpointChange) => {
21808
+ var _a, _b;
21795
21809
  // Defaults for the sheet swipe animation
21796
21810
  const defaultBackdrop = [
21797
21811
  { offset: 0, opacity: 'var(--backdrop-opacity)' },
@@ -21829,10 +21843,15 @@ const createSheetGesture = (baseEl, backdropEl, wrapperEl, initialBreakpoint, ba
21829
21843
  const backdropAnimation = animation.childAnimations.find((ani) => ani.id === 'backdropAnimation');
21830
21844
  const contentAnimation = animation.childAnimations.find((ani) => ani.id === 'contentAnimation');
21831
21845
  const enableBackdrop = () => {
21846
+ var _a, _b;
21832
21847
  // Respect explicit opt-out of focus trapping/backdrop interactions
21833
21848
  // If focusTrap is false or showBackdrop is false, do not enable the backdrop or re-enable focus trap
21834
21849
  const el = baseEl;
21835
- if (el.focusTrap === false || el.showBackdrop === false) {
21850
+ const focusTrapAttr = (_a = el.getAttribute) === null || _a === void 0 ? void 0 : _a.call(el, 'focus-trap');
21851
+ const showBackdropAttr = (_b = el.getAttribute) === null || _b === void 0 ? void 0 : _b.call(el, 'show-backdrop');
21852
+ const focusTrapDisabled = el.focusTrap === false || focusTrapAttr === 'false';
21853
+ const backdropDisabled = el.showBackdrop === false || showBackdropAttr === 'false';
21854
+ if (focusTrapDisabled || backdropDisabled) {
21836
21855
  return;
21837
21856
  }
21838
21857
  baseEl.style.setProperty('pointer-events', 'auto');
@@ -21959,9 +21978,12 @@ const createSheetGesture = (baseEl, backdropEl, wrapperEl, initialBreakpoint, ba
21959
21978
  * ion-backdrop and .modal-wrapper always have pointer-events: auto
21960
21979
  * applied, so the modal content can still be interacted with.
21961
21980
  */
21962
- const shouldEnableBackdrop = currentBreakpoint > backdropBreakpoint &&
21963
- baseEl.focusTrap !== false &&
21964
- baseEl.showBackdrop !== false;
21981
+ const modalEl = baseEl;
21982
+ const focusTrapAttr = (_a = modalEl.getAttribute) === null || _a === void 0 ? void 0 : _a.call(modalEl, 'focus-trap');
21983
+ const showBackdropAttr = (_b = modalEl.getAttribute) === null || _b === void 0 ? void 0 : _b.call(modalEl, 'show-backdrop');
21984
+ const focusTrapDisabled = modalEl.focusTrap === false || focusTrapAttr === 'false';
21985
+ const backdropDisabled = modalEl.showBackdrop === false || showBackdropAttr === 'false';
21986
+ const shouldEnableBackdrop = currentBreakpoint > backdropBreakpoint && !focusTrapDisabled && !backdropDisabled;
21965
21987
  if (shouldEnableBackdrop) {
21966
21988
  enableBackdrop();
21967
21989
  }
@@ -22259,6 +22281,7 @@ const createSheetGesture = (baseEl, backdropEl, wrapperEl, initialBreakpoint, ba
22259
22281
  */
22260
22282
  if (wrapperAnimation && backdropAnimation) {
22261
22283
  raf(() => {
22284
+ var _a, _b;
22262
22285
  wrapperAnimation.keyframes([...SheetDefaults.WRAPPER_KEYFRAMES]);
22263
22286
  backdropAnimation.keyframes([...SheetDefaults.BACKDROP_KEYFRAMES]);
22264
22287
  contentAnimation === null || contentAnimation === void 0 ? void 0 : contentAnimation.keyframes([...SheetDefaults.CONTENT_KEYFRAMES]);
@@ -22269,9 +22292,12 @@ const createSheetGesture = (baseEl, backdropEl, wrapperEl, initialBreakpoint, ba
22269
22292
  * Backdrop should become enabled
22270
22293
  * after the backdropBreakpoint value
22271
22294
  */
22272
- const shouldEnableBackdrop = currentBreakpoint > backdropBreakpoint &&
22273
- baseEl.focusTrap !== false &&
22274
- baseEl.showBackdrop !== false;
22295
+ const modalEl = baseEl;
22296
+ const focusTrapAttr = (_a = modalEl.getAttribute) === null || _a === void 0 ? void 0 : _a.call(modalEl, 'focus-trap');
22297
+ const showBackdropAttr = (_b = modalEl.getAttribute) === null || _b === void 0 ? void 0 : _b.call(modalEl, 'show-backdrop');
22298
+ const focusTrapDisabled = modalEl.focusTrap === false || focusTrapAttr === 'false';
22299
+ const backdropDisabled = modalEl.showBackdrop === false || showBackdropAttr === 'false';
22300
+ const shouldEnableBackdrop = currentBreakpoint > backdropBreakpoint && !focusTrapDisabled && !backdropDisabled;
22275
22301
  if (shouldEnableBackdrop) {
22276
22302
  enableBackdrop();
22277
22303
  }
@@ -23180,20 +23206,21 @@ class Modal {
23180
23206
  const isCardModal = presentingElement !== undefined && mode === 'ios';
23181
23207
  const isHandleCycle = handleBehavior === 'cycle';
23182
23208
  const isSheetModalWithHandle = isSheetModal && showHandle;
23183
- return (hAsync(Host, Object.assign({ key: '9e9a7bd591eb17a225a00b4fa2e379e94601d17f', "no-router": true,
23209
+ const focusTrapAttr = this.el.getAttribute('focus-trap');
23210
+ return (hAsync(Host, Object.assign({ key: '5cb4c73e060f5bc0fdc9728cb8029665a08b4187', "no-router": true,
23184
23211
  // Allow the modal to be navigable when the handle is focusable
23185
23212
  tabIndex: isHandleCycle && isSheetModalWithHandle ? 0 : -1 }, htmlAttributes, { style: {
23186
23213
  zIndex: `${20000 + this.overlayIndex}`,
23187
- }, class: Object.assign({ [mode]: true, ['modal-default']: !isCardModal && !isSheetModal, [`modal-card`]: isCardModal, [`modal-sheet`]: isSheetModal, [`modal-no-expand-scroll`]: isSheetModal && !expandToScroll, 'overlay-hidden': true, [FOCUS_TRAP_DISABLE_CLASS]: focusTrap === false }, getClassMap(this.cssClass)), onIonBackdropTap: this.onBackdropTap, onIonModalDidPresent: this.onLifecycle, onIonModalWillPresent: this.onLifecycle, onIonModalWillDismiss: this.onLifecycle, onIonModalDidDismiss: this.onLifecycle, onFocus: this.onModalFocus }), hAsync("ion-backdrop", { key: 'e5eae2c14f830f75e308fcd7f4c10c86fac5b962', ref: (el) => (this.backdropEl = el), visible: this.showBackdrop, tappable: this.backdropDismiss, part: "backdrop" }), mode === 'ios' && hAsync("div", { key: 'e268f9cd310c3cf4e051b5b92524ce4fb70d005e', class: "modal-shadow" }), hAsync("div", Object.assign({ key: '9c380f36c18144c153077b15744d1c3346bce63e',
23214
+ }, 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 || focusTrapAttr === 'false' }, getClassMap(this.cssClass)), onIonBackdropTap: this.onBackdropTap, onIonModalDidPresent: this.onLifecycle, onIonModalWillPresent: this.onLifecycle, onIonModalWillDismiss: this.onLifecycle, onIonModalDidDismiss: this.onLifecycle, onFocus: this.onModalFocus }), hAsync("ion-backdrop", { key: '7697171f861e148d3ef7e35460dd8d3df2d4f3ac', ref: (el) => (this.backdropEl = el), visible: this.showBackdrop, tappable: this.backdropDismiss, part: "backdrop" }), mode === 'ios' && hAsync("div", { key: 'd71a7ca23e1aa2048af82959f902ea0fc92d6fba', class: "modal-shadow" }), hAsync("div", Object.assign({ key: '9543fdf222f35bd22ded828f60a1345e3b3da65c',
23188
23215
  /*
23189
23216
  role and aria-modal must be used on the
23190
23217
  same element. They must also be set inside the
23191
23218
  shadow DOM otherwise ion-button will not be highlighted
23192
23219
  when using VoiceOver: https://bugs.webkit.org/show_bug.cgi?id=247134
23193
23220
  */
23194
- role: "dialog" }, inheritedAttributes, { "aria-modal": "true", class: "modal-wrapper ion-overlay-wrapper", part: "content", ref: (el) => (this.wrapperEl = el) }), showHandle && (hAsync("button", { key: '2d5ee6d5959d97309c306e8ce72eb0f2c19be144', class: "modal-handle",
23221
+ role: "dialog" }, inheritedAttributes, { "aria-modal": "true", class: "modal-wrapper ion-overlay-wrapper", part: "content", ref: (el) => (this.wrapperEl = el) }), showHandle && (hAsync("button", { key: '411f1e52935485e2791afd9a97d6685c994bf44a', class: "modal-handle",
23195
23222
  // Prevents the handle from receiving keyboard focus when it does not cycle
23196
- 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: '5590434c35ea04c42fc006498bc189038e15a298', onSlotchange: this.onSlotChange }))));
23223
+ 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: '8dac500e345dfd66f3a3fa62cd94570682b1083e', onSlotchange: this.onSlotChange }))));
23197
23224
  }
23198
23225
  get el() { return getElement(this); }
23199
23226
  static get watchers() { return {
@@ -27508,9 +27535,10 @@ class Popover {
27508
27535
  const { onLifecycle, parentPopover, dismissOnSelect, side, arrow, htmlAttributes, focusTrap } = this;
27509
27536
  const desktop = isPlatform('desktop');
27510
27537
  const enableArrow = arrow && !parentPopover;
27511
- return (hAsync(Host, Object.assign({ key: '16866c02534968c982cf4730d2936d03a5107c8b', "aria-modal": "true", "no-router": true, tabindex: "-1" }, htmlAttributes, { style: {
27538
+ const focusTrapAttr = this.el.getAttribute('focus-trap');
27539
+ return (hAsync(Host, Object.assign({ key: 'fe80ce582ef39698a3c11e305df3e8e599e91bdb', "aria-modal": "true", "no-router": true, tabindex: "-1" }, htmlAttributes, { style: {
27512
27540
  zIndex: `${20000 + this.overlayIndex}`,
27513
- }, class: Object.assign(Object.assign({}, getClassMap(this.cssClass)), { [mode]: true, 'popover-translucent': this.translucent, 'overlay-hidden': true, 'popover-desktop': desktop, [`popover-side-${side}`]: true, [FOCUS_TRAP_DISABLE_CLASS]: focusTrap === false, 'popover-nested': !!parentPopover }), onIonPopoverDidPresent: onLifecycle, onIonPopoverWillPresent: onLifecycle, onIonPopoverWillDismiss: onLifecycle, onIonPopoverDidDismiss: onLifecycle, onIonBackdropTap: this.onBackdropTap }), !parentPopover && hAsync("ion-backdrop", { key: '0df258601a4d30df3c27aa8234a7d5e056c3ecbb', tappable: this.backdropDismiss, visible: this.showBackdrop, part: "backdrop" }), hAsync("div", { key: 'f94e80ed996b957b5cd09b826472b4f60e8fcc78', class: "popover-wrapper ion-overlay-wrapper", onClick: dismissOnSelect ? () => this.dismiss() : undefined }, enableArrow && hAsync("div", { key: '185ce22f6386e8444a9cc7b8818dbfc16c463c99', class: "popover-arrow", part: "arrow" }), hAsync("div", { key: '206202b299404e110de5397b229678cca18568d3', class: "popover-content", part: "content" }, hAsync("slot", { key: 'ee543a0b92d6e35a837c0a0e4617c7b0fc4ad0b0' })))));
27541
+ }, class: Object.assign(Object.assign({}, getClassMap(this.cssClass)), { [mode]: true, 'popover-translucent': this.translucent, 'overlay-hidden': true, 'popover-desktop': desktop, [`popover-side-${side}`]: true, [FOCUS_TRAP_DISABLE_CLASS]: focusTrap === false || focusTrapAttr === 'false', 'popover-nested': !!parentPopover }), onIonPopoverDidPresent: onLifecycle, onIonPopoverWillPresent: onLifecycle, onIonPopoverWillDismiss: onLifecycle, onIonPopoverDidDismiss: onLifecycle, onIonBackdropTap: this.onBackdropTap }), !parentPopover && hAsync("ion-backdrop", { key: 'f37d7c8574fded2721311d4f12726e21d830cc54', tappable: this.backdropDismiss, visible: this.showBackdrop, part: "backdrop" }), hAsync("div", { key: '1567893f935e1da1cb46b81ea14a76af7895eee5', class: "popover-wrapper ion-overlay-wrapper", onClick: dismissOnSelect ? () => this.dismiss() : undefined }, enableArrow && hAsync("div", { key: '456163df03d2b582e07b1f81fa6088125d3308ef', class: "popover-arrow", part: "arrow" }), hAsync("div", { key: '470d257a44fb9532a392bf9f5a89a1531d02323c', class: "popover-content", part: "content" }, hAsync("slot", { key: 'd434289bba55ad9ab169a5092d214f4031511a8f' })))));
27514
27542
  }
27515
27543
  get el() { return getElement(this); }
27516
27544
  static get watchers() { return {
@@ -34381,7 +34409,6 @@ class TabBar {
34381
34409
  this.ionTabBarChanged = createEvent(this, "ionTabBarChanged", 7);
34382
34410
  this.ionTabBarLoaded = createEvent(this, "ionTabBarLoaded", 7);
34383
34411
  this.keyboardCtrl = null;
34384
- this.didLoad = false;
34385
34412
  this.keyboardVisible = false;
34386
34413
  /**
34387
34414
  * If `true`, the tab bar will be translucent.
@@ -34391,29 +34418,14 @@ class TabBar {
34391
34418
  this.translucent = false;
34392
34419
  }
34393
34420
  selectedTabChanged() {
34394
- // Skip the initial watcher call that happens during component load
34395
- // We handle that in componentDidLoad to ensure children are ready
34396
- if (!this.didLoad) {
34397
- return;
34398
- }
34399
34421
  if (this.selectedTab !== undefined) {
34400
34422
  this.ionTabBarChanged.emit({
34401
34423
  tab: this.selectedTab,
34402
34424
  });
34403
34425
  }
34404
34426
  }
34405
- componentDidLoad() {
34406
- this.ionTabBarLoaded.emit();
34407
- // Set the flag to indicate the component has loaded
34408
- // This allows the watcher to emit changes from this point forward
34409
- this.didLoad = true;
34410
- // Emit the initial selected tab after the component is fully loaded
34411
- // This ensures all child components (ion-tab-button) are ready
34412
- if (this.selectedTab !== undefined) {
34413
- this.ionTabBarChanged.emit({
34414
- tab: this.selectedTab,
34415
- });
34416
- }
34427
+ componentWillLoad() {
34428
+ this.selectedTabChanged();
34417
34429
  }
34418
34430
  async connectedCallback() {
34419
34431
  this.keyboardCtrl = await createKeyboardController(async (keyboardOpen, waitForResize) => {
@@ -34433,15 +34445,18 @@ class TabBar {
34433
34445
  this.keyboardCtrl.destroy();
34434
34446
  }
34435
34447
  }
34448
+ componentDidLoad() {
34449
+ this.ionTabBarLoaded.emit();
34450
+ }
34436
34451
  render() {
34437
34452
  const { color, translucent, keyboardVisible } = this;
34438
34453
  const mode = getIonMode$1(this);
34439
34454
  const shouldHide = keyboardVisible && this.el.getAttribute('slot') !== 'top';
34440
- return (hAsync(Host, { key: '388ec37ce308035bab78d6c9a016bb616e9517a9', role: "tablist", "aria-hidden": shouldHide ? 'true' : null, class: createColorClasses$1(color, {
34455
+ return (hAsync(Host, { key: '275dc6c1b30f6928ce9039b2f445208bb3500ddc', role: "tablist", "aria-hidden": shouldHide ? 'true' : null, class: createColorClasses$1(color, {
34441
34456
  [mode]: true,
34442
34457
  'tab-bar-translucent': translucent,
34443
34458
  'tab-bar-hidden': shouldHide,
34444
- }) }, hAsync("slot", { key: 'ce10ade2b86725e24f3254516483eeedd8ecb16a' })));
34459
+ }) }, hAsync("slot", { key: 'ceac20128d75c6a4a0f445f2df8deb8cc71fc4da' })));
34445
34460
  }
34446
34461
  get el() { return getElement(this); }
34447
34462
  static get watchers() { return {
@@ -34626,27 +34641,29 @@ class Tabs {
34626
34641
  }
34627
34642
  this.ionNavWillLoad.emit();
34628
34643
  }
34629
- componentDidLoad() {
34630
- this.updateTabBar();
34631
- }
34632
- componentDidUpdate() {
34633
- this.updateTabBar();
34634
- }
34635
- updateTabBar() {
34644
+ componentWillRender() {
34636
34645
  const tabBar = this.el.querySelector('ion-tab-bar');
34637
- if (!tabBar) {
34638
- return;
34639
- }
34640
- const tab = this.selectedTab ? this.selectedTab.tab : undefined;
34641
- // If tabs has no selected tab but tab-bar already has a selected-tab set,
34642
- // don't overwrite it. This handles cases where tab-bar is used without ion-tab elements.
34643
- if (tab === undefined) {
34644
- return;
34645
- }
34646
- if (tabBar.selectedTab === tab) {
34647
- return;
34646
+ if (tabBar) {
34647
+ let tab = this.selectedTab ? this.selectedTab.tab : undefined;
34648
+ // Fallback: if no selectedTab is set but we're using router mode,
34649
+ // determine the active tab from the current URL. This works around
34650
+ // timing issues in React Router integration where setRouteId may not
34651
+ // be called in time for the initial render.
34652
+ // TODO(FW-6724): Remove this with React Router upgrade
34653
+ if (!tab && this.useRouter && typeof window !== 'undefined') {
34654
+ const currentPath = window.location.pathname;
34655
+ const tabButtons = this.el.querySelectorAll('ion-tab-button');
34656
+ // Look for a tab button that matches the current path pattern
34657
+ for (const tabButton of tabButtons) {
34658
+ const tabId = tabButton.getAttribute('tab');
34659
+ if (tabId && currentPath.includes(tabId)) {
34660
+ tab = tabId;
34661
+ break;
34662
+ }
34663
+ }
34664
+ }
34665
+ tabBar.selectedTab = tab;
34648
34666
  }
34649
- tabBar.selectedTab = tab;
34650
34667
  }
34651
34668
  /**
34652
34669
  * Select a tab by the value of its `tab` property or an element reference. This method is only available for vanilla JavaScript projects. The Angular, React, and Vue implementations of tabs are coupled to each framework's router.
@@ -34705,7 +34722,6 @@ class Tabs {
34705
34722
  this.selectedTab = selectedTab;
34706
34723
  this.ionTabsWillChange.emit({ tab: selectedTab.tab });
34707
34724
  selectedTab.active = true;
34708
- this.updateTabBar();
34709
34725
  return Promise.resolve();
34710
34726
  }
34711
34727
  tabSwitch() {
@@ -34740,7 +34756,7 @@ class Tabs {
34740
34756
  return Array.from(this.el.querySelectorAll('ion-tab'));
34741
34757
  }
34742
34758
  render() {
34743
- return (hAsync(Host, { key: '7b4b302f2942d8d131f6fc24e817989a8be08867', onIonTabButtonClick: this.onTabClicked }, hAsync("slot", { key: '2c51cf14c0f17a8ddf2d879858c984cdf8fd3147', name: "top" }), hAsync("div", { key: '7e9d6055092d41bd9bc80ae15965f77e216feb84', class: "tabs-inner" }, hAsync("slot", { key: 'c308a787e37ff7f6653531d70deca597a7602d26' })), hAsync("slot", { key: 'd5f5e693710c853570811602f859cf3e88272684', name: "bottom" })));
34759
+ return (hAsync(Host, { key: '6dd1d17cc5a7aff4b910303006b4478080ca97af', onIonTabButtonClick: this.onTabClicked }, hAsync("slot", { key: 'db54a692d1a825498a116f090eb305f7cceceb5a', name: "top" }), hAsync("div", { key: 'e1b7d49ba7032e9071de2029695254e2a8303be9', class: "tabs-inner" }, hAsync("slot", { key: '4c3b58d5292c8c834e7532c51de0861068943d79' })), hAsync("slot", { key: 'dd59c0b9b217dfbfb0fccdbc6896b593278549cc', name: "bottom" })));
34744
34760
  }
34745
34761
  get el() { return getElement(this); }
34746
34762
  static get style() { return tabsCss; }