@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.
- package/components/ion-datetime.js +3 -3
- package/components/picker-column.js +49 -26
- package/dist/cjs/ion-datetime_3.cjs.entry.js +3 -3
- package/dist/cjs/ion-picker-column.cjs.entry.js +49 -26
- package/dist/collection/components/datetime/datetime.js +3 -3
- package/dist/collection/components/picker-column/picker-column.js +49 -26
- package/dist/collection/components/picker-column/test/picker-column.spec.js +0 -20
- package/dist/docs.json +1 -1
- package/dist/esm/ion-datetime_3.entry.js +3 -3
- package/dist/esm/ion-picker-column.entry.js +49 -26
- package/dist/esm-es5/ion-datetime_3.entry.js +1 -1
- package/dist/esm-es5/ion-picker-column.entry.js +1 -1
- package/dist/ionic/ionic.esm.js +1 -1
- package/dist/ionic/p-24a98ee7.entry.js +4 -0
- package/dist/ionic/p-3232c4de.entry.js +4 -0
- package/dist/ionic/p-587258c0.system.entry.js +4 -0
- package/dist/ionic/{p-e8c7fa1b.system.entry.js → p-92e46b28.system.entry.js} +1 -1
- package/dist/ionic/p-c478747f.system.js +1 -1
- package/dist/types/components/picker-column/picker-column.d.ts +7 -4
- package/hydrate/index.js +52 -29
- package/package.json +1 -1
- package/dist/ionic/p-0307a5ce.entry.js +0 -4
- package/dist/ionic/p-9958874b.system.entry.js +0 -4
- package/dist/ionic/p-bae993f0.entry.js +0 -4
|
@@ -1450,7 +1450,7 @@ const Datetime = /*@__PURE__*/ proxyCustomElement(class Datetime extends HTMLEle
|
|
|
1450
1450
|
}
|
|
1451
1451
|
const activePart = this.getActivePartsWithFallback();
|
|
1452
1452
|
const isDayPeriodRTL = isLocaleDayPeriodRTL(this.locale);
|
|
1453
|
-
return (h("ion-picker-column", { "aria-label": "Select a day", style: isDayPeriodRTL ? { order: '-1' } : {}, color: this.color, disabled: disabled, value: activePart.ampm, onIonChange: (ev) => {
|
|
1453
|
+
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) => {
|
|
1454
1454
|
const hour = calculateHourFromAMPM(workingParts, ev.detail.value);
|
|
1455
1455
|
this.setWorkingParts(Object.assign(Object.assign({}, workingParts), { ampm: ev.detail.value, hour }));
|
|
1456
1456
|
this.setActiveParts(Object.assign(Object.assign({}, activePart), { ampm: ev.detail.value, hour }));
|
|
@@ -1760,7 +1760,7 @@ const Datetime = /*@__PURE__*/ proxyCustomElement(class Datetime extends HTMLEle
|
|
|
1760
1760
|
const hasDatePresentation = presentation === 'date' || presentation === 'date-time' || presentation === 'time-date';
|
|
1761
1761
|
const hasWheelVariant = hasDatePresentation && preferWheel;
|
|
1762
1762
|
renderHiddenInput(true, el, name, formatValue(value), disabled);
|
|
1763
|
-
return (h(Host, { key: '
|
|
1763
|
+
return (h(Host, { key: '131cd9d8f73805ea76158c0ad05d86809fe8dfce', "aria-disabled": disabled ? 'true' : null, onFocus: this.onFocus, onBlur: this.onBlur, class: Object.assign({}, createColorClasses(color, {
|
|
1764
1764
|
[mode]: true,
|
|
1765
1765
|
['datetime-readonly']: readonly,
|
|
1766
1766
|
['datetime-disabled']: disabled,
|
|
@@ -1770,7 +1770,7 @@ const Datetime = /*@__PURE__*/ proxyCustomElement(class Datetime extends HTMLEle
|
|
|
1770
1770
|
[`datetime-size-${size}`]: true,
|
|
1771
1771
|
[`datetime-prefer-wheel`]: hasWheelVariant,
|
|
1772
1772
|
[`datetime-grid`]: isGridStyle,
|
|
1773
|
-
})) }, h("div", { key: '
|
|
1773
|
+
})) }, h("div", { key: '3be6976d484d9ccebac77630b2fd66388b2b85e4', class: "intersection-tracker", ref: (el) => (this.intersectionTrackerRef = el) }), this.renderDatetime(mode)));
|
|
1774
1774
|
}
|
|
1775
1775
|
get el() { return this; }
|
|
1776
1776
|
static get watchers() { return {
|
|
@@ -20,6 +20,7 @@ const PickerColumn = /*@__PURE__*/ proxyCustomElement(class PickerColumn extends
|
|
|
20
20
|
this.isScrolling = false;
|
|
21
21
|
this.isColumnVisible = false;
|
|
22
22
|
this.canExitInputMode = true;
|
|
23
|
+
this.updateValueTextOnScroll = false;
|
|
23
24
|
this.centerPickerItemInView = (target, smooth = true, canExitInputMode = true) => {
|
|
24
25
|
const { isColumnVisible, scrollEl } = this;
|
|
25
26
|
if (isColumnVisible && scrollEl) {
|
|
@@ -34,6 +35,7 @@ const PickerColumn = /*@__PURE__*/ proxyCustomElement(class PickerColumn extends
|
|
|
34
35
|
* of these can cause a scroll to occur.
|
|
35
36
|
*/
|
|
36
37
|
this.canExitInputMode = canExitInputMode;
|
|
38
|
+
this.updateValueTextOnScroll = false;
|
|
37
39
|
scrollEl.scroll({
|
|
38
40
|
top,
|
|
39
41
|
left: 0,
|
|
@@ -103,9 +105,10 @@ const PickerColumn = /*@__PURE__*/ proxyCustomElement(class PickerColumn extends
|
|
|
103
105
|
const enableHaptics = isPlatform('ios');
|
|
104
106
|
const { el, scrollEl } = this;
|
|
105
107
|
let timeout;
|
|
106
|
-
let
|
|
108
|
+
let activeEl = this.activeItem;
|
|
107
109
|
const scrollCallback = () => {
|
|
108
110
|
raf(() => {
|
|
111
|
+
var _a;
|
|
109
112
|
if (!scrollEl)
|
|
110
113
|
return;
|
|
111
114
|
if (timeout) {
|
|
@@ -186,8 +189,23 @@ const PickerColumn = /*@__PURE__*/ proxyCustomElement(class PickerColumn extends
|
|
|
186
189
|
}
|
|
187
190
|
activeEl = newActiveElement;
|
|
188
191
|
this.setPickerItemActiveState(newActiveElement, true);
|
|
192
|
+
/**
|
|
193
|
+
* Set the aria-valuetext even though the value prop has not been updated yet.
|
|
194
|
+
* This enables some screen readers to announce the value as the users drag
|
|
195
|
+
* as opposed to when their release their pointer from the screen.
|
|
196
|
+
*
|
|
197
|
+
* When the value is programmatically updated, we will smoothly scroll
|
|
198
|
+
* to the new option. However, we do not want to update aria-valuetext mid-scroll
|
|
199
|
+
* as that can cause the old value to be briefly set before being set to the
|
|
200
|
+
* correct option. This will cause some screen readers to announce the old value
|
|
201
|
+
* again before announcing the new value. The correct valuetext will be set on render.
|
|
202
|
+
*/
|
|
203
|
+
if (this.updateValueTextOnScroll) {
|
|
204
|
+
(_a = this.assistiveFocusable) === null || _a === void 0 ? void 0 : _a.setAttribute('aria-valuetext', this.getOptionValueText(newActiveElement));
|
|
205
|
+
}
|
|
189
206
|
timeout = setTimeout(() => {
|
|
190
207
|
this.isScrolling = false;
|
|
208
|
+
this.updateValueTextOnScroll = true;
|
|
191
209
|
enableHaptics && hapticSelectionEnd();
|
|
192
210
|
/**
|
|
193
211
|
* Certain tasks (such as those that
|
|
@@ -255,7 +273,7 @@ const PickerColumn = /*@__PURE__*/ proxyCustomElement(class PickerColumn extends
|
|
|
255
273
|
* may be past the stride if the option at the stride is disabled.
|
|
256
274
|
*/
|
|
257
275
|
this.findNextOption = (stride = 1) => {
|
|
258
|
-
const { activeItem } = this
|
|
276
|
+
const { activeItem } = this;
|
|
259
277
|
if (!activeItem)
|
|
260
278
|
return null;
|
|
261
279
|
let prevNode = activeItem;
|
|
@@ -282,7 +300,7 @@ const PickerColumn = /*@__PURE__*/ proxyCustomElement(class PickerColumn extends
|
|
|
282
300
|
* may be past the stride if the option at the stride is disabled.
|
|
283
301
|
*/
|
|
284
302
|
this.findPreviousOption = (stride = 1) => {
|
|
285
|
-
const { activeItem } = this
|
|
303
|
+
const { activeItem } = this;
|
|
286
304
|
if (!activeItem)
|
|
287
305
|
return null;
|
|
288
306
|
let nextNode = activeItem;
|
|
@@ -336,6 +354,13 @@ const PickerColumn = /*@__PURE__*/ proxyCustomElement(class PickerColumn extends
|
|
|
336
354
|
ev.preventDefault();
|
|
337
355
|
}
|
|
338
356
|
};
|
|
357
|
+
/**
|
|
358
|
+
* Utility to generate the correct text for aria-valuetext.
|
|
359
|
+
*/
|
|
360
|
+
this.getOptionValueText = (el) => {
|
|
361
|
+
var _a;
|
|
362
|
+
return el ? (_a = el.getAttribute('aria-label')) !== null && _a !== void 0 ? _a : el.innerText : '';
|
|
363
|
+
};
|
|
339
364
|
/**
|
|
340
365
|
* Render an element that overlays the column. This element is for assistive
|
|
341
366
|
* tech to allow users to navigate the column up/down. This element should receive
|
|
@@ -343,11 +368,15 @@ const PickerColumn = /*@__PURE__*/ proxyCustomElement(class PickerColumn extends
|
|
|
343
368
|
* slider role: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Roles/slider_role
|
|
344
369
|
*/
|
|
345
370
|
this.renderAssistiveFocusable = () => {
|
|
346
|
-
|
|
347
|
-
const
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
371
|
+
const { activeItem } = this;
|
|
372
|
+
const valueText = this.getOptionValueText(activeItem);
|
|
373
|
+
/**
|
|
374
|
+
* When using the picker, the valuetext provides important context that valuenow
|
|
375
|
+
* does not. Additionally, using non-zero valuemin/valuemax values can cause
|
|
376
|
+
* WebKit to incorrectly announce numeric valuetext values (such as a year
|
|
377
|
+
* like "2024") as percentages: https://bugs.webkit.org/show_bug.cgi?id=273126
|
|
378
|
+
*/
|
|
379
|
+
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) }));
|
|
351
380
|
};
|
|
352
381
|
this.ariaLabel = null;
|
|
353
382
|
this.isActive = false;
|
|
@@ -389,8 +418,7 @@ const PickerColumn = /*@__PURE__*/ proxyCustomElement(class PickerColumn extends
|
|
|
389
418
|
*/
|
|
390
419
|
const ev = entries[entries.length - 1];
|
|
391
420
|
if (ev.isIntersecting) {
|
|
392
|
-
const { activeItem } = this
|
|
393
|
-
const { el } = this;
|
|
421
|
+
const { activeItem, el } = this;
|
|
394
422
|
this.isColumnVisible = true;
|
|
395
423
|
/**
|
|
396
424
|
* Because this initial call to scrollActiveItemIntoView has to fire before
|
|
@@ -430,8 +458,7 @@ const PickerColumn = /*@__PURE__*/ proxyCustomElement(class PickerColumn extends
|
|
|
430
458
|
}
|
|
431
459
|
}
|
|
432
460
|
componentDidRender() {
|
|
433
|
-
const { activeItem } = this
|
|
434
|
-
const { el, isColumnVisible, value } = this;
|
|
461
|
+
const { el, activeItem, isColumnVisible, value } = this;
|
|
435
462
|
if (isColumnVisible && !activeItem) {
|
|
436
463
|
const firstOption = el.querySelector('ion-picker-column-option');
|
|
437
464
|
/**
|
|
@@ -448,7 +475,7 @@ const PickerColumn = /*@__PURE__*/ proxyCustomElement(class PickerColumn extends
|
|
|
448
475
|
}
|
|
449
476
|
/** @internal */
|
|
450
477
|
async scrollActiveItemIntoView(smooth = false) {
|
|
451
|
-
const
|
|
478
|
+
const activeEl = this.activeItem;
|
|
452
479
|
if (activeEl) {
|
|
453
480
|
this.centerPickerItemInView(activeEl, smooth, false);
|
|
454
481
|
}
|
|
@@ -482,33 +509,29 @@ const PickerColumn = /*@__PURE__*/ proxyCustomElement(class PickerColumn extends
|
|
|
482
509
|
}
|
|
483
510
|
get activeItem() {
|
|
484
511
|
const { value } = this;
|
|
485
|
-
const options = this.el.querySelectorAll('ion-picker-column-option');
|
|
486
|
-
|
|
487
|
-
const option = options[i];
|
|
512
|
+
const options = Array.from(this.el.querySelectorAll('ion-picker-column-option'));
|
|
513
|
+
return options.find((option) => {
|
|
488
514
|
/**
|
|
489
515
|
* If the whole picker column is disabled, the current value should appear active
|
|
490
516
|
* If the current value item is specifically disabled, it should not appear active
|
|
491
517
|
*/
|
|
492
|
-
if (
|
|
493
|
-
return
|
|
494
|
-
activeItem: option,
|
|
495
|
-
activeItemIndex: i,
|
|
496
|
-
};
|
|
518
|
+
if (!this.disabled && option.disabled) {
|
|
519
|
+
return false;
|
|
497
520
|
}
|
|
498
|
-
|
|
499
|
-
|
|
521
|
+
return option.value === value;
|
|
522
|
+
});
|
|
500
523
|
}
|
|
501
524
|
render() {
|
|
502
525
|
const { color, disabled, isActive, numericInput } = this;
|
|
503
526
|
const mode = getIonMode(this);
|
|
504
|
-
return (h(Host, { key: '
|
|
527
|
+
return (h(Host, { key: '50fe50a49f88aa9ec435436083f3cd1ef49c8c9c', class: createColorClasses(color, {
|
|
505
528
|
[mode]: true,
|
|
506
529
|
['picker-column-active']: isActive,
|
|
507
530
|
['picker-column-numeric-input']: numericInput,
|
|
508
531
|
['picker-column-disabled']: disabled,
|
|
509
|
-
}) }, this.renderAssistiveFocusable(), h("slot", { key: '
|
|
532
|
+
}) }, this.renderAssistiveFocusable(), h("slot", { key: '6350829748690895ab3ef101b9f2ae993852de7d', name: "prefix" }), h("div", { key: 'eaff9925aa8553f63ba2a1ae2bdfaa02963e0a5d', "aria-hidden": "true", class: "picker-opts", ref: (el) => {
|
|
510
533
|
this.scrollEl = el;
|
|
511
|
-
} }, h("div", { key: '
|
|
534
|
+
} }, 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" })));
|
|
512
535
|
}
|
|
513
536
|
get el() { return this; }
|
|
514
537
|
static get watchers() { return {
|
|
@@ -1452,7 +1452,7 @@ const Datetime = class {
|
|
|
1452
1452
|
}
|
|
1453
1453
|
const activePart = this.getActivePartsWithFallback();
|
|
1454
1454
|
const isDayPeriodRTL = data.isLocaleDayPeriodRTL(this.locale);
|
|
1455
|
-
return (index$1.h("ion-picker-column", { "aria-label": "Select a day", style: isDayPeriodRTL ? { order: '-1' } : {}, color: this.color, disabled: disabled, value: activePart.ampm, onIonChange: (ev) => {
|
|
1455
|
+
return (index$1.h("ion-picker-column", { "aria-label": "Select a day period", style: isDayPeriodRTL ? { order: '-1' } : {}, color: this.color, disabled: disabled, value: activePart.ampm, onIonChange: (ev) => {
|
|
1456
1456
|
const hour = data.calculateHourFromAMPM(workingParts, ev.detail.value);
|
|
1457
1457
|
this.setWorkingParts(Object.assign(Object.assign({}, workingParts), { ampm: ev.detail.value, hour }));
|
|
1458
1458
|
this.setActiveParts(Object.assign(Object.assign({}, activePart), { ampm: ev.detail.value, hour }));
|
|
@@ -1762,7 +1762,7 @@ const Datetime = class {
|
|
|
1762
1762
|
const hasDatePresentation = presentation === 'date' || presentation === 'date-time' || presentation === 'time-date';
|
|
1763
1763
|
const hasWheelVariant = hasDatePresentation && preferWheel;
|
|
1764
1764
|
helpers.renderHiddenInput(true, el, name, data.formatValue(value), disabled);
|
|
1765
|
-
return (index$1.h(index$1.Host, { key: '
|
|
1765
|
+
return (index$1.h(index$1.Host, { key: '131cd9d8f73805ea76158c0ad05d86809fe8dfce', "aria-disabled": disabled ? 'true' : null, onFocus: this.onFocus, onBlur: this.onBlur, class: Object.assign({}, theme.createColorClasses(color, {
|
|
1766
1766
|
[mode]: true,
|
|
1767
1767
|
['datetime-readonly']: readonly,
|
|
1768
1768
|
['datetime-disabled']: disabled,
|
|
@@ -1772,7 +1772,7 @@ const Datetime = class {
|
|
|
1772
1772
|
[`datetime-size-${size}`]: true,
|
|
1773
1773
|
[`datetime-prefer-wheel`]: hasWheelVariant,
|
|
1774
1774
|
[`datetime-grid`]: isGridStyle,
|
|
1775
|
-
})) }, index$1.h("div", { key: '
|
|
1775
|
+
})) }, index$1.h("div", { key: '3be6976d484d9ccebac77630b2fd66388b2b85e4', class: "intersection-tracker", ref: (el) => (this.intersectionTrackerRef = el) }), this.renderDatetime(mode)));
|
|
1776
1776
|
}
|
|
1777
1777
|
get el() { return index$1.getElement(this); }
|
|
1778
1778
|
static get watchers() { return {
|
|
@@ -23,6 +23,7 @@ const PickerColumn = class {
|
|
|
23
23
|
this.isScrolling = false;
|
|
24
24
|
this.isColumnVisible = false;
|
|
25
25
|
this.canExitInputMode = true;
|
|
26
|
+
this.updateValueTextOnScroll = false;
|
|
26
27
|
this.centerPickerItemInView = (target, smooth = true, canExitInputMode = true) => {
|
|
27
28
|
const { isColumnVisible, scrollEl } = this;
|
|
28
29
|
if (isColumnVisible && scrollEl) {
|
|
@@ -37,6 +38,7 @@ const PickerColumn = class {
|
|
|
37
38
|
* of these can cause a scroll to occur.
|
|
38
39
|
*/
|
|
39
40
|
this.canExitInputMode = canExitInputMode;
|
|
41
|
+
this.updateValueTextOnScroll = false;
|
|
40
42
|
scrollEl.scroll({
|
|
41
43
|
top,
|
|
42
44
|
left: 0,
|
|
@@ -106,9 +108,10 @@ const PickerColumn = class {
|
|
|
106
108
|
const enableHaptics = ionicGlobal.isPlatform('ios');
|
|
107
109
|
const { el, scrollEl } = this;
|
|
108
110
|
let timeout;
|
|
109
|
-
let
|
|
111
|
+
let activeEl = this.activeItem;
|
|
110
112
|
const scrollCallback = () => {
|
|
111
113
|
helpers.raf(() => {
|
|
114
|
+
var _a;
|
|
112
115
|
if (!scrollEl)
|
|
113
116
|
return;
|
|
114
117
|
if (timeout) {
|
|
@@ -189,8 +192,23 @@ const PickerColumn = class {
|
|
|
189
192
|
}
|
|
190
193
|
activeEl = newActiveElement;
|
|
191
194
|
this.setPickerItemActiveState(newActiveElement, true);
|
|
195
|
+
/**
|
|
196
|
+
* Set the aria-valuetext even though the value prop has not been updated yet.
|
|
197
|
+
* This enables some screen readers to announce the value as the users drag
|
|
198
|
+
* as opposed to when their release their pointer from the screen.
|
|
199
|
+
*
|
|
200
|
+
* When the value is programmatically updated, we will smoothly scroll
|
|
201
|
+
* to the new option. However, we do not want to update aria-valuetext mid-scroll
|
|
202
|
+
* as that can cause the old value to be briefly set before being set to the
|
|
203
|
+
* correct option. This will cause some screen readers to announce the old value
|
|
204
|
+
* again before announcing the new value. The correct valuetext will be set on render.
|
|
205
|
+
*/
|
|
206
|
+
if (this.updateValueTextOnScroll) {
|
|
207
|
+
(_a = this.assistiveFocusable) === null || _a === void 0 ? void 0 : _a.setAttribute('aria-valuetext', this.getOptionValueText(newActiveElement));
|
|
208
|
+
}
|
|
192
209
|
timeout = setTimeout(() => {
|
|
193
210
|
this.isScrolling = false;
|
|
211
|
+
this.updateValueTextOnScroll = true;
|
|
194
212
|
enableHaptics && haptic.hapticSelectionEnd();
|
|
195
213
|
/**
|
|
196
214
|
* Certain tasks (such as those that
|
|
@@ -258,7 +276,7 @@ const PickerColumn = class {
|
|
|
258
276
|
* may be past the stride if the option at the stride is disabled.
|
|
259
277
|
*/
|
|
260
278
|
this.findNextOption = (stride = 1) => {
|
|
261
|
-
const { activeItem } = this
|
|
279
|
+
const { activeItem } = this;
|
|
262
280
|
if (!activeItem)
|
|
263
281
|
return null;
|
|
264
282
|
let prevNode = activeItem;
|
|
@@ -285,7 +303,7 @@ const PickerColumn = class {
|
|
|
285
303
|
* may be past the stride if the option at the stride is disabled.
|
|
286
304
|
*/
|
|
287
305
|
this.findPreviousOption = (stride = 1) => {
|
|
288
|
-
const { activeItem } = this
|
|
306
|
+
const { activeItem } = this;
|
|
289
307
|
if (!activeItem)
|
|
290
308
|
return null;
|
|
291
309
|
let nextNode = activeItem;
|
|
@@ -339,6 +357,13 @@ const PickerColumn = class {
|
|
|
339
357
|
ev.preventDefault();
|
|
340
358
|
}
|
|
341
359
|
};
|
|
360
|
+
/**
|
|
361
|
+
* Utility to generate the correct text for aria-valuetext.
|
|
362
|
+
*/
|
|
363
|
+
this.getOptionValueText = (el) => {
|
|
364
|
+
var _a;
|
|
365
|
+
return el ? (_a = el.getAttribute('aria-label')) !== null && _a !== void 0 ? _a : el.innerText : '';
|
|
366
|
+
};
|
|
342
367
|
/**
|
|
343
368
|
* Render an element that overlays the column. This element is for assistive
|
|
344
369
|
* tech to allow users to navigate the column up/down. This element should receive
|
|
@@ -346,11 +371,15 @@ const PickerColumn = class {
|
|
|
346
371
|
* slider role: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Roles/slider_role
|
|
347
372
|
*/
|
|
348
373
|
this.renderAssistiveFocusable = () => {
|
|
349
|
-
|
|
350
|
-
const
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
374
|
+
const { activeItem } = this;
|
|
375
|
+
const valueText = this.getOptionValueText(activeItem);
|
|
376
|
+
/**
|
|
377
|
+
* When using the picker, the valuetext provides important context that valuenow
|
|
378
|
+
* does not. Additionally, using non-zero valuemin/valuemax values can cause
|
|
379
|
+
* WebKit to incorrectly announce numeric valuetext values (such as a year
|
|
380
|
+
* like "2024") as percentages: https://bugs.webkit.org/show_bug.cgi?id=273126
|
|
381
|
+
*/
|
|
382
|
+
return (index.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) }));
|
|
354
383
|
};
|
|
355
384
|
this.ariaLabel = null;
|
|
356
385
|
this.isActive = false;
|
|
@@ -392,8 +421,7 @@ const PickerColumn = class {
|
|
|
392
421
|
*/
|
|
393
422
|
const ev = entries[entries.length - 1];
|
|
394
423
|
if (ev.isIntersecting) {
|
|
395
|
-
const { activeItem } = this
|
|
396
|
-
const { el } = this;
|
|
424
|
+
const { activeItem, el } = this;
|
|
397
425
|
this.isColumnVisible = true;
|
|
398
426
|
/**
|
|
399
427
|
* Because this initial call to scrollActiveItemIntoView has to fire before
|
|
@@ -433,8 +461,7 @@ const PickerColumn = class {
|
|
|
433
461
|
}
|
|
434
462
|
}
|
|
435
463
|
componentDidRender() {
|
|
436
|
-
const { activeItem } = this
|
|
437
|
-
const { el, isColumnVisible, value } = this;
|
|
464
|
+
const { el, activeItem, isColumnVisible, value } = this;
|
|
438
465
|
if (isColumnVisible && !activeItem) {
|
|
439
466
|
const firstOption = el.querySelector('ion-picker-column-option');
|
|
440
467
|
/**
|
|
@@ -451,7 +478,7 @@ const PickerColumn = class {
|
|
|
451
478
|
}
|
|
452
479
|
/** @internal */
|
|
453
480
|
async scrollActiveItemIntoView(smooth = false) {
|
|
454
|
-
const
|
|
481
|
+
const activeEl = this.activeItem;
|
|
455
482
|
if (activeEl) {
|
|
456
483
|
this.centerPickerItemInView(activeEl, smooth, false);
|
|
457
484
|
}
|
|
@@ -485,33 +512,29 @@ const PickerColumn = class {
|
|
|
485
512
|
}
|
|
486
513
|
get activeItem() {
|
|
487
514
|
const { value } = this;
|
|
488
|
-
const options = this.el.querySelectorAll('ion-picker-column-option');
|
|
489
|
-
|
|
490
|
-
const option = options[i];
|
|
515
|
+
const options = Array.from(this.el.querySelectorAll('ion-picker-column-option'));
|
|
516
|
+
return options.find((option) => {
|
|
491
517
|
/**
|
|
492
518
|
* If the whole picker column is disabled, the current value should appear active
|
|
493
519
|
* If the current value item is specifically disabled, it should not appear active
|
|
494
520
|
*/
|
|
495
|
-
if (
|
|
496
|
-
return
|
|
497
|
-
activeItem: option,
|
|
498
|
-
activeItemIndex: i,
|
|
499
|
-
};
|
|
521
|
+
if (!this.disabled && option.disabled) {
|
|
522
|
+
return false;
|
|
500
523
|
}
|
|
501
|
-
|
|
502
|
-
|
|
524
|
+
return option.value === value;
|
|
525
|
+
});
|
|
503
526
|
}
|
|
504
527
|
render() {
|
|
505
528
|
const { color, disabled, isActive, numericInput } = this;
|
|
506
529
|
const mode = ionicGlobal.getIonMode(this);
|
|
507
|
-
return (index.h(index.Host, { key: '
|
|
530
|
+
return (index.h(index.Host, { key: '50fe50a49f88aa9ec435436083f3cd1ef49c8c9c', class: theme.createColorClasses(color, {
|
|
508
531
|
[mode]: true,
|
|
509
532
|
['picker-column-active']: isActive,
|
|
510
533
|
['picker-column-numeric-input']: numericInput,
|
|
511
534
|
['picker-column-disabled']: disabled,
|
|
512
|
-
}) }, this.renderAssistiveFocusable(), index.h("slot", { key: '
|
|
535
|
+
}) }, this.renderAssistiveFocusable(), index.h("slot", { key: '6350829748690895ab3ef101b9f2ae993852de7d', name: "prefix" }), index.h("div", { key: 'eaff9925aa8553f63ba2a1ae2bdfaa02963e0a5d', "aria-hidden": "true", class: "picker-opts", ref: (el) => {
|
|
513
536
|
this.scrollEl = el;
|
|
514
|
-
} }, index.h("div", { key: '
|
|
537
|
+
} }, index.h("div", { key: '25a24c4174782f2ec8a1fe06cbaf1f564b1f632f', class: "picker-item-empty", "aria-hidden": "true" }, "\u00A0"), index.h("div", { key: '7f4e9a5f1f74f7e8d5ad74178894edc80c0fb523', class: "picker-item-empty", "aria-hidden": "true" }, "\u00A0"), index.h("div", { key: '329b88b4af1d0e37da347e5f3fe9b462efcc2886', class: "picker-item-empty", "aria-hidden": "true" }, "\u00A0"), index.h("slot", { key: '82b9d5d541d41801bce06db0867d6cfbcee4ac3e' }), index.h("div", { key: '288ae193601d1eb49ead06f79eb1affa478f31d3', class: "picker-item-empty", "aria-hidden": "true" }, "\u00A0"), index.h("div", { key: '29661d0b74d11d650c2b23be66f857dd008dc5a0', class: "picker-item-empty", "aria-hidden": "true" }, "\u00A0"), index.h("div", { key: 'a7bd71b4abcb027654a828ffa65d87b6874d7484', class: "picker-item-empty", "aria-hidden": "true" }, "\u00A0")), index.h("slot", { key: '83ddd19d09ec48fe31b51f9f272a562320f90098', name: "suffix" })));
|
|
515
538
|
}
|
|
516
539
|
get el() { return index.getElement(this); }
|
|
517
540
|
static get watchers() { return {
|
|
@@ -1246,7 +1246,7 @@ export class Datetime {
|
|
|
1246
1246
|
}
|
|
1247
1247
|
const activePart = this.getActivePartsWithFallback();
|
|
1248
1248
|
const isDayPeriodRTL = isLocaleDayPeriodRTL(this.locale);
|
|
1249
|
-
return (h("ion-picker-column", { "aria-label": "Select a day", style: isDayPeriodRTL ? { order: '-1' } : {}, color: this.color, disabled: disabled, value: activePart.ampm, onIonChange: (ev) => {
|
|
1249
|
+
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) => {
|
|
1250
1250
|
const hour = calculateHourFromAMPM(workingParts, ev.detail.value);
|
|
1251
1251
|
this.setWorkingParts(Object.assign(Object.assign({}, workingParts), { ampm: ev.detail.value, hour }));
|
|
1252
1252
|
this.setActiveParts(Object.assign(Object.assign({}, activePart), { ampm: ev.detail.value, hour }));
|
|
@@ -1556,7 +1556,7 @@ export class Datetime {
|
|
|
1556
1556
|
const hasDatePresentation = presentation === 'date' || presentation === 'date-time' || presentation === 'time-date';
|
|
1557
1557
|
const hasWheelVariant = hasDatePresentation && preferWheel;
|
|
1558
1558
|
renderHiddenInput(true, el, name, formatValue(value), disabled);
|
|
1559
|
-
return (h(Host, { key: '
|
|
1559
|
+
return (h(Host, { key: '131cd9d8f73805ea76158c0ad05d86809fe8dfce', "aria-disabled": disabled ? 'true' : null, onFocus: this.onFocus, onBlur: this.onBlur, class: Object.assign({}, createColorClasses(color, {
|
|
1560
1560
|
[mode]: true,
|
|
1561
1561
|
['datetime-readonly']: readonly,
|
|
1562
1562
|
['datetime-disabled']: disabled,
|
|
@@ -1566,7 +1566,7 @@ export class Datetime {
|
|
|
1566
1566
|
[`datetime-size-${size}`]: true,
|
|
1567
1567
|
[`datetime-prefer-wheel`]: hasWheelVariant,
|
|
1568
1568
|
[`datetime-grid`]: isGridStyle,
|
|
1569
|
-
})) }, h("div", { key: '
|
|
1569
|
+
})) }, h("div", { key: '3be6976d484d9ccebac77630b2fd66388b2b85e4', class: "intersection-tracker", ref: (el) => (this.intersectionTrackerRef = el) }), this.renderDatetime(mode)));
|
|
1570
1570
|
}
|
|
1571
1571
|
static get is() { return "ion-datetime"; }
|
|
1572
1572
|
static get encapsulation() { return "shadow"; }
|
|
@@ -19,6 +19,7 @@ export class PickerColumn {
|
|
|
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 @@ export class PickerColumn {
|
|
|
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 @@ export class PickerColumn {
|
|
|
102
104
|
const enableHaptics = isPlatform('ios');
|
|
103
105
|
const { el, scrollEl } = this;
|
|
104
106
|
let timeout;
|
|
105
|
-
let
|
|
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 @@ export class PickerColumn {
|
|
|
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 @@ export class PickerColumn {
|
|
|
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
|
|
275
|
+
const { activeItem } = this;
|
|
258
276
|
if (!activeItem)
|
|
259
277
|
return null;
|
|
260
278
|
let prevNode = activeItem;
|
|
@@ -281,7 +299,7 @@ export class PickerColumn {
|
|
|
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
|
|
302
|
+
const { activeItem } = this;
|
|
285
303
|
if (!activeItem)
|
|
286
304
|
return null;
|
|
287
305
|
let nextNode = activeItem;
|
|
@@ -337,6 +355,13 @@ export class PickerColumn {
|
|
|
337
355
|
ev.preventDefault();
|
|
338
356
|
}
|
|
339
357
|
};
|
|
358
|
+
/**
|
|
359
|
+
* Utility to generate the correct text for aria-valuetext.
|
|
360
|
+
*/
|
|
361
|
+
this.getOptionValueText = (el) => {
|
|
362
|
+
var _a;
|
|
363
|
+
return el ? (_a = el.getAttribute('aria-label')) !== null && _a !== void 0 ? _a : el.innerText : '';
|
|
364
|
+
};
|
|
340
365
|
/**
|
|
341
366
|
* Render an element that overlays the column. This element is for assistive
|
|
342
367
|
* tech to allow users to navigate the column up/down. This element should receive
|
|
@@ -344,11 +369,15 @@ export class PickerColumn {
|
|
|
344
369
|
* slider role: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Roles/slider_role
|
|
345
370
|
*/
|
|
346
371
|
this.renderAssistiveFocusable = () => {
|
|
347
|
-
|
|
348
|
-
const
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
372
|
+
const { activeItem } = this;
|
|
373
|
+
const valueText = this.getOptionValueText(activeItem);
|
|
374
|
+
/**
|
|
375
|
+
* When using the picker, the valuetext provides important context that valuenow
|
|
376
|
+
* does not. Additionally, using non-zero valuemin/valuemax values can cause
|
|
377
|
+
* WebKit to incorrectly announce numeric valuetext values (such as a year
|
|
378
|
+
* like "2024") as percentages: https://bugs.webkit.org/show_bug.cgi?id=273126
|
|
379
|
+
*/
|
|
380
|
+
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) }));
|
|
352
381
|
};
|
|
353
382
|
this.ariaLabel = null;
|
|
354
383
|
this.isActive = false;
|
|
@@ -390,8 +419,7 @@ export class PickerColumn {
|
|
|
390
419
|
*/
|
|
391
420
|
const ev = entries[entries.length - 1];
|
|
392
421
|
if (ev.isIntersecting) {
|
|
393
|
-
const { activeItem } = this
|
|
394
|
-
const { el } = this;
|
|
422
|
+
const { activeItem, el } = this;
|
|
395
423
|
this.isColumnVisible = true;
|
|
396
424
|
/**
|
|
397
425
|
* Because this initial call to scrollActiveItemIntoView has to fire before
|
|
@@ -431,8 +459,7 @@ export class PickerColumn {
|
|
|
431
459
|
}
|
|
432
460
|
}
|
|
433
461
|
componentDidRender() {
|
|
434
|
-
const { activeItem } = this
|
|
435
|
-
const { el, isColumnVisible, value } = this;
|
|
462
|
+
const { el, activeItem, isColumnVisible, value } = this;
|
|
436
463
|
if (isColumnVisible && !activeItem) {
|
|
437
464
|
const firstOption = el.querySelector('ion-picker-column-option');
|
|
438
465
|
/**
|
|
@@ -449,7 +476,7 @@ export class PickerColumn {
|
|
|
449
476
|
}
|
|
450
477
|
/** @internal */
|
|
451
478
|
async scrollActiveItemIntoView(smooth = false) {
|
|
452
|
-
const
|
|
479
|
+
const activeEl = this.activeItem;
|
|
453
480
|
if (activeEl) {
|
|
454
481
|
this.centerPickerItemInView(activeEl, smooth, false);
|
|
455
482
|
}
|
|
@@ -483,33 +510,29 @@ export class PickerColumn {
|
|
|
483
510
|
}
|
|
484
511
|
get activeItem() {
|
|
485
512
|
const { value } = this;
|
|
486
|
-
const options = this.el.querySelectorAll('ion-picker-column-option');
|
|
487
|
-
|
|
488
|
-
const option = options[i];
|
|
513
|
+
const options = Array.from(this.el.querySelectorAll('ion-picker-column-option'));
|
|
514
|
+
return options.find((option) => {
|
|
489
515
|
/**
|
|
490
516
|
* If the whole picker column is disabled, the current value should appear active
|
|
491
517
|
* If the current value item is specifically disabled, it should not appear active
|
|
492
518
|
*/
|
|
493
|
-
if (
|
|
494
|
-
return
|
|
495
|
-
activeItem: option,
|
|
496
|
-
activeItemIndex: i,
|
|
497
|
-
};
|
|
519
|
+
if (!this.disabled && option.disabled) {
|
|
520
|
+
return false;
|
|
498
521
|
}
|
|
499
|
-
|
|
500
|
-
|
|
522
|
+
return option.value === value;
|
|
523
|
+
});
|
|
501
524
|
}
|
|
502
525
|
render() {
|
|
503
526
|
const { color, disabled, isActive, numericInput } = this;
|
|
504
527
|
const mode = getIonMode(this);
|
|
505
|
-
return (h(Host, { key: '
|
|
528
|
+
return (h(Host, { key: '50fe50a49f88aa9ec435436083f3cd1ef49c8c9c', class: createColorClasses(color, {
|
|
506
529
|
[mode]: true,
|
|
507
530
|
['picker-column-active']: isActive,
|
|
508
531
|
['picker-column-numeric-input']: numericInput,
|
|
509
532
|
['picker-column-disabled']: disabled,
|
|
510
|
-
}) }, this.renderAssistiveFocusable(), h("slot", { key: '
|
|
533
|
+
}) }, this.renderAssistiveFocusable(), h("slot", { key: '6350829748690895ab3ef101b9f2ae993852de7d', name: "prefix" }), h("div", { key: 'eaff9925aa8553f63ba2a1ae2bdfaa02963e0a5d', "aria-hidden": "true", class: "picker-opts", ref: (el) => {
|
|
511
534
|
this.scrollEl = el;
|
|
512
|
-
} }, h("div", { key: '
|
|
535
|
+
} }, 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" })));
|
|
513
536
|
}
|
|
514
537
|
static get is() { return "ion-picker-column"; }
|
|
515
538
|
static get encapsulation() { return "shadow"; }
|