@ionic/core 8.7.3-dev.11755006024.11261c64 → 8.7.3-dev.11755190119.16c6a375

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 (68) hide show
  1. package/components/ion-datetime.js +3 -4
  2. package/components/ion-input.js +4 -4
  3. package/components/overlays.js +97 -1
  4. package/components/picker-column-option.js +3 -3
  5. package/components/picker-column.js +39 -3
  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 +4 -4
  10. package/dist/cjs/ion-input.cjs.entry.js +4 -4
  11. package/dist/cjs/ion-loading.cjs.entry.js +1 -1
  12. package/dist/cjs/ion-menu_3.cjs.entry.js +1 -1
  13. package/dist/cjs/ion-modal.cjs.entry.js +1 -1
  14. package/dist/cjs/ion-picker-column-option.cjs.entry.js +3 -3
  15. package/dist/cjs/ion-picker-column.cjs.entry.js +39 -3
  16. package/dist/cjs/ion-popover.cjs.entry.js +1 -1
  17. package/dist/cjs/ion-select-modal.cjs.entry.js +1 -1
  18. package/dist/cjs/ion-select_3.cjs.entry.js +1 -1
  19. package/dist/cjs/ion-toast.cjs.entry.js +1 -1
  20. package/dist/cjs/{overlays-DsQx1liJ.js → overlays-CglR7j-u.js} +96 -0
  21. package/dist/collection/components/datetime/datetime.js +3 -4
  22. package/dist/collection/components/input/input.js +4 -4
  23. package/dist/collection/components/picker-column/picker-column.js +39 -3
  24. package/dist/collection/components/picker-column-option/picker-column-option.ios.css +2 -2
  25. package/dist/collection/components/picker-column-option/picker-column-option.js +1 -1
  26. package/dist/collection/components/picker-column-option/picker-column-option.md.css +2 -2
  27. package/dist/collection/utils/overlays.js +97 -0
  28. package/dist/docs.json +1 -1
  29. package/dist/esm/index.js +1 -1
  30. package/dist/esm/ion-action-sheet.entry.js +1 -1
  31. package/dist/esm/ion-alert.entry.js +1 -1
  32. package/dist/esm/ion-datetime_3.entry.js +4 -4
  33. package/dist/esm/ion-input.entry.js +4 -4
  34. package/dist/esm/ion-loading.entry.js +1 -1
  35. package/dist/esm/ion-menu_3.entry.js +1 -1
  36. package/dist/esm/ion-modal.entry.js +1 -1
  37. package/dist/esm/ion-picker-column-option.entry.js +3 -3
  38. package/dist/esm/ion-picker-column.entry.js +39 -3
  39. package/dist/esm/ion-popover.entry.js +1 -1
  40. package/dist/esm/ion-select-modal.entry.js +1 -1
  41. package/dist/esm/ion-select_3.entry.js +1 -1
  42. package/dist/esm/ion-toast.entry.js +1 -1
  43. package/dist/esm/{overlays-NqBaHPvD.js → overlays-ZX_4-t_r.js} +97 -1
  44. package/dist/ionic/index.esm.js +1 -1
  45. package/dist/ionic/ionic.esm.js +1 -1
  46. package/dist/ionic/p-1d5b934a.entry.js +4 -0
  47. package/dist/ionic/p-29032e49.entry.js +4 -0
  48. package/dist/ionic/{p-abdfa903.entry.js → p-7bac2c5f.entry.js} +1 -1
  49. package/dist/ionic/{p-6979d2fe.entry.js → p-8d96a0cd.entry.js} +1 -1
  50. package/dist/ionic/{p-ea415755.entry.js → p-91d6ccb0.entry.js} +1 -1
  51. package/dist/ionic/{p-25f16425.entry.js → p-92e8f208.entry.js} +1 -1
  52. package/dist/ionic/{p-4be3f593.entry.js → p-982fe1c4.entry.js} +1 -1
  53. package/dist/ionic/p-9f36c56a.entry.js +4 -0
  54. package/dist/ionic/p-CSwZyt05.js +4 -0
  55. package/dist/ionic/{p-bbea41a8.entry.js → p-ab33ef20.entry.js} +1 -1
  56. package/dist/ionic/{p-82f92e81.entry.js → p-ac434970.entry.js} +1 -1
  57. package/dist/ionic/{p-cb155366.entry.js → p-c575e7ce.entry.js} +1 -1
  58. package/dist/ionic/{p-2b9eb6e6.entry.js → p-f2884bc2.entry.js} +1 -1
  59. package/dist/ionic/p-f456d176.entry.js +4 -0
  60. package/dist/types/components/picker-column/picker-column.d.ts +7 -0
  61. package/hydrate/index.js +145 -13
  62. package/hydrate/index.mjs +145 -13
  63. package/package.json +1 -1
  64. package/dist/ionic/p-1488b7cc.entry.js +0 -4
  65. package/dist/ionic/p-61646e84.entry.js +0 -4
  66. package/dist/ionic/p-8888efe4.entry.js +0 -4
  67. package/dist/ionic/p-Dks1yZU6.js +0 -4
  68. package/dist/ionic/p-b292804d.entry.js +0 -4
package/hydrate/index.js CHANGED
@@ -6188,6 +6188,8 @@ const present = async (overlay, name, iosEnterAnimation, mdEnterAnimation, opts)
6188
6188
  setRootAriaHidden(true);
6189
6189
  document.body.classList.add(BACKDROP_NO_SCROLL);
6190
6190
  }
6191
+ hideUnderlyingOverlaysFromScreenReaders(overlay.el);
6192
+ hideAnimatingOverlayFromScreenReaders(overlay.el);
6191
6193
  overlay.presented = true;
6192
6194
  overlay.willPresent.emit();
6193
6195
  (_a = overlay.willPresentShorthand) === null || _a === void 0 ? void 0 : _a.emit();
@@ -6313,6 +6315,12 @@ const dismiss = async (overlay, data, role, name, iosLeaveAnimation, mdLeaveAnim
6313
6315
  }
6314
6316
  overlay.presented = false;
6315
6317
  try {
6318
+ /**
6319
+ * There is no need to show the overlay to screen readers during
6320
+ * the dismiss animation. This is because the overlay will be removed
6321
+ * from the DOM after the animation is complete.
6322
+ */
6323
+ hideAnimatingOverlayFromScreenReaders(overlay.el);
6316
6324
  // Overlay contents should not be clickable during dismiss
6317
6325
  overlay.el.style.setProperty('pointer-events', 'none');
6318
6326
  overlay.willDismiss.emit({ data, role });
@@ -6351,6 +6359,7 @@ const dismiss = async (overlay, data, role, name, iosLeaveAnimation, mdLeaveAnim
6351
6359
  printIonError(`[${overlay.el.tagName.toLowerCase()}] - `, err);
6352
6360
  }
6353
6361
  overlay.el.remove();
6362
+ revealOverlaysToScreenReaders();
6354
6363
  return true;
6355
6364
  };
6356
6365
  const getAppRoot = (doc) => {
@@ -6546,6 +6555,93 @@ const createTriggerController = () => {
6546
6555
  removeClickListener,
6547
6556
  };
6548
6557
  };
6558
+ /**
6559
+ * The overlay that is being animated also needs to hide from screen
6560
+ * readers during its animation. This ensures that assistive technologies
6561
+ * like TalkBack do not announce or interact with the content until the
6562
+ * animation is complete, avoiding confusion for users.
6563
+ *
6564
+ * When the overlay is presented on an Android device, TalkBack's focus rings
6565
+ * may appear in the wrong position due to the transition (specifically
6566
+ * `transform` styles). This occurs because the focus rings are initially
6567
+ * displayed at the starting position of the elements before the transition
6568
+ * begins. This workaround ensures the focus rings do not appear in the
6569
+ * incorrect location.
6570
+ *
6571
+ * If this solution is applied to iOS devices, then it leads to a bug where
6572
+ * the overlays cannot be accessed by screen readers. This is due to
6573
+ * VoiceOver not being able to update the accessibility tree when the
6574
+ * `aria-hidden` is removed.
6575
+ *
6576
+ * @param overlay - The overlay that is being animated.
6577
+ */
6578
+ const hideAnimatingOverlayFromScreenReaders = (overlay) => {
6579
+ if (doc === undefined)
6580
+ return;
6581
+ if (isPlatform('android')) {
6582
+ /**
6583
+ * Once the animation is complete, this attribute will be removed.
6584
+ * This is done at the end of the `present` method.
6585
+ */
6586
+ overlay.setAttribute('aria-hidden', 'true');
6587
+ }
6588
+ };
6589
+ /**
6590
+ * Ensure that underlying overlays have aria-hidden if necessary so that screen readers
6591
+ * cannot move focus to these elements. Note that we cannot rely on focus/focusin/focusout
6592
+ * events here because those events do not fire when the screen readers moves to a non-focusable
6593
+ * element such as text.
6594
+ * Without this logic screen readers would be able to move focus outside of the top focus-trapped overlay.
6595
+ *
6596
+ * @param newTopMostOverlay - The overlay that is being presented. Since the overlay has not been
6597
+ * fully presented yet at the time this function is called it will not be included in the getPresentedOverlays result.
6598
+ */
6599
+ const hideUnderlyingOverlaysFromScreenReaders = (newTopMostOverlay) => {
6600
+ var _a;
6601
+ if (doc === undefined)
6602
+ return;
6603
+ const overlays = getPresentedOverlays(doc);
6604
+ for (let i = overlays.length - 1; i >= 0; i--) {
6605
+ const presentedOverlay = overlays[i];
6606
+ const nextPresentedOverlay = (_a = overlays[i + 1]) !== null && _a !== void 0 ? _a : newTopMostOverlay;
6607
+ /**
6608
+ * If next overlay has aria-hidden then all remaining overlays will have it too.
6609
+ * Or, if the next overlay is a Toast that does not have aria-hidden then current overlay
6610
+ * should not have aria-hidden either so focus can remain in the current overlay.
6611
+ */
6612
+ if (nextPresentedOverlay.hasAttribute('aria-hidden') || nextPresentedOverlay.tagName !== 'ION-TOAST') {
6613
+ presentedOverlay.setAttribute('aria-hidden', 'true');
6614
+ }
6615
+ }
6616
+ };
6617
+ /**
6618
+ * When dismissing an overlay we need to reveal the new top-most overlay to screen readers.
6619
+ * If the top-most overlay is a Toast we potentially need to reveal more overlays since
6620
+ * focus is never automatically moved to the Toast.
6621
+ */
6622
+ const revealOverlaysToScreenReaders = () => {
6623
+ if (doc === undefined)
6624
+ return;
6625
+ const overlays = getPresentedOverlays(doc);
6626
+ for (let i = overlays.length - 1; i >= 0; i--) {
6627
+ const currentOverlay = overlays[i];
6628
+ /**
6629
+ * If the current we are looking at is a Toast then we can remove aria-hidden.
6630
+ * However, we potentially need to keep looking at the overlay stack because there
6631
+ * could be more Toasts underneath. Additionally, we need to unhide the closest non-Toast
6632
+ * overlay too so focus can move there since focus is never automatically moved to the Toast.
6633
+ */
6634
+ currentOverlay.removeAttribute('aria-hidden');
6635
+ /**
6636
+ * If we found a non-Toast element then we can just remove aria-hidden and stop searching entirely
6637
+ * since this overlay should always receive focus. As a result, all underlying overlays should still
6638
+ * be hidden from screen readers.
6639
+ */
6640
+ if (currentOverlay.tagName !== 'ION-TOAST') {
6641
+ break;
6642
+ }
6643
+ }
6644
+ };
6549
6645
  const FOCUS_TRAP_DISABLE_CLASS = 'ion-disable-focus-trap';
6550
6646
 
6551
6647
  const hostContext = (selector, el) => {
@@ -13435,7 +13531,7 @@ class Datetime {
13435
13531
  const renderArray = forcePresentation === 'time-date'
13436
13532
  ? [this.renderTimePickerColumns(forcePresentation), this.renderDatePickerColumns(forcePresentation)]
13437
13533
  : [this.renderDatePickerColumns(forcePresentation), this.renderTimePickerColumns(forcePresentation)];
13438
- return hAsync("ion-picker", { class: FOCUS_TRAP_DISABLE_CLASS }, renderArray);
13534
+ return hAsync("ion-picker", null, renderArray);
13439
13535
  }
13440
13536
  renderDatePickerColumns(forcePresentation) {
13441
13537
  return forcePresentation === 'date-time' || forcePresentation === 'time-date'
@@ -13992,7 +14088,7 @@ class Datetime {
13992
14088
  const hasDatePresentation = presentation === 'date' || presentation === 'date-time' || presentation === 'time-date';
13993
14089
  const hasWheelVariant = hasDatePresentation && preferWheel;
13994
14090
  renderHiddenInput(true, el, name, formatValue(value), disabled);
13995
- return (hAsync(Host, { key: '57492534800ea059a7c2bbd9f0059cc0b75ae8d2', "aria-disabled": disabled ? 'true' : null, onFocus: this.onFocus, onBlur: this.onBlur, class: Object.assign({}, createColorClasses$1(color, {
14091
+ return (hAsync(Host, { key: 'f35cf200ff05d33074576e3d2754d3b2a0735b96', "aria-disabled": disabled ? 'true' : null, onFocus: this.onFocus, onBlur: this.onBlur, class: Object.assign({}, createColorClasses$1(color, {
13996
14092
  [mode]: true,
13997
14093
  ['datetime-readonly']: readonly,
13998
14094
  ['datetime-disabled']: disabled,
@@ -14002,7 +14098,7 @@ class Datetime {
14002
14098
  [`datetime-size-${size}`]: true,
14003
14099
  [`datetime-prefer-wheel`]: hasWheelVariant,
14004
14100
  [`datetime-grid`]: isGridStyle,
14005
- })) }, hAsync("div", { key: '97dac5e5195635ac0bc5fb472b9d09e5c3c6bbc3', class: "intersection-tracker", ref: (el) => (this.intersectionTrackerRef = el) }), this.renderDatetime(mode)));
14101
+ })) }, hAsync("div", { key: '859e9354a12bfa58ac3f964c2e66839f17071c00', class: "intersection-tracker", ref: (el) => (this.intersectionTrackerRef = el) }), this.renderDatetime(mode)));
14006
14102
  }
14007
14103
  get el() { return getElement(this); }
14008
14104
  static get watchers() { return {
@@ -16850,7 +16946,7 @@ class Input {
16850
16946
  const { helperText, errorText, helperTextId, errorTextId } = this;
16851
16947
  return [
16852
16948
  hAsync("div", { id: helperTextId, class: "helper-text" }, helperText),
16853
- hAsync("div", { id: errorTextId, class: "error-text" }, errorText),
16949
+ hAsync("div", { id: errorTextId, class: "error-text", "aria-live": "assertive", "aria-atomic": "true" }, errorText),
16854
16950
  ];
16855
16951
  }
16856
16952
  getHintTextID() {
@@ -16968,7 +17064,7 @@ class Input {
16968
17064
  * TODO(FW-5592): Remove hasStartEndSlots condition
16969
17065
  */
16970
17066
  const labelShouldFloat = labelPlacement === 'stacked' || (labelPlacement === 'floating' && (hasValue || hasFocus || hasStartEndSlots));
16971
- return (hAsync(Host, { key: '41b2526627e7d2773a80f011b123284203a71ca0', class: createColorClasses$1(this.color, {
17067
+ return (hAsync(Host, { key: 'f00c1c1d3f57e98dd0c5a88c5bfef156a265e742', class: createColorClasses$1(this.color, {
16972
17068
  [mode]: true,
16973
17069
  'has-value': hasValue,
16974
17070
  'has-focus': hasFocus,
@@ -16979,14 +17075,14 @@ class Input {
16979
17075
  'in-item': inItem,
16980
17076
  'in-item-color': hostContext('ion-item.ion-color', this.el),
16981
17077
  'input-disabled': disabled,
16982
- }) }, hAsync("label", { key: '9ab078363e32528102b441ad1791d83f86fdcbdc', class: "input-wrapper", htmlFor: inputId, onClick: this.onLabelClick }, this.renderLabelContainer(), hAsync("div", { key: 'e34b594980ec62e4c618e827fadf7669a39ad0d8', class: "native-wrapper", onClick: this.onLabelClick }, hAsync("slot", { key: '12dc04ead5502e9e5736240e918bf9331bf7b5d9', name: "start" }), hAsync("input", Object.assign({ key: 'df356eb4ced23109b2c0242f36dc043aba8782d6', class: "native-input", ref: (input) => (this.nativeInput = input), id: inputId, disabled: disabled, autoCapitalize: this.autocapitalize, autoComplete: this.autocomplete, autoCorrect: this.autocorrect, autoFocus: this.autofocus, enterKeyHint: this.enterkeyhint, inputMode: this.inputmode, min: this.min, max: this.max, minLength: this.minlength, maxLength: this.maxlength, multiple: this.multiple, name: this.name, pattern: this.pattern, placeholder: this.placeholder || '', readOnly: readonly, required: this.required, spellcheck: this.spellcheck, step: this.step, type: this.type, value: value, onInput: this.onInput, onChange: this.onChange, onBlur: this.onBlur, onFocus: this.onFocus, onKeyDown: this.onKeydown, onCompositionstart: this.onCompositionStart, onCompositionend: this.onCompositionEnd, "aria-describedby": this.getHintTextID(), "aria-invalid": this.getHintTextID() === this.errorTextId }, this.inheritedAttributes)), this.clearInput && !readonly && !disabled && (hAsync("button", { key: 'f79f68cabcd4ea99419331174a377827db0c0741', "aria-label": "reset", type: "button", class: "input-clear-icon", onPointerDown: (ev) => {
17078
+ }) }, hAsync("label", { key: '95de0c0153ddd94c39e15d779ea0e1b3a991a3d9', class: "input-wrapper", htmlFor: inputId, onClick: this.onLabelClick }, this.renderLabelContainer(), hAsync("div", { key: '55d22ffcac1f8c07c5b86df1ae36ff39643143cd', class: "native-wrapper", onClick: this.onLabelClick }, hAsync("slot", { key: '59341c66cace2c718219d1023bd9190dbd41b000', name: "start" }), hAsync("input", Object.assign({ key: 'ab675664758bee4b2717c3914438c85b8b1ebb44', class: "native-input", ref: (input) => (this.nativeInput = input), id: inputId, disabled: disabled, autoCapitalize: this.autocapitalize, autoComplete: this.autocomplete, autoCorrect: this.autocorrect, autoFocus: this.autofocus, enterKeyHint: this.enterkeyhint, inputMode: this.inputmode, min: this.min, max: this.max, minLength: this.minlength, maxLength: this.maxlength, multiple: this.multiple, name: this.name, pattern: this.pattern, placeholder: this.placeholder || '', readOnly: readonly, required: this.required, spellcheck: this.spellcheck, step: this.step, type: this.type, value: value, onInput: this.onInput, onChange: this.onChange, onBlur: this.onBlur, onFocus: this.onFocus, onKeyDown: this.onKeydown, onCompositionstart: this.onCompositionStart, onCompositionend: this.onCompositionEnd, "aria-describedby": this.getHintTextID(), "aria-invalid": this.getHintTextID() === this.errorTextId }, this.inheritedAttributes)), this.clearInput && !readonly && !disabled && (hAsync("button", { key: 'fec4fa631b33151bc31ed9fc4f34970f72fd36f5', "aria-label": "reset", type: "button", class: "input-clear-icon", onPointerDown: (ev) => {
16983
17079
  /**
16984
17080
  * This prevents mobile browsers from
16985
17081
  * blurring the input when the clear
16986
17082
  * button is activated.
16987
17083
  */
16988
17084
  ev.preventDefault();
16989
- }, onClick: this.clearTextInput }, hAsync("ion-icon", { key: '237ec07ec2e10f08818a332bb596578c2c49f770', "aria-hidden": "true", icon: clearIconData }))), hAsync("slot", { key: '1f0a3624aa3e8dc3c307a6762230ab698768a5e5', name: "end" })), shouldRenderHighlight && hAsync("div", { key: '8a8cbb82695a722a0010b53dd0b1f1f97534a20b', class: "input-highlight" })), this.renderBottomContent()));
17085
+ }, onClick: this.clearTextInput }, hAsync("ion-icon", { key: '47bc105137bfad30a5d3c05b11eda552bc643d9a', "aria-hidden": "true", icon: clearIconData }))), hAsync("slot", { key: '6d93afaf67d147dff45e17825d5d8c7a82d7be18', name: "end" })), shouldRenderHighlight && hAsync("div", { key: '7ea437e065d66ba7d143e1c9ad72f4bcdb1e5f01', class: "input-highlight" })), this.renderBottomContent()));
16990
17086
  }
16991
17087
  get el() { return getElement(this); }
16992
17088
  static get watchers() { return {
@@ -25408,6 +25504,23 @@ class PickerColumn {
25408
25504
  var _a;
25409
25505
  return el ? (_a = el.getAttribute('aria-label')) !== null && _a !== void 0 ? _a : el.innerText : '';
25410
25506
  };
25507
+ /**
25508
+ * Render an element that overlays the column. This element is for assistive
25509
+ * tech to allow users to navigate the column up/down. This element should receive
25510
+ * focus as it listens for synthesized keyboard events as required by the
25511
+ * slider role: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Roles/slider_role
25512
+ */
25513
+ this.renderAssistiveFocusable = () => {
25514
+ const { activeItem } = this;
25515
+ const valueText = this.getOptionValueText(activeItem);
25516
+ /**
25517
+ * When using the picker, the valuetext provides important context that valuenow
25518
+ * does not. Additionally, using non-zero valuemin/valuemax values can cause
25519
+ * WebKit to incorrectly announce numeric valuetext values (such as a year
25520
+ * like "2024") as percentages: https://bugs.webkit.org/show_bug.cgi?id=273126
25521
+ */
25522
+ return (hAsync("div", { ref: (el) => (this.assistiveFocusable = el), class: "assistive-focusable", role: "slider", tabindex: this.disabled ? undefined : 0, "aria-label": this.ariaLabel, "aria-valuemin": 0, "aria-valuemax": 0, "aria-valuenow": 0, "aria-valuetext": valueText, "aria-orientation": "vertical", onKeyDown: (ev) => this.onKeyDown(ev) }));
25523
+ };
25411
25524
  }
25412
25525
  ariaLabelChanged(newValue) {
25413
25526
  this.ariaLabel = newValue;
@@ -25548,14 +25661,33 @@ class PickerColumn {
25548
25661
  render() {
25549
25662
  const { color, disabled, isActive, numericInput } = this;
25550
25663
  const mode = getIonMode$1(this);
25551
- return (hAsync(Host, { key: 'db903fd415f8a2d91994dececca481c1af8ba6a9', class: createColorClasses$1(color, {
25664
+ return (hAsync(Host, { key: 'ea0280355b2f87895bf7dddd289ccf473aa759f3', class: createColorClasses$1(color, {
25552
25665
  [mode]: true,
25553
25666
  ['picker-column-active']: isActive,
25554
25667
  ['picker-column-numeric-input']: numericInput,
25555
25668
  ['picker-column-disabled']: disabled,
25556
- }) }, hAsync("slot", { key: '02ce9e1dd7df91afcd50b06416552bcffb5dec98', name: "prefix" }), hAsync("div", { key: '6dfd7d2429bec19244a6b1afb4448121963a031b', class: "picker-opts", ref: (el) => {
25669
+ }) }, this.renderAssistiveFocusable(), hAsync("slot", { key: '482992131cdeb85b1f61430d7fe1322a16345769', name: "prefix" }), hAsync("div", { key: '43f7f80d621d411ef366b3ca1396299e8c9a0c97', "aria-hidden": "true", class: "picker-opts", ref: (el) => {
25557
25670
  this.scrollEl = el;
25558
- }, role: "slider", tabindex: this.disabled ? undefined : 0, "aria-label": this.ariaLabel, "aria-valuemin": 0, "aria-valuemax": 0, "aria-valuenow": 0, "aria-valuetext": this.getOptionValueText(this.activeItem), "aria-orientation": "vertical", onKeyDown: (ev) => this.onKeyDown(ev) }, hAsync("div", { key: 'e30ce0b9cefbfe4d4441fa33acf595da31855c3f', class: "picker-item-empty", "aria-hidden": "true" }, "\u00A0"), hAsync("div", { key: '8be2bd293c12c6ba720d9b31d0d561a96f42e97d', class: "picker-item-empty", "aria-hidden": "true" }, "\u00A0"), hAsync("div", { key: '8afdcddddabbf646fbb55cb0ba4448309a2c1dd9', class: "picker-item-empty", "aria-hidden": "true" }, "\u00A0"), hAsync("slot", { key: '6aa0dacc34d6848575ad5b122b9046982308ca43' }), hAsync("div", { key: '92ec8a357414c1b779b11d1dd18fb87a7ee63982', class: "picker-item-empty", "aria-hidden": "true" }, "\u00A0"), hAsync("div", { key: 'b89457cb74b5907c25594ff6720ac54ca537e933', class: "picker-item-empty", "aria-hidden": "true" }, "\u00A0"), hAsync("div", { key: '5bbc92e6bc24de08e39873bf08c5b668373ac0f8', class: "picker-item-empty", "aria-hidden": "true" }, "\u00A0")), hAsync("slot", { key: 'd7bf2b519214f0f3576a4ca79844ad97827dd97f', name: "suffix" })));
25671
+ },
25672
+ /**
25673
+ * When an element has an overlay scroll style and
25674
+ * a fixed height, Firefox will focus the scrollable
25675
+ * container if the content exceeds the container's
25676
+ * dimensions.
25677
+ *
25678
+ * This causes keyboard navigation to focus to this
25679
+ * element instead of going to the next element in
25680
+ * the tab order.
25681
+ *
25682
+ * The desired behavior is for the user to be able to
25683
+ * focus the assistive focusable element and tab to
25684
+ * the next element in the tab order. Instead of tabbing
25685
+ * to this element.
25686
+ *
25687
+ * To prevent this, we set the tabIndex to -1. This
25688
+ * will match the behavior of the other browsers.
25689
+ */
25690
+ tabIndex: -1 }, hAsync("div", { key: '13a9ee686132af32240710730765de4c0003a9e8', class: "picker-item-empty", "aria-hidden": "true" }, "\u00A0"), hAsync("div", { key: 'dbccba4920833cfcebe9b0fc763458ec3053705a', class: "picker-item-empty", "aria-hidden": "true" }, "\u00A0"), hAsync("div", { key: '682b43f83a5ea2e46067457f3af118535e111edb', class: "picker-item-empty", "aria-hidden": "true" }, "\u00A0"), hAsync("slot", { key: 'd27e1e1dc0504b2f4627a29912a05bb91e8e413a' }), hAsync("div", { key: '61c948dbb9cf7469aed3018542bc0954211585ba', class: "picker-item-empty", "aria-hidden": "true" }, "\u00A0"), hAsync("div", { key: 'cf46c277fbee65e35ff44ce0d53ce12aa9cbf9db', class: "picker-item-empty", "aria-hidden": "true" }, "\u00A0"), hAsync("div", { key: 'bbc0e2d491d3f836ab849493ade2f7fa6ad9244e', class: "picker-item-empty", "aria-hidden": "true" }, "\u00A0")), hAsync("slot", { key: 'd25cbbe14b2914fe7b878d43b4e3f4a8c8177d24', name: "suffix" })));
25559
25691
  }
25560
25692
  get el() { return getElement(this); }
25561
25693
  static get watchers() { return {
@@ -25947,9 +26079,9 @@ const DECELERATION_FRICTION = 0.97;
25947
26079
  const MAX_PICKER_SPEED = 90;
25948
26080
  const TRANSITION_DURATION = 150;
25949
26081
 
25950
- const pickerColumnOptionIosCss = ".picker-column-option-button{padding-left:0;padding-right:0;padding-top:0;padding-bottom:0;margin-left:0;margin-right:0;margin-top:0;margin-bottom:0;width:100%;height:34px;border:0px;outline:none;background:transparent;color:inherit;font-family:var(--ion-font-family, inherit);font-size:inherit;line-height:34px;text-align:inherit;text-overflow:ellipsis;white-space:nowrap;cursor:pointer;overflow:hidden}:host(.option-disabled){opacity:0.4}:host(.option-disabled) .picker-column-option-button{cursor:default}";
26082
+ const pickerColumnOptionIosCss = "button{padding-left:0;padding-right:0;padding-top:0;padding-bottom:0;margin-left:0;margin-right:0;margin-top:0;margin-bottom:0;width:100%;height:34px;border:0px;outline:none;background:transparent;color:inherit;font-family:var(--ion-font-family, inherit);font-size:inherit;line-height:34px;text-align:inherit;text-overflow:ellipsis;white-space:nowrap;cursor:pointer;overflow:hidden}:host(.option-disabled){opacity:0.4}:host(.option-disabled) button{cursor:default}";
25951
26083
 
25952
- const pickerColumnOptionMdCss = ".picker-column-option-button{padding-left:0;padding-right:0;padding-top:0;padding-bottom:0;margin-left:0;margin-right:0;margin-top:0;margin-bottom:0;width:100%;height:34px;border:0px;outline:none;background:transparent;color:inherit;font-family:var(--ion-font-family, inherit);font-size:inherit;line-height:34px;text-align:inherit;text-overflow:ellipsis;white-space:nowrap;cursor:pointer;overflow:hidden}:host(.option-disabled){opacity:0.4}:host(.option-disabled) .picker-column-option-button{cursor:default}:host(.option-active){color:var(--ion-color-base)}";
26084
+ const pickerColumnOptionMdCss = "button{padding-left:0;padding-right:0;padding-top:0;padding-bottom:0;margin-left:0;margin-right:0;margin-top:0;margin-bottom:0;width:100%;height:34px;border:0px;outline:none;background:transparent;color:inherit;font-family:var(--ion-font-family, inherit);font-size:inherit;line-height:34px;text-align:inherit;text-overflow:ellipsis;white-space:nowrap;cursor:pointer;overflow:hidden}:host(.option-disabled){opacity:0.4}:host(.option-disabled) button{cursor:default}:host(.option-active){color:var(--ion-color-base)}";
25953
26085
 
25954
26086
  class PickerColumnOption {
25955
26087
  constructor(hostRef) {
@@ -26041,7 +26173,7 @@ class PickerColumnOption {
26041
26173
  return (hAsync(Host, { key: 'f816729941aabcb31ddfdce3ffe2e2139030d715', class: createColorClasses$1(color, {
26042
26174
  [mode]: true,
26043
26175
  ['option-disabled']: disabled,
26044
- }) }, hAsync("div", { key: 'd942de84fd14d7dc06b1e5cf4f7920d1dc3c6371', class: 'picker-column-option-button', role: "button", "aria-label": ariaLabel, onClick: () => this.onClick() }, hAsync("slot", { key: 'b0df5717b42209e649097209a01476e1a66f5c5c' }))));
26176
+ }) }, hAsync("button", { key: '48dff7833bb60fc8331cd353a0885e6affa683d1', tabindex: "-1", "aria-label": ariaLabel, disabled: disabled, onClick: () => this.onClick() }, hAsync("slot", { key: 'f9224d0e7b7aa6c05b29abfdcfe0f30ad6ee3141' }))));
26045
26177
  }
26046
26178
  get el() { return getElement(this); }
26047
26179
  static get watchers() { return {
package/hydrate/index.mjs CHANGED
@@ -6186,6 +6186,8 @@ const present = async (overlay, name, iosEnterAnimation, mdEnterAnimation, opts)
6186
6186
  setRootAriaHidden(true);
6187
6187
  document.body.classList.add(BACKDROP_NO_SCROLL);
6188
6188
  }
6189
+ hideUnderlyingOverlaysFromScreenReaders(overlay.el);
6190
+ hideAnimatingOverlayFromScreenReaders(overlay.el);
6189
6191
  overlay.presented = true;
6190
6192
  overlay.willPresent.emit();
6191
6193
  (_a = overlay.willPresentShorthand) === null || _a === void 0 ? void 0 : _a.emit();
@@ -6311,6 +6313,12 @@ const dismiss = async (overlay, data, role, name, iosLeaveAnimation, mdLeaveAnim
6311
6313
  }
6312
6314
  overlay.presented = false;
6313
6315
  try {
6316
+ /**
6317
+ * There is no need to show the overlay to screen readers during
6318
+ * the dismiss animation. This is because the overlay will be removed
6319
+ * from the DOM after the animation is complete.
6320
+ */
6321
+ hideAnimatingOverlayFromScreenReaders(overlay.el);
6314
6322
  // Overlay contents should not be clickable during dismiss
6315
6323
  overlay.el.style.setProperty('pointer-events', 'none');
6316
6324
  overlay.willDismiss.emit({ data, role });
@@ -6349,6 +6357,7 @@ const dismiss = async (overlay, data, role, name, iosLeaveAnimation, mdLeaveAnim
6349
6357
  printIonError(`[${overlay.el.tagName.toLowerCase()}] - `, err);
6350
6358
  }
6351
6359
  overlay.el.remove();
6360
+ revealOverlaysToScreenReaders();
6352
6361
  return true;
6353
6362
  };
6354
6363
  const getAppRoot = (doc) => {
@@ -6544,6 +6553,93 @@ const createTriggerController = () => {
6544
6553
  removeClickListener,
6545
6554
  };
6546
6555
  };
6556
+ /**
6557
+ * The overlay that is being animated also needs to hide from screen
6558
+ * readers during its animation. This ensures that assistive technologies
6559
+ * like TalkBack do not announce or interact with the content until the
6560
+ * animation is complete, avoiding confusion for users.
6561
+ *
6562
+ * When the overlay is presented on an Android device, TalkBack's focus rings
6563
+ * may appear in the wrong position due to the transition (specifically
6564
+ * `transform` styles). This occurs because the focus rings are initially
6565
+ * displayed at the starting position of the elements before the transition
6566
+ * begins. This workaround ensures the focus rings do not appear in the
6567
+ * incorrect location.
6568
+ *
6569
+ * If this solution is applied to iOS devices, then it leads to a bug where
6570
+ * the overlays cannot be accessed by screen readers. This is due to
6571
+ * VoiceOver not being able to update the accessibility tree when the
6572
+ * `aria-hidden` is removed.
6573
+ *
6574
+ * @param overlay - The overlay that is being animated.
6575
+ */
6576
+ const hideAnimatingOverlayFromScreenReaders = (overlay) => {
6577
+ if (doc === undefined)
6578
+ return;
6579
+ if (isPlatform('android')) {
6580
+ /**
6581
+ * Once the animation is complete, this attribute will be removed.
6582
+ * This is done at the end of the `present` method.
6583
+ */
6584
+ overlay.setAttribute('aria-hidden', 'true');
6585
+ }
6586
+ };
6587
+ /**
6588
+ * Ensure that underlying overlays have aria-hidden if necessary so that screen readers
6589
+ * cannot move focus to these elements. Note that we cannot rely on focus/focusin/focusout
6590
+ * events here because those events do not fire when the screen readers moves to a non-focusable
6591
+ * element such as text.
6592
+ * Without this logic screen readers would be able to move focus outside of the top focus-trapped overlay.
6593
+ *
6594
+ * @param newTopMostOverlay - The overlay that is being presented. Since the overlay has not been
6595
+ * fully presented yet at the time this function is called it will not be included in the getPresentedOverlays result.
6596
+ */
6597
+ const hideUnderlyingOverlaysFromScreenReaders = (newTopMostOverlay) => {
6598
+ var _a;
6599
+ if (doc === undefined)
6600
+ return;
6601
+ const overlays = getPresentedOverlays(doc);
6602
+ for (let i = overlays.length - 1; i >= 0; i--) {
6603
+ const presentedOverlay = overlays[i];
6604
+ const nextPresentedOverlay = (_a = overlays[i + 1]) !== null && _a !== void 0 ? _a : newTopMostOverlay;
6605
+ /**
6606
+ * If next overlay has aria-hidden then all remaining overlays will have it too.
6607
+ * Or, if the next overlay is a Toast that does not have aria-hidden then current overlay
6608
+ * should not have aria-hidden either so focus can remain in the current overlay.
6609
+ */
6610
+ if (nextPresentedOverlay.hasAttribute('aria-hidden') || nextPresentedOverlay.tagName !== 'ION-TOAST') {
6611
+ presentedOverlay.setAttribute('aria-hidden', 'true');
6612
+ }
6613
+ }
6614
+ };
6615
+ /**
6616
+ * When dismissing an overlay we need to reveal the new top-most overlay to screen readers.
6617
+ * If the top-most overlay is a Toast we potentially need to reveal more overlays since
6618
+ * focus is never automatically moved to the Toast.
6619
+ */
6620
+ const revealOverlaysToScreenReaders = () => {
6621
+ if (doc === undefined)
6622
+ return;
6623
+ const overlays = getPresentedOverlays(doc);
6624
+ for (let i = overlays.length - 1; i >= 0; i--) {
6625
+ const currentOverlay = overlays[i];
6626
+ /**
6627
+ * If the current we are looking at is a Toast then we can remove aria-hidden.
6628
+ * However, we potentially need to keep looking at the overlay stack because there
6629
+ * could be more Toasts underneath. Additionally, we need to unhide the closest non-Toast
6630
+ * overlay too so focus can move there since focus is never automatically moved to the Toast.
6631
+ */
6632
+ currentOverlay.removeAttribute('aria-hidden');
6633
+ /**
6634
+ * If we found a non-Toast element then we can just remove aria-hidden and stop searching entirely
6635
+ * since this overlay should always receive focus. As a result, all underlying overlays should still
6636
+ * be hidden from screen readers.
6637
+ */
6638
+ if (currentOverlay.tagName !== 'ION-TOAST') {
6639
+ break;
6640
+ }
6641
+ }
6642
+ };
6547
6643
  const FOCUS_TRAP_DISABLE_CLASS = 'ion-disable-focus-trap';
6548
6644
 
6549
6645
  const hostContext = (selector, el) => {
@@ -13433,7 +13529,7 @@ class Datetime {
13433
13529
  const renderArray = forcePresentation === 'time-date'
13434
13530
  ? [this.renderTimePickerColumns(forcePresentation), this.renderDatePickerColumns(forcePresentation)]
13435
13531
  : [this.renderDatePickerColumns(forcePresentation), this.renderTimePickerColumns(forcePresentation)];
13436
- return hAsync("ion-picker", { class: FOCUS_TRAP_DISABLE_CLASS }, renderArray);
13532
+ return hAsync("ion-picker", null, renderArray);
13437
13533
  }
13438
13534
  renderDatePickerColumns(forcePresentation) {
13439
13535
  return forcePresentation === 'date-time' || forcePresentation === 'time-date'
@@ -13990,7 +14086,7 @@ class Datetime {
13990
14086
  const hasDatePresentation = presentation === 'date' || presentation === 'date-time' || presentation === 'time-date';
13991
14087
  const hasWheelVariant = hasDatePresentation && preferWheel;
13992
14088
  renderHiddenInput(true, el, name, formatValue(value), disabled);
13993
- return (hAsync(Host, { key: '57492534800ea059a7c2bbd9f0059cc0b75ae8d2', "aria-disabled": disabled ? 'true' : null, onFocus: this.onFocus, onBlur: this.onBlur, class: Object.assign({}, createColorClasses$1(color, {
14089
+ return (hAsync(Host, { key: 'f35cf200ff05d33074576e3d2754d3b2a0735b96', "aria-disabled": disabled ? 'true' : null, onFocus: this.onFocus, onBlur: this.onBlur, class: Object.assign({}, createColorClasses$1(color, {
13994
14090
  [mode]: true,
13995
14091
  ['datetime-readonly']: readonly,
13996
14092
  ['datetime-disabled']: disabled,
@@ -14000,7 +14096,7 @@ class Datetime {
14000
14096
  [`datetime-size-${size}`]: true,
14001
14097
  [`datetime-prefer-wheel`]: hasWheelVariant,
14002
14098
  [`datetime-grid`]: isGridStyle,
14003
- })) }, hAsync("div", { key: '97dac5e5195635ac0bc5fb472b9d09e5c3c6bbc3', class: "intersection-tracker", ref: (el) => (this.intersectionTrackerRef = el) }), this.renderDatetime(mode)));
14099
+ })) }, hAsync("div", { key: '859e9354a12bfa58ac3f964c2e66839f17071c00', class: "intersection-tracker", ref: (el) => (this.intersectionTrackerRef = el) }), this.renderDatetime(mode)));
14004
14100
  }
14005
14101
  get el() { return getElement(this); }
14006
14102
  static get watchers() { return {
@@ -16848,7 +16944,7 @@ class Input {
16848
16944
  const { helperText, errorText, helperTextId, errorTextId } = this;
16849
16945
  return [
16850
16946
  hAsync("div", { id: helperTextId, class: "helper-text" }, helperText),
16851
- hAsync("div", { id: errorTextId, class: "error-text" }, errorText),
16947
+ hAsync("div", { id: errorTextId, class: "error-text", "aria-live": "assertive", "aria-atomic": "true" }, errorText),
16852
16948
  ];
16853
16949
  }
16854
16950
  getHintTextID() {
@@ -16966,7 +17062,7 @@ class Input {
16966
17062
  * TODO(FW-5592): Remove hasStartEndSlots condition
16967
17063
  */
16968
17064
  const labelShouldFloat = labelPlacement === 'stacked' || (labelPlacement === 'floating' && (hasValue || hasFocus || hasStartEndSlots));
16969
- return (hAsync(Host, { key: '41b2526627e7d2773a80f011b123284203a71ca0', class: createColorClasses$1(this.color, {
17065
+ return (hAsync(Host, { key: 'f00c1c1d3f57e98dd0c5a88c5bfef156a265e742', class: createColorClasses$1(this.color, {
16970
17066
  [mode]: true,
16971
17067
  'has-value': hasValue,
16972
17068
  'has-focus': hasFocus,
@@ -16977,14 +17073,14 @@ class Input {
16977
17073
  'in-item': inItem,
16978
17074
  'in-item-color': hostContext('ion-item.ion-color', this.el),
16979
17075
  'input-disabled': disabled,
16980
- }) }, hAsync("label", { key: '9ab078363e32528102b441ad1791d83f86fdcbdc', class: "input-wrapper", htmlFor: inputId, onClick: this.onLabelClick }, this.renderLabelContainer(), hAsync("div", { key: 'e34b594980ec62e4c618e827fadf7669a39ad0d8', class: "native-wrapper", onClick: this.onLabelClick }, hAsync("slot", { key: '12dc04ead5502e9e5736240e918bf9331bf7b5d9', name: "start" }), hAsync("input", Object.assign({ key: 'df356eb4ced23109b2c0242f36dc043aba8782d6', class: "native-input", ref: (input) => (this.nativeInput = input), id: inputId, disabled: disabled, autoCapitalize: this.autocapitalize, autoComplete: this.autocomplete, autoCorrect: this.autocorrect, autoFocus: this.autofocus, enterKeyHint: this.enterkeyhint, inputMode: this.inputmode, min: this.min, max: this.max, minLength: this.minlength, maxLength: this.maxlength, multiple: this.multiple, name: this.name, pattern: this.pattern, placeholder: this.placeholder || '', readOnly: readonly, required: this.required, spellcheck: this.spellcheck, step: this.step, type: this.type, value: value, onInput: this.onInput, onChange: this.onChange, onBlur: this.onBlur, onFocus: this.onFocus, onKeyDown: this.onKeydown, onCompositionstart: this.onCompositionStart, onCompositionend: this.onCompositionEnd, "aria-describedby": this.getHintTextID(), "aria-invalid": this.getHintTextID() === this.errorTextId }, this.inheritedAttributes)), this.clearInput && !readonly && !disabled && (hAsync("button", { key: 'f79f68cabcd4ea99419331174a377827db0c0741', "aria-label": "reset", type: "button", class: "input-clear-icon", onPointerDown: (ev) => {
17076
+ }) }, hAsync("label", { key: '95de0c0153ddd94c39e15d779ea0e1b3a991a3d9', class: "input-wrapper", htmlFor: inputId, onClick: this.onLabelClick }, this.renderLabelContainer(), hAsync("div", { key: '55d22ffcac1f8c07c5b86df1ae36ff39643143cd', class: "native-wrapper", onClick: this.onLabelClick }, hAsync("slot", { key: '59341c66cace2c718219d1023bd9190dbd41b000', name: "start" }), hAsync("input", Object.assign({ key: 'ab675664758bee4b2717c3914438c85b8b1ebb44', class: "native-input", ref: (input) => (this.nativeInput = input), id: inputId, disabled: disabled, autoCapitalize: this.autocapitalize, autoComplete: this.autocomplete, autoCorrect: this.autocorrect, autoFocus: this.autofocus, enterKeyHint: this.enterkeyhint, inputMode: this.inputmode, min: this.min, max: this.max, minLength: this.minlength, maxLength: this.maxlength, multiple: this.multiple, name: this.name, pattern: this.pattern, placeholder: this.placeholder || '', readOnly: readonly, required: this.required, spellcheck: this.spellcheck, step: this.step, type: this.type, value: value, onInput: this.onInput, onChange: this.onChange, onBlur: this.onBlur, onFocus: this.onFocus, onKeyDown: this.onKeydown, onCompositionstart: this.onCompositionStart, onCompositionend: this.onCompositionEnd, "aria-describedby": this.getHintTextID(), "aria-invalid": this.getHintTextID() === this.errorTextId }, this.inheritedAttributes)), this.clearInput && !readonly && !disabled && (hAsync("button", { key: 'fec4fa631b33151bc31ed9fc4f34970f72fd36f5', "aria-label": "reset", type: "button", class: "input-clear-icon", onPointerDown: (ev) => {
16981
17077
  /**
16982
17078
  * This prevents mobile browsers from
16983
17079
  * blurring the input when the clear
16984
17080
  * button is activated.
16985
17081
  */
16986
17082
  ev.preventDefault();
16987
- }, onClick: this.clearTextInput }, hAsync("ion-icon", { key: '237ec07ec2e10f08818a332bb596578c2c49f770', "aria-hidden": "true", icon: clearIconData }))), hAsync("slot", { key: '1f0a3624aa3e8dc3c307a6762230ab698768a5e5', name: "end" })), shouldRenderHighlight && hAsync("div", { key: '8a8cbb82695a722a0010b53dd0b1f1f97534a20b', class: "input-highlight" })), this.renderBottomContent()));
17083
+ }, onClick: this.clearTextInput }, hAsync("ion-icon", { key: '47bc105137bfad30a5d3c05b11eda552bc643d9a', "aria-hidden": "true", icon: clearIconData }))), hAsync("slot", { key: '6d93afaf67d147dff45e17825d5d8c7a82d7be18', name: "end" })), shouldRenderHighlight && hAsync("div", { key: '7ea437e065d66ba7d143e1c9ad72f4bcdb1e5f01', class: "input-highlight" })), this.renderBottomContent()));
16988
17084
  }
16989
17085
  get el() { return getElement(this); }
16990
17086
  static get watchers() { return {
@@ -25406,6 +25502,23 @@ class PickerColumn {
25406
25502
  var _a;
25407
25503
  return el ? (_a = el.getAttribute('aria-label')) !== null && _a !== void 0 ? _a : el.innerText : '';
25408
25504
  };
25505
+ /**
25506
+ * Render an element that overlays the column. This element is for assistive
25507
+ * tech to allow users to navigate the column up/down. This element should receive
25508
+ * focus as it listens for synthesized keyboard events as required by the
25509
+ * slider role: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Roles/slider_role
25510
+ */
25511
+ this.renderAssistiveFocusable = () => {
25512
+ const { activeItem } = this;
25513
+ const valueText = this.getOptionValueText(activeItem);
25514
+ /**
25515
+ * When using the picker, the valuetext provides important context that valuenow
25516
+ * does not. Additionally, using non-zero valuemin/valuemax values can cause
25517
+ * WebKit to incorrectly announce numeric valuetext values (such as a year
25518
+ * like "2024") as percentages: https://bugs.webkit.org/show_bug.cgi?id=273126
25519
+ */
25520
+ return (hAsync("div", { ref: (el) => (this.assistiveFocusable = el), class: "assistive-focusable", role: "slider", tabindex: this.disabled ? undefined : 0, "aria-label": this.ariaLabel, "aria-valuemin": 0, "aria-valuemax": 0, "aria-valuenow": 0, "aria-valuetext": valueText, "aria-orientation": "vertical", onKeyDown: (ev) => this.onKeyDown(ev) }));
25521
+ };
25409
25522
  }
25410
25523
  ariaLabelChanged(newValue) {
25411
25524
  this.ariaLabel = newValue;
@@ -25546,14 +25659,33 @@ class PickerColumn {
25546
25659
  render() {
25547
25660
  const { color, disabled, isActive, numericInput } = this;
25548
25661
  const mode = getIonMode$1(this);
25549
- return (hAsync(Host, { key: 'db903fd415f8a2d91994dececca481c1af8ba6a9', class: createColorClasses$1(color, {
25662
+ return (hAsync(Host, { key: 'ea0280355b2f87895bf7dddd289ccf473aa759f3', class: createColorClasses$1(color, {
25550
25663
  [mode]: true,
25551
25664
  ['picker-column-active']: isActive,
25552
25665
  ['picker-column-numeric-input']: numericInput,
25553
25666
  ['picker-column-disabled']: disabled,
25554
- }) }, hAsync("slot", { key: '02ce9e1dd7df91afcd50b06416552bcffb5dec98', name: "prefix" }), hAsync("div", { key: '6dfd7d2429bec19244a6b1afb4448121963a031b', class: "picker-opts", ref: (el) => {
25667
+ }) }, this.renderAssistiveFocusable(), hAsync("slot", { key: '482992131cdeb85b1f61430d7fe1322a16345769', name: "prefix" }), hAsync("div", { key: '43f7f80d621d411ef366b3ca1396299e8c9a0c97', "aria-hidden": "true", class: "picker-opts", ref: (el) => {
25555
25668
  this.scrollEl = el;
25556
- }, role: "slider", tabindex: this.disabled ? undefined : 0, "aria-label": this.ariaLabel, "aria-valuemin": 0, "aria-valuemax": 0, "aria-valuenow": 0, "aria-valuetext": this.getOptionValueText(this.activeItem), "aria-orientation": "vertical", onKeyDown: (ev) => this.onKeyDown(ev) }, hAsync("div", { key: 'e30ce0b9cefbfe4d4441fa33acf595da31855c3f', class: "picker-item-empty", "aria-hidden": "true" }, "\u00A0"), hAsync("div", { key: '8be2bd293c12c6ba720d9b31d0d561a96f42e97d', class: "picker-item-empty", "aria-hidden": "true" }, "\u00A0"), hAsync("div", { key: '8afdcddddabbf646fbb55cb0ba4448309a2c1dd9', class: "picker-item-empty", "aria-hidden": "true" }, "\u00A0"), hAsync("slot", { key: '6aa0dacc34d6848575ad5b122b9046982308ca43' }), hAsync("div", { key: '92ec8a357414c1b779b11d1dd18fb87a7ee63982', class: "picker-item-empty", "aria-hidden": "true" }, "\u00A0"), hAsync("div", { key: 'b89457cb74b5907c25594ff6720ac54ca537e933', class: "picker-item-empty", "aria-hidden": "true" }, "\u00A0"), hAsync("div", { key: '5bbc92e6bc24de08e39873bf08c5b668373ac0f8', class: "picker-item-empty", "aria-hidden": "true" }, "\u00A0")), hAsync("slot", { key: 'd7bf2b519214f0f3576a4ca79844ad97827dd97f', name: "suffix" })));
25669
+ },
25670
+ /**
25671
+ * When an element has an overlay scroll style and
25672
+ * a fixed height, Firefox will focus the scrollable
25673
+ * container if the content exceeds the container's
25674
+ * dimensions.
25675
+ *
25676
+ * This causes keyboard navigation to focus to this
25677
+ * element instead of going to the next element in
25678
+ * the tab order.
25679
+ *
25680
+ * The desired behavior is for the user to be able to
25681
+ * focus the assistive focusable element and tab to
25682
+ * the next element in the tab order. Instead of tabbing
25683
+ * to this element.
25684
+ *
25685
+ * To prevent this, we set the tabIndex to -1. This
25686
+ * will match the behavior of the other browsers.
25687
+ */
25688
+ tabIndex: -1 }, hAsync("div", { key: '13a9ee686132af32240710730765de4c0003a9e8', class: "picker-item-empty", "aria-hidden": "true" }, "\u00A0"), hAsync("div", { key: 'dbccba4920833cfcebe9b0fc763458ec3053705a', class: "picker-item-empty", "aria-hidden": "true" }, "\u00A0"), hAsync("div", { key: '682b43f83a5ea2e46067457f3af118535e111edb', class: "picker-item-empty", "aria-hidden": "true" }, "\u00A0"), hAsync("slot", { key: 'd27e1e1dc0504b2f4627a29912a05bb91e8e413a' }), hAsync("div", { key: '61c948dbb9cf7469aed3018542bc0954211585ba', class: "picker-item-empty", "aria-hidden": "true" }, "\u00A0"), hAsync("div", { key: 'cf46c277fbee65e35ff44ce0d53ce12aa9cbf9db', class: "picker-item-empty", "aria-hidden": "true" }, "\u00A0"), hAsync("div", { key: 'bbc0e2d491d3f836ab849493ade2f7fa6ad9244e', class: "picker-item-empty", "aria-hidden": "true" }, "\u00A0")), hAsync("slot", { key: 'd25cbbe14b2914fe7b878d43b4e3f4a8c8177d24', name: "suffix" })));
25557
25689
  }
25558
25690
  get el() { return getElement(this); }
25559
25691
  static get watchers() { return {
@@ -25945,9 +26077,9 @@ const DECELERATION_FRICTION = 0.97;
25945
26077
  const MAX_PICKER_SPEED = 90;
25946
26078
  const TRANSITION_DURATION = 150;
25947
26079
 
25948
- const pickerColumnOptionIosCss = ".picker-column-option-button{padding-left:0;padding-right:0;padding-top:0;padding-bottom:0;margin-left:0;margin-right:0;margin-top:0;margin-bottom:0;width:100%;height:34px;border:0px;outline:none;background:transparent;color:inherit;font-family:var(--ion-font-family, inherit);font-size:inherit;line-height:34px;text-align:inherit;text-overflow:ellipsis;white-space:nowrap;cursor:pointer;overflow:hidden}:host(.option-disabled){opacity:0.4}:host(.option-disabled) .picker-column-option-button{cursor:default}";
26080
+ const pickerColumnOptionIosCss = "button{padding-left:0;padding-right:0;padding-top:0;padding-bottom:0;margin-left:0;margin-right:0;margin-top:0;margin-bottom:0;width:100%;height:34px;border:0px;outline:none;background:transparent;color:inherit;font-family:var(--ion-font-family, inherit);font-size:inherit;line-height:34px;text-align:inherit;text-overflow:ellipsis;white-space:nowrap;cursor:pointer;overflow:hidden}:host(.option-disabled){opacity:0.4}:host(.option-disabled) button{cursor:default}";
25949
26081
 
25950
- const pickerColumnOptionMdCss = ".picker-column-option-button{padding-left:0;padding-right:0;padding-top:0;padding-bottom:0;margin-left:0;margin-right:0;margin-top:0;margin-bottom:0;width:100%;height:34px;border:0px;outline:none;background:transparent;color:inherit;font-family:var(--ion-font-family, inherit);font-size:inherit;line-height:34px;text-align:inherit;text-overflow:ellipsis;white-space:nowrap;cursor:pointer;overflow:hidden}:host(.option-disabled){opacity:0.4}:host(.option-disabled) .picker-column-option-button{cursor:default}:host(.option-active){color:var(--ion-color-base)}";
26082
+ const pickerColumnOptionMdCss = "button{padding-left:0;padding-right:0;padding-top:0;padding-bottom:0;margin-left:0;margin-right:0;margin-top:0;margin-bottom:0;width:100%;height:34px;border:0px;outline:none;background:transparent;color:inherit;font-family:var(--ion-font-family, inherit);font-size:inherit;line-height:34px;text-align:inherit;text-overflow:ellipsis;white-space:nowrap;cursor:pointer;overflow:hidden}:host(.option-disabled){opacity:0.4}:host(.option-disabled) button{cursor:default}:host(.option-active){color:var(--ion-color-base)}";
25951
26083
 
25952
26084
  class PickerColumnOption {
25953
26085
  constructor(hostRef) {
@@ -26039,7 +26171,7 @@ class PickerColumnOption {
26039
26171
  return (hAsync(Host, { key: 'f816729941aabcb31ddfdce3ffe2e2139030d715', class: createColorClasses$1(color, {
26040
26172
  [mode]: true,
26041
26173
  ['option-disabled']: disabled,
26042
- }) }, hAsync("div", { key: 'd942de84fd14d7dc06b1e5cf4f7920d1dc3c6371', class: 'picker-column-option-button', role: "button", "aria-label": ariaLabel, onClick: () => this.onClick() }, hAsync("slot", { key: 'b0df5717b42209e649097209a01476e1a66f5c5c' }))));
26174
+ }) }, hAsync("button", { key: '48dff7833bb60fc8331cd353a0885e6affa683d1', tabindex: "-1", "aria-label": ariaLabel, disabled: disabled, onClick: () => this.onClick() }, hAsync("slot", { key: 'f9224d0e7b7aa6c05b29abfdcfe0f30ad6ee3141' }))));
26043
26175
  }
26044
26176
  get el() { return getElement(this); }
26045
26177
  static get watchers() { return {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ionic/core",
3
- "version": "8.7.3-dev.11755006024.11261c64",
3
+ "version": "8.7.3-dev.11755190119.16c6a375",
4
4
  "description": "Base components for Ionic",
5
5
  "keywords": [
6
6
  "ionic",