@ionic/core 8.0.0-dev.11713809015.1aabd368 → 8.0.0-dev.11713893672.15a2b23e

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.
@@ -80,24 +80,4 @@ describe('picker-column: assistive element', () => {
80
80
  const assistiveFocusable = pickerCol.shadowRoot.querySelector('.assistive-focusable');
81
81
  expect(assistiveFocusable.getAttribute('aria-valuetext')).toBe('My Text');
82
82
  });
83
- it('should have the correct value count attributes', async () => {
84
- const page = await newSpecPage({
85
- components: [PickerColumn, PickerColumnOption],
86
- template: () => (h("ion-picker-column", { value: 2 }, h("ion-picker-column-option", { value: 1 }, "My Text"), h("ion-picker-column-option", { value: 2 }, "My Text"), h("ion-picker-column-option", { value: 3 }, "My Text"))),
87
- });
88
- const pickerCol = page.body.querySelector('ion-picker-column');
89
- const assistiveFocusable = pickerCol.shadowRoot.querySelector('.assistive-focusable');
90
- expect(assistiveFocusable.getAttribute('aria-valuemin')).toBe('0');
91
- expect(assistiveFocusable.getAttribute('aria-valuemax')).toBe('2');
92
- expect(assistiveFocusable.getAttribute('aria-valuenow')).toBe('1');
93
- });
94
- it('should clamp the value now attributes', async () => {
95
- const page = await newSpecPage({
96
- components: [PickerColumn, PickerColumnOption],
97
- template: () => (h("ion-picker-column", null, h("ion-picker-column-option", { value: 1 }, "My Text"), h("ion-picker-column-option", { value: 2 }, "My Text"), h("ion-picker-column-option", { value: 3 }, "My Text"))),
98
- });
99
- const pickerCol = page.body.querySelector('ion-picker-column');
100
- const assistiveFocusable = pickerCol.shadowRoot.querySelector('.assistive-focusable');
101
- expect(assistiveFocusable.getAttribute('aria-valuenow')).toBe('0');
102
- });
103
83
  });
package/dist/docs.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "timestamp": "2024-04-22T18:05:39",
2
+ "timestamp": "2024-04-23T17:36:43",
3
3
  "compiler": {
4
4
  "name": "@stencil/core",
5
5
  "version": "4.14.0",
@@ -1448,7 +1448,7 @@ const Datetime = class {
1448
1448
  }
1449
1449
  const activePart = this.getActivePartsWithFallback();
1450
1450
  const isDayPeriodRTL = isLocaleDayPeriodRTL(this.locale);
1451
- return (h("ion-picker-column", { "aria-label": "Select a day", style: isDayPeriodRTL ? { order: '-1' } : {}, color: this.color, disabled: disabled, value: activePart.ampm, onIonChange: (ev) => {
1451
+ return (h("ion-picker-column", { "aria-label": "Select a day period", style: isDayPeriodRTL ? { order: '-1' } : {}, color: this.color, disabled: disabled, value: activePart.ampm, onIonChange: (ev) => {
1452
1452
  const hour = calculateHourFromAMPM(workingParts, ev.detail.value);
1453
1453
  this.setWorkingParts(Object.assign(Object.assign({}, workingParts), { ampm: ev.detail.value, hour }));
1454
1454
  this.setActiveParts(Object.assign(Object.assign({}, activePart), { ampm: ev.detail.value, hour }));
@@ -1758,7 +1758,7 @@ const Datetime = class {
1758
1758
  const hasDatePresentation = presentation === 'date' || presentation === 'date-time' || presentation === 'time-date';
1759
1759
  const hasWheelVariant = hasDatePresentation && preferWheel;
1760
1760
  renderHiddenInput(true, el, name, formatValue(value), disabled);
1761
- return (h(Host, { key: 'ea2ff775f17d5990cb9bb56a1372986e40b94fab', "aria-disabled": disabled ? 'true' : null, onFocus: this.onFocus, onBlur: this.onBlur, class: Object.assign({}, createColorClasses(color, {
1761
+ return (h(Host, { key: '131cd9d8f73805ea76158c0ad05d86809fe8dfce', "aria-disabled": disabled ? 'true' : null, onFocus: this.onFocus, onBlur: this.onBlur, class: Object.assign({}, createColorClasses(color, {
1762
1762
  [mode]: true,
1763
1763
  ['datetime-readonly']: readonly,
1764
1764
  ['datetime-disabled']: disabled,
@@ -1768,7 +1768,7 @@ const Datetime = class {
1768
1768
  [`datetime-size-${size}`]: true,
1769
1769
  [`datetime-prefer-wheel`]: hasWheelVariant,
1770
1770
  [`datetime-grid`]: isGridStyle,
1771
- })) }, h("div", { key: 'acc8a91a57d090c0092066f543d921792b7cbed2', class: "intersection-tracker", ref: (el) => (this.intersectionTrackerRef = el) }), this.renderDatetime(mode)));
1771
+ })) }, h("div", { key: '3be6976d484d9ccebac77630b2fd66388b2b85e4', class: "intersection-tracker", ref: (el) => (this.intersectionTrackerRef = el) }), this.renderDatetime(mode)));
1772
1772
  }
1773
1773
  get el() { return getElement(this); }
1774
1774
  static get watchers() { return {
@@ -19,6 +19,7 @@ const PickerColumn = class {
19
19
  this.isScrolling = false;
20
20
  this.isColumnVisible = false;
21
21
  this.canExitInputMode = true;
22
+ this.updateValueTextOnScroll = false;
22
23
  this.centerPickerItemInView = (target, smooth = true, canExitInputMode = true) => {
23
24
  const { isColumnVisible, scrollEl } = this;
24
25
  if (isColumnVisible && scrollEl) {
@@ -33,6 +34,7 @@ const PickerColumn = class {
33
34
  * of these can cause a scroll to occur.
34
35
  */
35
36
  this.canExitInputMode = canExitInputMode;
37
+ this.updateValueTextOnScroll = false;
36
38
  scrollEl.scroll({
37
39
  top,
38
40
  left: 0,
@@ -102,9 +104,10 @@ const PickerColumn = class {
102
104
  const enableHaptics = isPlatform('ios');
103
105
  const { el, scrollEl } = this;
104
106
  let timeout;
105
- let { activeItem: activeEl } = this.activeItem;
107
+ let activeEl = this.activeItem;
106
108
  const scrollCallback = () => {
107
109
  raf(() => {
110
+ var _a;
108
111
  if (!scrollEl)
109
112
  return;
110
113
  if (timeout) {
@@ -185,8 +188,23 @@ const PickerColumn = class {
185
188
  }
186
189
  activeEl = newActiveElement;
187
190
  this.setPickerItemActiveState(newActiveElement, true);
191
+ /**
192
+ * Set the aria-valuetext even though the value prop has not been updated yet.
193
+ * This enables some screen readers to announce the value as the users drag
194
+ * as opposed to when their release their pointer from the screen.
195
+ *
196
+ * When the value is programmatically updated, we will smoothly scroll
197
+ * to the new option. However, we do not want to update aria-valuetext mid-scroll
198
+ * as that can cause the old value to be briefly set before being set to the
199
+ * correct option. This will cause some screen readers to announce the old value
200
+ * again before announcing the new value. The correct valuetext will be set on render.
201
+ */
202
+ if (this.updateValueTextOnScroll) {
203
+ (_a = this.assistiveFocusable) === null || _a === void 0 ? void 0 : _a.setAttribute('aria-valuetext', this.getOptionValueText(newActiveElement));
204
+ }
188
205
  timeout = setTimeout(() => {
189
206
  this.isScrolling = false;
207
+ this.updateValueTextOnScroll = true;
190
208
  enableHaptics && hapticSelectionEnd();
191
209
  /**
192
210
  * Certain tasks (such as those that
@@ -254,7 +272,7 @@ const PickerColumn = class {
254
272
  * may be past the stride if the option at the stride is disabled.
255
273
  */
256
274
  this.findNextOption = (stride = 1) => {
257
- const { activeItem } = this.activeItem;
275
+ const { activeItem } = this;
258
276
  if (!activeItem)
259
277
  return null;
260
278
  let prevNode = activeItem;
@@ -281,7 +299,7 @@ const PickerColumn = class {
281
299
  * may be past the stride if the option at the stride is disabled.
282
300
  */
283
301
  this.findPreviousOption = (stride = 1) => {
284
- const { activeItem } = this.activeItem;
302
+ const { activeItem } = this;
285
303
  if (!activeItem)
286
304
  return null;
287
305
  let nextNode = activeItem;
@@ -335,6 +353,13 @@ const PickerColumn = class {
335
353
  ev.preventDefault();
336
354
  }
337
355
  };
356
+ /**
357
+ * Utility to generate the correct text for aria-valuetext.
358
+ */
359
+ this.getOptionValueText = (el) => {
360
+ var _a;
361
+ return el ? (_a = el.getAttribute('aria-label')) !== null && _a !== void 0 ? _a : el.innerText : '';
362
+ };
338
363
  /**
339
364
  * Render an element that overlays the column. This element is for assistive
340
365
  * tech to allow users to navigate the column up/down. This element should receive
@@ -342,11 +367,15 @@ const PickerColumn = class {
342
367
  * slider role: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Roles/slider_role
343
368
  */
344
369
  this.renderAssistiveFocusable = () => {
345
- var _a;
346
- const { activeItem, activeItemIndex } = this.activeItem;
347
- const { el } = this;
348
- const valueText = activeItem ? (_a = activeItem.getAttribute('aria-label')) !== null && _a !== void 0 ? _a : activeItem.innerText : '';
349
- return (h("div", { class: "assistive-focusable", role: "slider", tabindex: this.disabled ? undefined : 0, "aria-label": this.ariaLabel, "aria-valuemin": 0, "aria-valuemax": el.childElementCount - 1, "aria-valuenow": activeItemIndex >= 0 ? activeItemIndex : 0, "aria-valuetext": valueText, "aria-orientation": "vertical", onKeyDown: (ev) => this.onKeyDown(ev) }));
370
+ const { activeItem } = this;
371
+ const valueText = this.getOptionValueText(activeItem);
372
+ /**
373
+ * When using the picker, the valuetext provides important context that valuenow
374
+ * does not. Additionally, using non-zero valuemin/valuemax values can cause
375
+ * WebKit to incorrectly announce numeric valuetext values (such as a year
376
+ * like "2024") as percentages: https://bugs.webkit.org/show_bug.cgi?id=273126
377
+ */
378
+ return (h("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) }));
350
379
  };
351
380
  this.ariaLabel = null;
352
381
  this.isActive = false;
@@ -388,8 +417,7 @@ const PickerColumn = class {
388
417
  */
389
418
  const ev = entries[entries.length - 1];
390
419
  if (ev.isIntersecting) {
391
- const { activeItem } = this.activeItem;
392
- const { el } = this;
420
+ const { activeItem, el } = this;
393
421
  this.isColumnVisible = true;
394
422
  /**
395
423
  * Because this initial call to scrollActiveItemIntoView has to fire before
@@ -429,8 +457,7 @@ const PickerColumn = class {
429
457
  }
430
458
  }
431
459
  componentDidRender() {
432
- const { activeItem } = this.activeItem;
433
- const { el, isColumnVisible, value } = this;
460
+ const { el, activeItem, isColumnVisible, value } = this;
434
461
  if (isColumnVisible && !activeItem) {
435
462
  const firstOption = el.querySelector('ion-picker-column-option');
436
463
  /**
@@ -447,7 +474,7 @@ const PickerColumn = class {
447
474
  }
448
475
  /** @internal */
449
476
  async scrollActiveItemIntoView(smooth = false) {
450
- const { activeItem: activeEl } = this.activeItem;
477
+ const activeEl = this.activeItem;
451
478
  if (activeEl) {
452
479
  this.centerPickerItemInView(activeEl, smooth, false);
453
480
  }
@@ -481,33 +508,29 @@ const PickerColumn = class {
481
508
  }
482
509
  get activeItem() {
483
510
  const { value } = this;
484
- const options = this.el.querySelectorAll('ion-picker-column-option');
485
- for (let i = 0; i <= options.length - 1; i++) {
486
- const option = options[i];
511
+ const options = Array.from(this.el.querySelectorAll('ion-picker-column-option'));
512
+ return options.find((option) => {
487
513
  /**
488
514
  * If the whole picker column is disabled, the current value should appear active
489
515
  * If the current value item is specifically disabled, it should not appear active
490
516
  */
491
- if (option.value === value && !option.disabled) {
492
- return {
493
- activeItem: option,
494
- activeItemIndex: i,
495
- };
517
+ if (!this.disabled && option.disabled) {
518
+ return false;
496
519
  }
497
- }
498
- return { activeItem: undefined, activeItemIndex: -1 };
520
+ return option.value === value;
521
+ });
499
522
  }
500
523
  render() {
501
524
  const { color, disabled, isActive, numericInput } = this;
502
525
  const mode = getIonMode(this);
503
- return (h(Host, { key: '87534568ba47096dca1be00fee184052767087f5', class: createColorClasses(color, {
526
+ return (h(Host, { key: '50fe50a49f88aa9ec435436083f3cd1ef49c8c9c', class: createColorClasses(color, {
504
527
  [mode]: true,
505
528
  ['picker-column-active']: isActive,
506
529
  ['picker-column-numeric-input']: numericInput,
507
530
  ['picker-column-disabled']: disabled,
508
- }) }, this.renderAssistiveFocusable(), h("slot", { key: '8dedc4f294f1a6658a12151a765f6fa790f4d854', name: "prefix" }), h("div", { key: 'c82975dc3996d3ddb8dee12ad381ee733466a069', "aria-hidden": "true", class: "picker-opts", ref: (el) => {
531
+ }) }, this.renderAssistiveFocusable(), h("slot", { key: '6350829748690895ab3ef101b9f2ae993852de7d', name: "prefix" }), h("div", { key: 'eaff9925aa8553f63ba2a1ae2bdfaa02963e0a5d', "aria-hidden": "true", class: "picker-opts", ref: (el) => {
509
532
  this.scrollEl = el;
510
- } }, h("div", { key: '2de49979f9339f4a9a384e115ea5a073b6467e50', class: "picker-item-empty", "aria-hidden": "true" }, "\u00A0"), h("div", { key: '304e0bcc506f4c4d35d053e95c85de9c9bdc303c', class: "picker-item-empty", "aria-hidden": "true" }, "\u00A0"), h("div", { key: '3da0eb1d7e1d8b196112f7d695447b40716eef1d', class: "picker-item-empty", "aria-hidden": "true" }, "\u00A0"), h("slot", { key: '43668a05c3eb39749bde1137e33872e1b406cba9' }), h("div", { key: '95d4ae922ad45aa541a70b08958b08a2d3c79fbe', class: "picker-item-empty", "aria-hidden": "true" }, "\u00A0"), h("div", { key: '412aca51c2d3b4cc1bcc1fffca68922db64f7745', class: "picker-item-empty", "aria-hidden": "true" }, "\u00A0"), h("div", { key: '2319fa61c7649dec3efa2ec2e7b93d5e9a775708', class: "picker-item-empty", "aria-hidden": "true" }, "\u00A0")), h("slot", { key: '010cee6ffdbe1a6d5331cb4e185b1aa0b6effd2d', name: "suffix" })));
533
+ } }, h("div", { key: '25a24c4174782f2ec8a1fe06cbaf1f564b1f632f', class: "picker-item-empty", "aria-hidden": "true" }, "\u00A0"), h("div", { key: '7f4e9a5f1f74f7e8d5ad74178894edc80c0fb523', class: "picker-item-empty", "aria-hidden": "true" }, "\u00A0"), h("div", { key: '329b88b4af1d0e37da347e5f3fe9b462efcc2886', class: "picker-item-empty", "aria-hidden": "true" }, "\u00A0"), h("slot", { key: '82b9d5d541d41801bce06db0867d6cfbcee4ac3e' }), h("div", { key: '288ae193601d1eb49ead06f79eb1affa478f31d3', class: "picker-item-empty", "aria-hidden": "true" }, "\u00A0"), h("div", { key: '29661d0b74d11d650c2b23be66f857dd008dc5a0', class: "picker-item-empty", "aria-hidden": "true" }, "\u00A0"), h("div", { key: 'a7bd71b4abcb027654a828ffa65d87b6874d7484', class: "picker-item-empty", "aria-hidden": "true" }, "\u00A0")), h("slot", { key: '83ddd19d09ec48fe31b51f9f272a562320f90098', name: "suffix" })));
511
534
  }
512
535
  get el() { return getElement(this); }
513
536
  static get watchers() { return {