@ionic/core 8.7.3-dev.11755600455.1e79c35a → 8.7.3-dev.11755622775.1fc05815
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 -4
- package/components/ion-input.js +36 -5
- package/components/ion-refresher.js +18 -1
- package/components/ion-textarea.js +35 -4
- package/components/overlays.js +97 -3
- package/components/picker-column-option.js +3 -3
- package/components/picker-column.js +39 -3
- package/dist/cjs/index.cjs.js +1 -1
- package/dist/cjs/ion-action-sheet.cjs.entry.js +1 -1
- package/dist/cjs/ion-alert.cjs.entry.js +1 -1
- package/dist/cjs/ion-datetime_3.cjs.entry.js +4 -4
- package/dist/cjs/ion-input.cjs.entry.js +35 -5
- package/dist/cjs/ion-loading.cjs.entry.js +1 -1
- package/dist/cjs/ion-menu_3.cjs.entry.js +1 -1
- package/dist/cjs/ion-modal.cjs.entry.js +1 -1
- package/dist/cjs/ion-picker-column-option.cjs.entry.js +3 -3
- package/dist/cjs/ion-picker-column.cjs.entry.js +39 -3
- package/dist/cjs/ion-popover.cjs.entry.js +1 -1
- package/dist/cjs/ion-refresher_2.cjs.entry.js +18 -1
- package/dist/cjs/ion-select-modal.cjs.entry.js +1 -1
- package/dist/cjs/ion-select_3.cjs.entry.js +1 -1
- package/dist/cjs/ion-textarea.cjs.entry.js +34 -4
- package/dist/cjs/ion-toast.cjs.entry.js +1 -1
- package/dist/cjs/ionic.cjs.js +1 -1
- package/dist/cjs/loader.cjs.js +1 -1
- package/dist/cjs/{overlays-DUsEBICv.js → overlays-CglR7j-u.js} +96 -2
- package/dist/collection/components/datetime/datetime.js +3 -4
- package/dist/collection/components/input/input.js +37 -6
- package/dist/collection/components/picker-column/picker-column.js +39 -3
- package/dist/collection/components/picker-column-option/picker-column-option.ios.css +2 -2
- package/dist/collection/components/picker-column-option/picker-column-option.js +1 -1
- package/dist/collection/components/picker-column-option/picker-column-option.md.css +2 -2
- package/dist/collection/components/refresher/refresher.js +18 -1
- package/dist/collection/components/textarea/textarea.js +36 -5
- package/dist/collection/utils/overlays.js +97 -2
- package/dist/docs.json +1 -1
- package/dist/esm/index.js +1 -1
- package/dist/esm/ion-action-sheet.entry.js +1 -1
- package/dist/esm/ion-alert.entry.js +1 -1
- package/dist/esm/ion-datetime_3.entry.js +4 -4
- package/dist/esm/ion-input.entry.js +35 -5
- package/dist/esm/ion-loading.entry.js +1 -1
- package/dist/esm/ion-menu_3.entry.js +1 -1
- package/dist/esm/ion-modal.entry.js +1 -1
- package/dist/esm/ion-picker-column-option.entry.js +3 -3
- package/dist/esm/ion-picker-column.entry.js +39 -3
- package/dist/esm/ion-popover.entry.js +1 -1
- package/dist/esm/ion-refresher_2.entry.js +18 -1
- package/dist/esm/ion-select-modal.entry.js +1 -1
- package/dist/esm/ion-select_3.entry.js +1 -1
- package/dist/esm/ion-textarea.entry.js +34 -4
- package/dist/esm/ion-toast.entry.js +1 -1
- package/dist/esm/ionic.js +1 -1
- package/dist/esm/loader.js +1 -1
- package/dist/esm/{overlays-B_dsLNe8.js → overlays-ZX_4-t_r.js} +97 -3
- package/dist/ionic/index.esm.js +1 -1
- package/dist/ionic/ionic.esm.js +1 -1
- package/dist/ionic/p-187aaf4a.entry.js +4 -0
- package/dist/ionic/p-1d5b934a.entry.js +4 -0
- package/dist/ionic/p-1e34d434.entry.js +4 -0
- package/dist/ionic/p-29032e49.entry.js +4 -0
- package/dist/ionic/{p-8b54aa01.entry.js → p-7bac2c5f.entry.js} +1 -1
- package/dist/ionic/p-8cdb4ff5.entry.js +4 -0
- package/dist/ionic/{p-7ed24ba0.entry.js → p-8d96a0cd.entry.js} +1 -1
- package/dist/ionic/{p-84236acb.entry.js → p-91d6ccb0.entry.js} +1 -1
- package/dist/ionic/{p-09ed68cf.entry.js → p-92e8f208.entry.js} +1 -1
- package/dist/ionic/{p-98d0823e.entry.js → p-982fe1c4.entry.js} +1 -1
- package/dist/ionic/p-CSwZyt05.js +4 -0
- package/dist/ionic/{p-698fb72c.entry.js → p-ab33ef20.entry.js} +1 -1
- package/dist/ionic/{p-07d8f62a.entry.js → p-ac434970.entry.js} +1 -1
- package/dist/ionic/{p-57bb1214.entry.js → p-c575e7ce.entry.js} +1 -1
- package/dist/ionic/{p-9c6fddc6.entry.js → p-f2884bc2.entry.js} +1 -1
- package/dist/ionic/p-f456d176.entry.js +4 -0
- package/dist/types/components/input/input.d.ts +9 -0
- package/dist/types/components/picker-column/picker-column.d.ts +7 -0
- package/dist/types/components/textarea/textarea.d.ts +9 -0
- package/hydrate/index.js +204 -21
- package/hydrate/index.mjs +204 -21
- package/package.json +1 -1
- package/dist/ionic/p-1488b7cc.entry.js +0 -4
- package/dist/ionic/p-8888efe4.entry.js +0 -4
- package/dist/ionic/p-8bfe00f3.entry.js +0 -4
- package/dist/ionic/p-C3MD7jSK.js +0 -4
- package/dist/ionic/p-ac2be9d6.entry.js +0 -4
- package/dist/ionic/p-b292804d.entry.js +0 -4
- package/dist/ionic/p-c5210d3e.entry.js +0 -4
package/hydrate/index.js
CHANGED
|
@@ -6167,11 +6167,9 @@ const setRootAriaHidden = (hidden = false) => {
|
|
|
6167
6167
|
}
|
|
6168
6168
|
if (hidden) {
|
|
6169
6169
|
viewContainer.setAttribute('aria-hidden', 'true');
|
|
6170
|
-
viewContainer.setAttribute('inert', '');
|
|
6171
6170
|
}
|
|
6172
6171
|
else {
|
|
6173
6172
|
viewContainer.removeAttribute('aria-hidden');
|
|
6174
|
-
viewContainer.removeAttribute('inert');
|
|
6175
6173
|
}
|
|
6176
6174
|
};
|
|
6177
6175
|
const present = async (overlay, name, iosEnterAnimation, mdEnterAnimation, opts) => {
|
|
@@ -6190,6 +6188,8 @@ const present = async (overlay, name, iosEnterAnimation, mdEnterAnimation, opts)
|
|
|
6190
6188
|
setRootAriaHidden(true);
|
|
6191
6189
|
document.body.classList.add(BACKDROP_NO_SCROLL);
|
|
6192
6190
|
}
|
|
6191
|
+
hideUnderlyingOverlaysFromScreenReaders(overlay.el);
|
|
6192
|
+
hideAnimatingOverlayFromScreenReaders(overlay.el);
|
|
6193
6193
|
overlay.presented = true;
|
|
6194
6194
|
overlay.willPresent.emit();
|
|
6195
6195
|
(_a = overlay.willPresentShorthand) === null || _a === void 0 ? void 0 : _a.emit();
|
|
@@ -6315,6 +6315,12 @@ const dismiss = async (overlay, data, role, name, iosLeaveAnimation, mdLeaveAnim
|
|
|
6315
6315
|
}
|
|
6316
6316
|
overlay.presented = false;
|
|
6317
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);
|
|
6318
6324
|
// Overlay contents should not be clickable during dismiss
|
|
6319
6325
|
overlay.el.style.setProperty('pointer-events', 'none');
|
|
6320
6326
|
overlay.willDismiss.emit({ data, role });
|
|
@@ -6353,6 +6359,7 @@ const dismiss = async (overlay, data, role, name, iosLeaveAnimation, mdLeaveAnim
|
|
|
6353
6359
|
printIonError(`[${overlay.el.tagName.toLowerCase()}] - `, err);
|
|
6354
6360
|
}
|
|
6355
6361
|
overlay.el.remove();
|
|
6362
|
+
revealOverlaysToScreenReaders();
|
|
6356
6363
|
return true;
|
|
6357
6364
|
};
|
|
6358
6365
|
const getAppRoot = (doc) => {
|
|
@@ -6548,6 +6555,93 @@ const createTriggerController = () => {
|
|
|
6548
6555
|
removeClickListener,
|
|
6549
6556
|
};
|
|
6550
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
|
+
};
|
|
6551
6645
|
const FOCUS_TRAP_DISABLE_CLASS = 'ion-disable-focus-trap';
|
|
6552
6646
|
|
|
6553
6647
|
const hostContext = (selector, el) => {
|
|
@@ -13437,7 +13531,7 @@ class Datetime {
|
|
|
13437
13531
|
const renderArray = forcePresentation === 'time-date'
|
|
13438
13532
|
? [this.renderTimePickerColumns(forcePresentation), this.renderDatePickerColumns(forcePresentation)]
|
|
13439
13533
|
: [this.renderDatePickerColumns(forcePresentation), this.renderTimePickerColumns(forcePresentation)];
|
|
13440
|
-
return hAsync("ion-picker",
|
|
13534
|
+
return hAsync("ion-picker", null, renderArray);
|
|
13441
13535
|
}
|
|
13442
13536
|
renderDatePickerColumns(forcePresentation) {
|
|
13443
13537
|
return forcePresentation === 'date-time' || forcePresentation === 'time-date'
|
|
@@ -13994,7 +14088,7 @@ class Datetime {
|
|
|
13994
14088
|
const hasDatePresentation = presentation === 'date' || presentation === 'date-time' || presentation === 'time-date';
|
|
13995
14089
|
const hasWheelVariant = hasDatePresentation && preferWheel;
|
|
13996
14090
|
renderHiddenInput(true, el, name, formatValue(value), disabled);
|
|
13997
|
-
return (hAsync(Host, { key: '
|
|
14091
|
+
return (hAsync(Host, { key: 'f35cf200ff05d33074576e3d2754d3b2a0735b96', "aria-disabled": disabled ? 'true' : null, onFocus: this.onFocus, onBlur: this.onBlur, class: Object.assign({}, createColorClasses$1(color, {
|
|
13998
14092
|
[mode]: true,
|
|
13999
14093
|
['datetime-readonly']: readonly,
|
|
14000
14094
|
['datetime-disabled']: disabled,
|
|
@@ -14004,7 +14098,7 @@ class Datetime {
|
|
|
14004
14098
|
[`datetime-size-${size}`]: true,
|
|
14005
14099
|
[`datetime-prefer-wheel`]: hasWheelVariant,
|
|
14006
14100
|
[`datetime-grid`]: isGridStyle,
|
|
14007
|
-
})) }, hAsync("div", { key: '
|
|
14101
|
+
})) }, hAsync("div", { key: '859e9354a12bfa58ac3f964c2e66839f17071c00', class: "intersection-tracker", ref: (el) => (this.intersectionTrackerRef = el) }), this.renderDatetime(mode)));
|
|
14008
14102
|
}
|
|
14009
14103
|
get el() { return getElement(this); }
|
|
14010
14104
|
static get watchers() { return {
|
|
@@ -16535,6 +16629,10 @@ class Input {
|
|
|
16535
16629
|
* is applied in both cases.
|
|
16536
16630
|
*/
|
|
16537
16631
|
this.hasFocus = false;
|
|
16632
|
+
/**
|
|
16633
|
+
* Track validation state for proper aria-live announcements
|
|
16634
|
+
*/
|
|
16635
|
+
this.isInvalid = false;
|
|
16538
16636
|
/**
|
|
16539
16637
|
* Indicates whether and how the text value should be automatically capitalized as it is entered/edited by the user.
|
|
16540
16638
|
* Available options: `"off"`, `"none"`, `"on"`, `"sentences"`, `"words"`, `"characters"`.
|
|
@@ -16718,10 +16816,18 @@ class Input {
|
|
|
16718
16816
|
componentWillLoad() {
|
|
16719
16817
|
this.inheritedAttributes = Object.assign(Object.assign({}, inheritAriaAttributes(this.el)), inheritAttributes$1(this.el, ['tabindex', 'title', 'data-form-type', 'dir']));
|
|
16720
16818
|
}
|
|
16819
|
+
/**
|
|
16820
|
+
* Checks if the input is in an invalid state based on validation classes
|
|
16821
|
+
*/
|
|
16822
|
+
checkValidationState() {
|
|
16823
|
+
return this.el.classList.contains('ion-touched') && this.el.classList.contains('ion-invalid');
|
|
16824
|
+
}
|
|
16721
16825
|
connectedCallback() {
|
|
16722
16826
|
const { el } = this;
|
|
16723
16827
|
this.slotMutationController = createSlotMutationController(el, ['label', 'start', 'end'], () => forceUpdate());
|
|
16724
16828
|
this.notchController = createNotchController(el, () => this.notchSpacerEl, () => this.labelSlot);
|
|
16829
|
+
// Always set initial state
|
|
16830
|
+
this.isInvalid = this.checkValidationState();
|
|
16725
16831
|
this.debounceChanged();
|
|
16726
16832
|
}
|
|
16727
16833
|
componentDidLoad() {
|
|
@@ -16748,6 +16854,11 @@ class Input {
|
|
|
16748
16854
|
this.notchController.destroy();
|
|
16749
16855
|
this.notchController = undefined;
|
|
16750
16856
|
}
|
|
16857
|
+
// Clean up validation observer to prevent memory leaks
|
|
16858
|
+
if (this.validationObserver) {
|
|
16859
|
+
this.validationObserver.disconnect();
|
|
16860
|
+
this.validationObserver = undefined;
|
|
16861
|
+
}
|
|
16751
16862
|
}
|
|
16752
16863
|
/**
|
|
16753
16864
|
* Sets focus on the native `input` in `ion-input`. Use this method instead of the global
|
|
@@ -16856,8 +16967,8 @@ class Input {
|
|
|
16856
16967
|
];
|
|
16857
16968
|
}
|
|
16858
16969
|
getHintTextID() {
|
|
16859
|
-
const {
|
|
16860
|
-
if (
|
|
16970
|
+
const { isInvalid, helperText, errorText, helperTextId, errorTextId } = this;
|
|
16971
|
+
if (isInvalid && errorText) {
|
|
16861
16972
|
return errorTextId;
|
|
16862
16973
|
}
|
|
16863
16974
|
if (helperText) {
|
|
@@ -16970,7 +17081,7 @@ class Input {
|
|
|
16970
17081
|
* TODO(FW-5592): Remove hasStartEndSlots condition
|
|
16971
17082
|
*/
|
|
16972
17083
|
const labelShouldFloat = labelPlacement === 'stacked' || (labelPlacement === 'floating' && (hasValue || hasFocus || hasStartEndSlots));
|
|
16973
|
-
return (hAsync(Host, { key: '
|
|
17084
|
+
return (hAsync(Host, { key: '1b0cffa910aef4eac24438bf3158e51905e70788', class: createColorClasses$1(this.color, {
|
|
16974
17085
|
[mode]: true,
|
|
16975
17086
|
'has-value': hasValue,
|
|
16976
17087
|
'has-focus': hasFocus,
|
|
@@ -16981,14 +17092,14 @@ class Input {
|
|
|
16981
17092
|
'in-item': inItem,
|
|
16982
17093
|
'in-item-color': hostContext('ion-item.ion-color', this.el),
|
|
16983
17094
|
'input-disabled': disabled,
|
|
16984
|
-
}) }, hAsync("label", { key: '
|
|
17095
|
+
}) }, hAsync("label", { key: '24411a6cc190e2054015bca5e2827b96c65bba17', class: "input-wrapper", htmlFor: inputId, onClick: this.onLabelClick }, this.renderLabelContainer(), hAsync("div", { key: '7fa7a7f6d2778e6efbebc6f2671d8a63048f76a8', class: "native-wrapper", onClick: this.onLabelClick }, hAsync("slot", { key: '14f489e6026967ee1b2eee1519bad4230f028489', name: "start" }), hAsync("input", Object.assign({ key: 'd0f5b756394aced0831e80e91313a417bda37e6f', 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.isInvalid ? 'true' : undefined }, this.inheritedAttributes)), this.clearInput && !readonly && !disabled && (hAsync("button", { key: '3e37003927082bbbfce4b3396a263969aa2289fc', "aria-label": "reset", type: "button", class: "input-clear-icon", onPointerDown: (ev) => {
|
|
16985
17096
|
/**
|
|
16986
17097
|
* This prevents mobile browsers from
|
|
16987
17098
|
* blurring the input when the clear
|
|
16988
17099
|
* button is activated.
|
|
16989
17100
|
*/
|
|
16990
17101
|
ev.preventDefault();
|
|
16991
|
-
}, onClick: this.clearTextInput }, hAsync("ion-icon", { key: '
|
|
17102
|
+
}, onClick: this.clearTextInput }, hAsync("ion-icon", { key: '269ccdfd95a8a5b39bf0587b1494b4badd5c65b3', "aria-hidden": "true", icon: clearIconData }))), hAsync("slot", { key: '5d93a350194c4197c01c5d54f50060e7f527f065', name: "end" })), shouldRenderHighlight && hAsync("div", { key: 'fbdd13d41b37aa1e4608ba2535f7b833748eae3f', class: "input-highlight" })), this.renderBottomContent()));
|
|
16992
17103
|
}
|
|
16993
17104
|
get el() { return getElement(this); }
|
|
16994
17105
|
static get watchers() { return {
|
|
@@ -17040,6 +17151,7 @@ class Input {
|
|
|
17040
17151
|
"type": [1],
|
|
17041
17152
|
"value": [1032],
|
|
17042
17153
|
"hasFocus": [32],
|
|
17154
|
+
"isInvalid": [32],
|
|
17043
17155
|
"setFocus": [64],
|
|
17044
17156
|
"getInputElement": [64]
|
|
17045
17157
|
},
|
|
@@ -25410,6 +25522,23 @@ class PickerColumn {
|
|
|
25410
25522
|
var _a;
|
|
25411
25523
|
return el ? (_a = el.getAttribute('aria-label')) !== null && _a !== void 0 ? _a : el.innerText : '';
|
|
25412
25524
|
};
|
|
25525
|
+
/**
|
|
25526
|
+
* Render an element that overlays the column. This element is for assistive
|
|
25527
|
+
* tech to allow users to navigate the column up/down. This element should receive
|
|
25528
|
+
* focus as it listens for synthesized keyboard events as required by the
|
|
25529
|
+
* slider role: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Roles/slider_role
|
|
25530
|
+
*/
|
|
25531
|
+
this.renderAssistiveFocusable = () => {
|
|
25532
|
+
const { activeItem } = this;
|
|
25533
|
+
const valueText = this.getOptionValueText(activeItem);
|
|
25534
|
+
/**
|
|
25535
|
+
* When using the picker, the valuetext provides important context that valuenow
|
|
25536
|
+
* does not. Additionally, using non-zero valuemin/valuemax values can cause
|
|
25537
|
+
* WebKit to incorrectly announce numeric valuetext values (such as a year
|
|
25538
|
+
* like "2024") as percentages: https://bugs.webkit.org/show_bug.cgi?id=273126
|
|
25539
|
+
*/
|
|
25540
|
+
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) }));
|
|
25541
|
+
};
|
|
25413
25542
|
}
|
|
25414
25543
|
ariaLabelChanged(newValue) {
|
|
25415
25544
|
this.ariaLabel = newValue;
|
|
@@ -25550,14 +25679,33 @@ class PickerColumn {
|
|
|
25550
25679
|
render() {
|
|
25551
25680
|
const { color, disabled, isActive, numericInput } = this;
|
|
25552
25681
|
const mode = getIonMode$1(this);
|
|
25553
|
-
return (hAsync(Host, { key: '
|
|
25682
|
+
return (hAsync(Host, { key: 'ea0280355b2f87895bf7dddd289ccf473aa759f3', class: createColorClasses$1(color, {
|
|
25554
25683
|
[mode]: true,
|
|
25555
25684
|
['picker-column-active']: isActive,
|
|
25556
25685
|
['picker-column-numeric-input']: numericInput,
|
|
25557
25686
|
['picker-column-disabled']: disabled,
|
|
25558
|
-
}) }, hAsync("slot", { key: '
|
|
25687
|
+
}) }, this.renderAssistiveFocusable(), hAsync("slot", { key: '482992131cdeb85b1f61430d7fe1322a16345769', name: "prefix" }), hAsync("div", { key: '43f7f80d621d411ef366b3ca1396299e8c9a0c97', "aria-hidden": "true", class: "picker-opts", ref: (el) => {
|
|
25559
25688
|
this.scrollEl = el;
|
|
25560
|
-
},
|
|
25689
|
+
},
|
|
25690
|
+
/**
|
|
25691
|
+
* When an element has an overlay scroll style and
|
|
25692
|
+
* a fixed height, Firefox will focus the scrollable
|
|
25693
|
+
* container if the content exceeds the container's
|
|
25694
|
+
* dimensions.
|
|
25695
|
+
*
|
|
25696
|
+
* This causes keyboard navigation to focus to this
|
|
25697
|
+
* element instead of going to the next element in
|
|
25698
|
+
* the tab order.
|
|
25699
|
+
*
|
|
25700
|
+
* The desired behavior is for the user to be able to
|
|
25701
|
+
* focus the assistive focusable element and tab to
|
|
25702
|
+
* the next element in the tab order. Instead of tabbing
|
|
25703
|
+
* to this element.
|
|
25704
|
+
*
|
|
25705
|
+
* To prevent this, we set the tabIndex to -1. This
|
|
25706
|
+
* will match the behavior of the other browsers.
|
|
25707
|
+
*/
|
|
25708
|
+
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" })));
|
|
25561
25709
|
}
|
|
25562
25710
|
get el() { return getElement(this); }
|
|
25563
25711
|
static get watchers() { return {
|
|
@@ -25949,9 +26097,9 @@ const DECELERATION_FRICTION = 0.97;
|
|
|
25949
26097
|
const MAX_PICKER_SPEED = 90;
|
|
25950
26098
|
const TRANSITION_DURATION = 150;
|
|
25951
26099
|
|
|
25952
|
-
const pickerColumnOptionIosCss = "
|
|
26100
|
+
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}";
|
|
25953
26101
|
|
|
25954
|
-
const pickerColumnOptionMdCss = "
|
|
26102
|
+
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)}";
|
|
25955
26103
|
|
|
25956
26104
|
class PickerColumnOption {
|
|
25957
26105
|
constructor(hostRef) {
|
|
@@ -26043,7 +26191,7 @@ class PickerColumnOption {
|
|
|
26043
26191
|
return (hAsync(Host, { key: 'f816729941aabcb31ddfdce3ffe2e2139030d715', class: createColorClasses$1(color, {
|
|
26044
26192
|
[mode]: true,
|
|
26045
26193
|
['option-disabled']: disabled,
|
|
26046
|
-
}) }, hAsync("
|
|
26194
|
+
}) }, hAsync("button", { key: '48dff7833bb60fc8331cd353a0885e6affa683d1', tabindex: "-1", "aria-label": ariaLabel, disabled: disabled, onClick: () => this.onClick() }, hAsync("slot", { key: 'f9224d0e7b7aa6c05b29abfdcfe0f30ad6ee3141' }))));
|
|
26047
26195
|
}
|
|
26048
26196
|
get el() { return getElement(this); }
|
|
26049
26197
|
static get watchers() { return {
|
|
@@ -29202,6 +29350,14 @@ class Refresher {
|
|
|
29202
29350
|
this.beginRefresh();
|
|
29203
29351
|
this.didRefresh = true;
|
|
29204
29352
|
hapticImpact({ style: ImpactStyle.Light });
|
|
29353
|
+
/**
|
|
29354
|
+
* Clear focus from any active element to prevent scroll jumps
|
|
29355
|
+
* when the refresh completes
|
|
29356
|
+
*/
|
|
29357
|
+
const activeElement = document.activeElement;
|
|
29358
|
+
if ((activeElement === null || activeElement === void 0 ? void 0 : activeElement.blur) !== undefined) {
|
|
29359
|
+
activeElement.blur();
|
|
29360
|
+
}
|
|
29205
29361
|
/**
|
|
29206
29362
|
* Translate the content element otherwise when pointer is removed
|
|
29207
29363
|
* from screen the scroll content will bounce back over the refresher
|
|
@@ -29617,6 +29773,15 @@ class Refresher {
|
|
|
29617
29773
|
this.state = 8 /* RefresherState.Refreshing */;
|
|
29618
29774
|
// place the content in a hangout position while it thinks
|
|
29619
29775
|
this.setCss(this.pullMin, this.snapbackDuration, true, '');
|
|
29776
|
+
/**
|
|
29777
|
+
* Clear focus from any active element to prevent the browser
|
|
29778
|
+
* from restoring focus and causing scroll jumps after refresh.
|
|
29779
|
+
* This ensures the view stays at the top after refresh completes.
|
|
29780
|
+
*/
|
|
29781
|
+
const activeElement = document.activeElement;
|
|
29782
|
+
if ((activeElement === null || activeElement === void 0 ? void 0 : activeElement.blur) !== undefined) {
|
|
29783
|
+
activeElement.blur();
|
|
29784
|
+
}
|
|
29620
29785
|
// emit "refresh" because it was pulled down far enough
|
|
29621
29786
|
// and they let go to begin refreshing
|
|
29622
29787
|
this.ionRefresh.emit({
|
|
@@ -29699,7 +29864,7 @@ class Refresher {
|
|
|
29699
29864
|
}
|
|
29700
29865
|
render() {
|
|
29701
29866
|
const mode = getIonMode$1(this);
|
|
29702
|
-
return (hAsync(Host, { key: '
|
|
29867
|
+
return (hAsync(Host, { key: '2d1bd880877b698604542ab2d602d38b9504d975', slot: "fixed", class: {
|
|
29703
29868
|
[mode]: true,
|
|
29704
29869
|
// Used internally for styling
|
|
29705
29870
|
[`refresher-${mode}`]: true,
|
|
@@ -34746,6 +34911,10 @@ class Textarea {
|
|
|
34746
34911
|
* is applied in both cases.
|
|
34747
34912
|
*/
|
|
34748
34913
|
this.hasFocus = false;
|
|
34914
|
+
/**
|
|
34915
|
+
* Track validation state for proper aria-live announcements
|
|
34916
|
+
*/
|
|
34917
|
+
this.isInvalid = false;
|
|
34749
34918
|
/**
|
|
34750
34919
|
* Indicates whether and how the text value should be automatically capitalized as it is entered/edited by the user.
|
|
34751
34920
|
* Available options: `"off"`, `"none"`, `"on"`, `"sentences"`, `"words"`, `"characters"`.
|
|
@@ -34891,10 +35060,18 @@ class Textarea {
|
|
|
34891
35060
|
this.el.click();
|
|
34892
35061
|
}
|
|
34893
35062
|
}
|
|
35063
|
+
/**
|
|
35064
|
+
* Checks if the textarea is in an invalid state based on validation classes
|
|
35065
|
+
*/
|
|
35066
|
+
checkValidationState() {
|
|
35067
|
+
return this.el.classList.contains('ion-touched') && this.el.classList.contains('ion-invalid');
|
|
35068
|
+
}
|
|
34894
35069
|
connectedCallback() {
|
|
34895
35070
|
const { el } = this;
|
|
34896
35071
|
this.slotMutationController = createSlotMutationController(el, ['label', 'start', 'end'], () => forceUpdate());
|
|
34897
35072
|
this.notchController = createNotchController(el, () => this.notchSpacerEl, () => this.labelSlot);
|
|
35073
|
+
// Always set initial state
|
|
35074
|
+
this.isInvalid = this.checkValidationState();
|
|
34898
35075
|
this.debounceChanged();
|
|
34899
35076
|
}
|
|
34900
35077
|
disconnectedCallback() {
|
|
@@ -34906,6 +35083,11 @@ class Textarea {
|
|
|
34906
35083
|
this.notchController.destroy();
|
|
34907
35084
|
this.notchController = undefined;
|
|
34908
35085
|
}
|
|
35086
|
+
// Clean up validation observer to prevent memory leaks
|
|
35087
|
+
if (this.validationObserver) {
|
|
35088
|
+
this.validationObserver.disconnect();
|
|
35089
|
+
this.validationObserver = undefined;
|
|
35090
|
+
}
|
|
34909
35091
|
}
|
|
34910
35092
|
componentWillLoad() {
|
|
34911
35093
|
this.inheritedAttributes = Object.assign(Object.assign({}, inheritAriaAttributes(this.el)), inheritAttributes$1(this.el, ['data-form-type', 'title', 'tabindex', 'dir']));
|
|
@@ -35083,8 +35265,8 @@ class Textarea {
|
|
|
35083
35265
|
];
|
|
35084
35266
|
}
|
|
35085
35267
|
getHintTextID() {
|
|
35086
|
-
const {
|
|
35087
|
-
if (
|
|
35268
|
+
const { isInvalid, helperText, errorText, helperTextId, errorTextId } = this;
|
|
35269
|
+
if (isInvalid && errorText) {
|
|
35088
35270
|
return errorTextId;
|
|
35089
35271
|
}
|
|
35090
35272
|
if (helperText) {
|
|
@@ -35143,7 +35325,7 @@ class Textarea {
|
|
|
35143
35325
|
* TODO(FW-5592): Remove hasStartEndSlots condition
|
|
35144
35326
|
*/
|
|
35145
35327
|
const labelShouldFloat = labelPlacement === 'stacked' || (labelPlacement === 'floating' && (hasValue || hasFocus || hasStartEndSlots));
|
|
35146
|
-
return (hAsync(Host, { key: '
|
|
35328
|
+
return (hAsync(Host, { key: 'de258335fde7fa934cf3bd58c469525440457468', class: createColorClasses$1(this.color, {
|
|
35147
35329
|
[mode]: true,
|
|
35148
35330
|
'has-value': hasValue,
|
|
35149
35331
|
'has-focus': hasFocus,
|
|
@@ -35152,7 +35334,7 @@ class Textarea {
|
|
|
35152
35334
|
[`textarea-shape-${shape}`]: shape !== undefined,
|
|
35153
35335
|
[`textarea-label-placement-${labelPlacement}`]: true,
|
|
35154
35336
|
'textarea-disabled': disabled,
|
|
35155
|
-
}) }, hAsync("label", { key: '
|
|
35337
|
+
}) }, hAsync("label", { key: '79fc87122871d45316b1c5fd0a467bf85351e804', class: "textarea-wrapper", htmlFor: inputId, onClick: this.onLabelClick }, this.renderLabelContainer(), hAsync("div", { key: '2375888a47557b41ea3b3bf8eae1fd3f2a4032bd', class: "textarea-wrapper-inner" }, hAsync("div", { key: 'c5af683527a870bd85256b6de8a7d216283403dd', class: "start-slot-wrapper" }, hAsync("slot", { key: 'd972e5784403c5cc6ed067ae578ce23ff8303e1e', name: "start" })), hAsync("div", { key: '1092067609d912a76a8679767611e4ca3e071c6f', class: "native-wrapper", ref: (el) => (this.textareaWrapper = el) }, hAsync("textarea", Object.assign({ key: 'cd23a4bad4d5b460830340009d24d0618f14fd73', class: "native-textarea", ref: (el) => (this.nativeInput = el), id: inputId, disabled: disabled, autoCapitalize: this.autocapitalize, autoFocus: this.autofocus, enterKeyHint: this.enterkeyhint, inputMode: this.inputmode, minLength: this.minlength, maxLength: this.maxlength, name: this.name, placeholder: this.placeholder || '', readOnly: this.readonly, required: this.required, spellcheck: this.spellcheck, cols: this.cols, rows: this.rows, wrap: this.wrap, onInput: this.onInput, onChange: this.onChange, onBlur: this.onBlur, onFocus: this.onFocus, onKeyDown: this.onKeyDown, "aria-describedby": this.getHintTextID(), "aria-invalid": this.isInvalid ? 'true' : undefined }, this.inheritedAttributes), value)), hAsync("div", { key: 'c91a5456f4490ef8699f2e44b4a6c64f6084f5fd', class: "end-slot-wrapper" }, hAsync("slot", { key: 'b71ba7ba0d74091e81784432dcffa832b66f3f25', name: "end" }))), shouldRenderHighlight && hAsync("div", { key: '757c3287e1cea5ee851227407685a437f8408c54', class: "textarea-highlight" })), this.renderBottomContent()));
|
|
35156
35338
|
}
|
|
35157
35339
|
get el() { return getElement(this); }
|
|
35158
35340
|
static get watchers() { return {
|
|
@@ -35197,6 +35379,7 @@ class Textarea {
|
|
|
35197
35379
|
"labelPlacement": [1, "label-placement"],
|
|
35198
35380
|
"shape": [1],
|
|
35199
35381
|
"hasFocus": [32],
|
|
35382
|
+
"isInvalid": [32],
|
|
35200
35383
|
"setFocus": [64],
|
|
35201
35384
|
"getInputElement": [64]
|
|
35202
35385
|
},
|