voyager-ionic-core 8.7.6 → 8.7.11
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/button.js +3 -7
- package/components/checkbox.js +64 -13
- package/components/header.js +42 -4
- package/components/index2.js +74 -3
- package/components/ion-accordion.js +93 -14
- package/components/ion-datetime.js +35 -2
- package/components/ion-input.js +6 -13
- package/components/ion-select.js +59 -10
- package/components/ion-textarea.js +5 -12
- package/components/ion-toggle.js +63 -16
- package/components/radio-group.js +60 -7
- package/components/validity.js +17 -0
- package/dist/cjs/{index-CD5Rjp23.js → index-094mMFB-.js} +76 -5
- package/dist/cjs/index.cjs.js +3 -3
- package/dist/cjs/ion-accordion_2.cjs.entry.js +91 -13
- package/dist/cjs/ion-app_8.cjs.entry.js +43 -5
- package/dist/cjs/ion-button_2.cjs.entry.js +3 -7
- package/dist/cjs/ion-checkbox.cjs.entry.js +61 -12
- package/dist/cjs/ion-datetime_3.cjs.entry.js +35 -2
- package/dist/cjs/ion-input.cjs.entry.js +6 -13
- package/dist/cjs/ion-modal.cjs.entry.js +1 -1
- package/dist/cjs/ion-nav_2.cjs.entry.js +1 -1
- package/dist/cjs/ion-popover.cjs.entry.js +1 -1
- package/dist/cjs/ion-radio_2.cjs.entry.js +57 -6
- package/dist/cjs/ion-select_3.cjs.entry.js +56 -9
- package/dist/cjs/ion-textarea.cjs.entry.js +5 -12
- package/dist/cjs/ion-toggle.cjs.entry.js +59 -14
- package/dist/cjs/ionic.cjs.js +1 -1
- package/dist/cjs/{ios.transition-j9CclgEW.js → ios.transition-BOt_uW73.js} +1 -1
- package/dist/cjs/loader.cjs.js +1 -1
- package/dist/cjs/{md.transition-CwFyRSfv.js → md.transition-Dt968VXB.js} +1 -1
- package/dist/cjs/validity-BpS37YFM.js +19 -0
- package/dist/collection/components/accordion/accordion.js +93 -14
- package/dist/collection/components/button/button.js +3 -7
- package/dist/collection/components/checkbox/checkbox.js +68 -13
- package/dist/collection/components/datetime/datetime.js +35 -2
- package/dist/collection/components/header/header.ios.css +27 -1
- package/dist/collection/components/header/header.js +5 -4
- package/dist/collection/components/header/header.utils.js +37 -0
- package/dist/collection/components/input/input.js +6 -14
- package/dist/collection/components/radio-group/radio-group.js +64 -7
- package/dist/collection/components/select/select.js +60 -12
- package/dist/collection/components/textarea/textarea.js +5 -13
- package/dist/collection/components/toggle/toggle.js +63 -16
- package/dist/collection/utils/forms/index.js +1 -0
- package/dist/collection/utils/forms/validity.js +15 -0
- package/dist/collection/utils/test/playwright/page/utils/set-content.js +7 -0
- package/dist/collection/utils/test/playwright/page/utils/spy-on-event.js +32 -0
- package/dist/collection/utils/transition/index.js +74 -3
- package/dist/docs.json +1 -1
- package/dist/esm/{index-D6G2seR8.js → index-r2D9DEro.js} +76 -5
- package/dist/esm/index.js +3 -3
- package/dist/esm/ion-accordion_2.entry.js +91 -13
- package/dist/esm/ion-app_8.entry.js +43 -5
- package/dist/esm/ion-button_2.entry.js +3 -7
- package/dist/esm/ion-checkbox.entry.js +61 -12
- package/dist/esm/ion-datetime_3.entry.js +35 -2
- package/dist/esm/ion-input.entry.js +6 -13
- package/dist/esm/ion-modal.entry.js +1 -1
- package/dist/esm/ion-nav_2.entry.js +1 -1
- package/dist/esm/ion-popover.entry.js +1 -1
- package/dist/esm/ion-radio_2.entry.js +57 -6
- package/dist/esm/ion-select_3.entry.js +56 -9
- package/dist/esm/ion-textarea.entry.js +5 -12
- package/dist/esm/ion-toggle.entry.js +59 -14
- package/dist/esm/ionic.js +1 -1
- package/dist/esm/{ios.transition-Bpq9ixwv.js → ios.transition-BDzw0_Hm.js} +1 -1
- package/dist/esm/loader.js +1 -1
- package/dist/esm/{md.transition-zOA0oanq.js → md.transition-BzDYi3qq.js} +1 -1
- package/dist/esm/validity-DJztqcrH.js +17 -0
- package/dist/ionic/index.esm.js +1 -1
- package/dist/ionic/ionic.esm.js +1 -1
- package/dist/ionic/p-40c261a3.entry.js +4 -0
- package/dist/ionic/p-43ed1ef5.entry.js +4 -0
- package/dist/ionic/p-4e41ea20.entry.js +4 -0
- package/dist/ionic/{p-323421af.entry.js → p-5a39a99a.entry.js} +1 -1
- package/dist/ionic/p-5fb517e4.entry.js +4 -0
- package/dist/ionic/p-7380261c.entry.js +4 -0
- package/dist/ionic/{p-9a36e2e7.entry.js → p-95bddd49.entry.js} +1 -1
- package/dist/ionic/{p-DPhQmGJN.js → p-C7hRNDhM.js} +1 -1
- package/dist/ionic/p-DJztqcrH.js +4 -0
- package/dist/ionic/p-DUt5fQmA.js +4 -0
- package/dist/ionic/{p-9R1XyICs.js → p-DZRJwG4S.js} +1 -1
- package/dist/ionic/p-c19f63d0.entry.js +4 -0
- package/dist/ionic/p-cb93126d.entry.js +4 -0
- package/dist/ionic/p-d0a2a1ab.entry.js +4 -0
- package/dist/ionic/p-d1f54e28.entry.js +4 -0
- package/dist/ionic/p-d3014190.entry.js +4 -0
- package/dist/ionic/{p-de7b5fa3.entry.js → p-e16b69e1.entry.js} +1 -1
- package/dist/ionic/svg/checkbox-outline.svg +1 -0
- package/dist/ionic/svg/checkbox-sharp.svg +1 -0
- package/dist/ionic/svg/checkbox.svg +1 -0
- package/dist/ionic/svg/checkmark-circle-outline.svg +1 -0
- package/dist/ionic/svg/checkmark-circle-sharp.svg +1 -0
- package/dist/ionic/svg/checkmark-circle.svg +1 -0
- package/dist/ionic/svg/checkmark-done-circle-outline.svg +1 -0
- package/dist/ionic/svg/checkmark-done-circle-sharp.svg +1 -0
- package/dist/ionic/svg/checkmark-done-circle.svg +1 -0
- package/dist/ionic/svg/checkmark-done-outline.svg +1 -0
- package/dist/ionic/svg/checkmark-done-sharp.svg +1 -0
- package/dist/ionic/svg/checkmark-done.svg +1 -0
- package/dist/ionic/svg/checkmark-outline.svg +1 -0
- package/dist/ionic/svg/checkmark-sharp.svg +1 -0
- package/dist/ionic/svg/checkmark.svg +1 -0
- package/dist/ionic/svg/chevron-back-circle-outline.svg +1 -0
- package/dist/ionic/svg/chevron-back-circle-sharp.svg +1 -0
- package/dist/ionic/svg/chevron-back-circle.svg +1 -0
- package/dist/ionic/svg/chevron-back-outline.svg +1 -0
- package/dist/ionic/svg/chevron-back-sharp.svg +1 -0
- package/dist/ionic/svg/chevron-back.svg +1 -0
- package/dist/ionic/svg/chevron-collapse-outline.svg +1 -0
- package/dist/ionic/svg/chevron-collapse-sharp.svg +1 -0
- package/dist/ionic/svg/chevron-collapse.svg +1 -0
- package/dist/ionic/svg/chevron-down-circle-outline.svg +1 -0
- package/dist/ionic/svg/chevron-down-circle-sharp.svg +1 -0
- package/dist/ionic/svg/chevron-down-circle.svg +1 -0
- package/dist/ionic/svg/chevron-down-outline.svg +1 -0
- package/dist/ionic/svg/chevron-down-sharp.svg +1 -0
- package/dist/ionic/svg/chevron-down.svg +1 -0
- package/dist/ionic/svg/chevron-expand-outline.svg +1 -0
- package/dist/ionic/svg/chevron-expand-sharp.svg +1 -0
- package/dist/ionic/svg/chevron-expand.svg +1 -0
- package/dist/ionic/svg/chevron-forward-circle-outline.svg +1 -0
- package/dist/ionic/svg/chevron-forward-circle-sharp.svg +1 -0
- package/dist/ionic/svg/chevron-forward-circle.svg +1 -0
- package/dist/ionic/svg/chevron-forward-outline.svg +1 -0
- package/dist/ionic/svg/chevron-forward-sharp.svg +1 -0
- package/dist/ionic/svg/chevron-forward.svg +1 -0
- package/dist/ionic/svg/chevron-up-circle-outline.svg +1 -0
- package/dist/ionic/svg/chevron-up-circle-sharp.svg +1 -0
- package/dist/ionic/svg/chevron-up-circle.svg +1 -0
- package/dist/ionic/svg/chevron-up-outline.svg +1 -0
- package/dist/ionic/svg/chevron-up-sharp.svg +1 -0
- package/dist/ionic/svg/chevron-up.svg +1 -0
- package/dist/ionic/svg/clipboard-outline.svg +1 -0
- package/dist/ionic/svg/clipboard-sharp.svg +1 -0
- package/dist/ionic/svg/clipboard.svg +1 -0
- package/dist/ionic/svg/close-circle-outline.svg +1 -0
- package/dist/ionic/svg/close-circle-sharp.svg +1 -0
- package/dist/ionic/svg/close-circle.svg +1 -0
- package/dist/ionic/svg/close-outline.svg +1 -0
- package/dist/ionic/svg/close-sharp.svg +1 -0
- package/dist/ionic/svg/close.svg +1 -0
- package/dist/ionic/svg/cloud-circle-outline.svg +1 -0
- package/dist/ionic/svg/cloud-circle-sharp.svg +1 -0
- package/dist/ionic/svg/cloud-circle.svg +1 -0
- package/dist/ionic/svg/cloud-done-outline.svg +1 -0
- package/dist/ionic/svg/cloud-done-sharp.svg +1 -0
- package/dist/ionic/svg/cloud-done.svg +1 -0
- package/dist/ionic/svg/cloud-download-outline.svg +1 -0
- package/dist/ionic/svg/cloud-download-sharp.svg +1 -0
- package/dist/ionic/svg/cloud-download.svg +1 -0
- package/dist/ionic/svg/cloud-offline-outline.svg +1 -0
- package/dist/ionic/svg/cloud-offline-sharp.svg +1 -0
- package/dist/ionic/svg/cloud-offline.svg +1 -0
- package/dist/ionic/svg/cloud-outline.svg +1 -0
- package/dist/ionic/svg/cloud-sharp.svg +1 -0
- package/dist/ionic/svg/cloud-upload-outline.svg +1 -0
- package/dist/ionic/svg/cloud-upload-sharp.svg +1 -0
- package/dist/ionic/svg/cloud-upload.svg +1 -0
- package/dist/ionic/svg/cloud.svg +1 -0
- package/dist/ionic/svg/cloudy-night-outline.svg +1 -0
- package/dist/ionic/svg/cloudy-night-sharp.svg +1 -0
- package/dist/ionic/svg/cloudy-night.svg +1 -0
- package/dist/ionic/svg/cloudy-outline.svg +1 -0
- package/dist/ionic/svg/cloudy-sharp.svg +1 -0
- package/dist/ionic/svg/cloudy.svg +1 -0
- package/dist/ionic/svg/code-download-outline.svg +1 -0
- package/dist/ionic/svg/code-download-sharp.svg +1 -0
- package/dist/ionic/svg/code-download.svg +1 -0
- package/dist/ionic/svg/code-outline.svg +1 -0
- package/dist/ionic/svg/code-sharp.svg +1 -0
- package/dist/ionic/svg/code-slash-outline.svg +1 -0
- package/dist/ionic/svg/code-slash-sharp.svg +1 -0
- package/dist/ionic/svg/code-slash.svg +1 -0
- package/dist/ionic/svg/code-working-outline.svg +1 -0
- package/dist/ionic/svg/code-working-sharp.svg +1 -0
- package/dist/ionic/svg/code-working.svg +1 -0
- package/dist/ionic/svg/code.svg +1 -0
- package/dist/ionic/svg/cog-outline.svg +1 -0
- package/dist/ionic/svg/cog-sharp.svg +1 -0
- package/dist/ionic/svg/cog.svg +1 -0
- package/dist/ionic/svg/color-fill-outline.svg +1 -0
- package/dist/ionic/svg/color-fill-sharp.svg +1 -0
- package/dist/ionic/svg/color-fill.svg +1 -0
- package/dist/ionic/svg/color-filter-outline.svg +1 -0
- package/dist/ionic/svg/color-filter-sharp.svg +1 -0
- package/dist/ionic/svg/color-filter.svg +1 -0
- package/dist/ionic/svg/color-palette-outline.svg +1 -0
- package/dist/ionic/svg/color-palette-sharp.svg +1 -0
- package/dist/ionic/svg/color-palette.svg +1 -0
- package/dist/ionic/svg/color-wand-outline.svg +1 -0
- package/dist/ionic/svg/color-wand-sharp.svg +1 -0
- package/dist/ionic/svg/color-wand.svg +1 -0
- package/dist/ionic/svg/compass-outline.svg +1 -0
- package/dist/ionic/svg/compass-sharp.svg +1 -0
- package/dist/ionic/svg/compass.svg +1 -0
- package/dist/ionic/svg/construct-outline.svg +1 -0
- package/dist/ionic/svg/construct-sharp.svg +1 -0
- package/dist/ionic/svg/construct.svg +1 -0
- package/dist/ionic/svg/contract-outline.svg +1 -0
- package/dist/ionic/svg/contract-sharp.svg +1 -0
- package/dist/ionic/svg/contract.svg +1 -0
- package/dist/ionic/svg/contrast-outline.svg +1 -0
- package/dist/ionic/svg/contrast-sharp.svg +1 -0
- package/dist/ionic/svg/contrast.svg +1 -0
- package/dist/ionic/svg/copy-outline.svg +1 -0
- package/dist/ionic/svg/copy-sharp.svg +1 -0
- package/dist/ionic/svg/copy.svg +1 -0
- package/dist/ionic/svg/create-outline.svg +1 -0
- package/dist/ionic/svg/create-sharp.svg +1 -0
- package/dist/ionic/svg/create.svg +1 -0
- package/dist/ionic/svg/crop-outline.svg +1 -0
- package/dist/ionic/svg/crop-sharp.svg +1 -0
- package/dist/ionic/svg/crop.svg +1 -0
- package/dist/ionic/svg/cube-outline.svg +1 -0
- package/dist/ionic/svg/cube-sharp.svg +1 -0
- package/dist/ionic/svg/cube.svg +1 -0
- package/dist/ionic/svg/cut-outline.svg +1 -0
- package/dist/ionic/svg/cut-sharp.svg +1 -0
- package/dist/ionic/svg/cut.svg +1 -0
- package/dist/ionic/svg/desktop-outline.svg +1 -0
- package/dist/ionic/svg/desktop-sharp.svg +1 -0
- package/dist/ionic/svg/desktop.svg +1 -0
- package/dist/ionic/svg/diamond-outline.svg +1 -0
- package/dist/ionic/svg/diamond-sharp.svg +1 -0
- package/dist/ionic/svg/diamond.svg +1 -0
- package/dist/ionic/svg/dice-outline.svg +1 -0
- package/dist/ionic/svg/dice-sharp.svg +1 -0
- package/dist/ionic/svg/dice.svg +1 -0
- package/dist/ionic/svg/disc-outline.svg +1 -0
- package/dist/ionic/svg/disc-sharp.svg +1 -0
- package/dist/ionic/svg/disc.svg +1 -0
- package/dist/ionic/svg/document-attach-outline.svg +1 -0
- package/dist/ionic/svg/document-attach-sharp.svg +1 -0
- package/dist/ionic/svg/document-attach.svg +1 -0
- package/dist/ionic/svg/document-lock-outline.svg +1 -0
- package/dist/ionic/svg/document-lock-sharp.svg +1 -0
- package/dist/ionic/svg/document-lock.svg +1 -0
- package/dist/ionic/svg/document-outline.svg +1 -0
- package/dist/types/components/accordion/accordion.d.ts +18 -1
- package/dist/types/components/checkbox/checkbox.d.ts +9 -2
- package/dist/types/components/datetime/datetime.d.ts +10 -0
- package/dist/types/components/header/header.utils.d.ts +10 -0
- package/dist/types/components/input/input.d.ts +0 -4
- package/dist/types/components/radio-group/radio-group.d.ts +9 -1
- package/dist/types/components/select/select.d.ts +7 -1
- package/dist/types/components/textarea/textarea.d.ts +0 -4
- package/dist/types/components/toggle/toggle.d.ts +7 -2
- package/dist/types/utils/forms/index.d.ts +1 -0
- package/dist/types/utils/forms/validity.d.ts +10 -0
- package/dist/types/utils/transition/index.d.ts +9 -0
- package/hydrate/index.js +687 -413
- package/hydrate/index.mjs +687 -413
- package/package.json +4 -4
- package/dist/ionic/p-1c8a476d.entry.js +0 -4
- package/dist/ionic/p-3355a2ff.entry.js +0 -4
- package/dist/ionic/p-4efea47a.entry.js +0 -4
- package/dist/ionic/p-62e50f80.entry.js +0 -4
- package/dist/ionic/p-785026d7.entry.js +0 -4
- package/dist/ionic/p-78c74a3e.entry.js +0 -4
- package/dist/ionic/p-7bcfc421.entry.js +0 -4
- package/dist/ionic/p-83fc84e7.entry.js +0 -4
- package/dist/ionic/p-913a7c1e.entry.js +0 -4
- package/dist/ionic/p-CMhMiYSX.js +0 -4
- package/dist/ionic/p-c17c0a01.entry.js +0 -4
|
@@ -786,6 +786,28 @@ const Datetime = class {
|
|
|
786
786
|
destroyKeyboardMO();
|
|
787
787
|
}
|
|
788
788
|
};
|
|
789
|
+
/**
|
|
790
|
+
* TODO(FW-6931): Remove this fallback upon solving the root cause
|
|
791
|
+
* Fallback to ensure the datetime becomes ready even if
|
|
792
|
+
* IntersectionObserver never reports it as intersecting.
|
|
793
|
+
*
|
|
794
|
+
* This is primarily used in environments where the observer
|
|
795
|
+
* might not fire as expected, such as when running under
|
|
796
|
+
* synthetic tests that stub IntersectionObserver.
|
|
797
|
+
*/
|
|
798
|
+
this.ensureReadyIfVisible = () => {
|
|
799
|
+
if (this.el.classList.contains('datetime-ready')) {
|
|
800
|
+
return;
|
|
801
|
+
}
|
|
802
|
+
const rect = this.el.getBoundingClientRect();
|
|
803
|
+
if (rect.width === 0 || rect.height === 0) {
|
|
804
|
+
return;
|
|
805
|
+
}
|
|
806
|
+
this.initializeListeners();
|
|
807
|
+
index.writeTask(() => {
|
|
808
|
+
this.el.classList.add('datetime-ready');
|
|
809
|
+
});
|
|
810
|
+
};
|
|
789
811
|
this.processValue = (value) => {
|
|
790
812
|
const hasValue = value !== null && value !== undefined && value !== '' && (!Array.isArray(value) || value.length > 0);
|
|
791
813
|
const valueToProcess = hasValue ? data.parseDate(value) : this.defaultParts;
|
|
@@ -1103,6 +1125,17 @@ const Datetime = class {
|
|
|
1103
1125
|
* triggering the `hiddenIO` observer below.
|
|
1104
1126
|
*/
|
|
1105
1127
|
helpers.raf(() => visibleIO === null || visibleIO === void 0 ? void 0 : visibleIO.observe(intersectionTrackerRef));
|
|
1128
|
+
/**
|
|
1129
|
+
* TODO(FW-6931): Remove this fallback upon solving the root cause
|
|
1130
|
+
* Fallback: If IntersectionObserver never reports that the
|
|
1131
|
+
* datetime is visible but the host clearly has layout, ensure
|
|
1132
|
+
* we still initialize listeners and mark the component as ready.
|
|
1133
|
+
*
|
|
1134
|
+
* We schedule this after everything has had a chance to run.
|
|
1135
|
+
*/
|
|
1136
|
+
setTimeout(() => {
|
|
1137
|
+
this.ensureReadyIfVisible();
|
|
1138
|
+
}, 100);
|
|
1106
1139
|
/**
|
|
1107
1140
|
* We need to clean up listeners when the datetime is hidden
|
|
1108
1141
|
* in a popover/modal so that we can properly scroll containers
|
|
@@ -1858,7 +1891,7 @@ const Datetime = class {
|
|
|
1858
1891
|
const hasDatePresentation = presentation === 'date' || presentation === 'date-time' || presentation === 'time-date';
|
|
1859
1892
|
const hasWheelVariant = hasDatePresentation && preferWheel;
|
|
1860
1893
|
helpers.renderHiddenInput(true, el, name, data.formatValue(value), disabled);
|
|
1861
|
-
return (index.h(index.Host, { key: '
|
|
1894
|
+
return (index.h(index.Host, { key: 'efdbc0922670a841bc667ceac392cdc1dedffd01', "aria-disabled": disabled ? 'true' : null, onFocus: this.onFocus, onBlur: this.onBlur, class: Object.assign({}, theme.createColorClasses(color, {
|
|
1862
1895
|
[mode]: true,
|
|
1863
1896
|
['datetime-readonly']: readonly,
|
|
1864
1897
|
['datetime-disabled']: disabled,
|
|
@@ -1868,7 +1901,7 @@ const Datetime = class {
|
|
|
1868
1901
|
[`datetime-size-${size}`]: true,
|
|
1869
1902
|
[`datetime-prefer-wheel`]: hasWheelVariant,
|
|
1870
1903
|
[`datetime-grid`]: isGridStyle,
|
|
1871
|
-
})) }, index.h("div", { key: '
|
|
1904
|
+
})) }, index.h("div", { key: '3f8bb75fcb0baff55182ef3aa1b535eacc58d81f', class: "intersection-tracker", ref: (el) => (this.intersectionTrackerRef = el) }), this.renderDatetime(mode)));
|
|
1872
1905
|
}
|
|
1873
1906
|
get el() { return index.getElement(this); }
|
|
1874
1907
|
static get watchers() { return {
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
|
|
6
6
|
var index = require('./index-D6Wc6v08.js');
|
|
7
7
|
var notchController = require('./notch-controller-Bzqhjm4f.js');
|
|
8
|
+
var validity = require('./validity-BpS37YFM.js');
|
|
8
9
|
var helpers = require('./helpers-DrTqNghc.js');
|
|
9
10
|
var input_utils = require('./input.utils-B_QROI2g.js');
|
|
10
11
|
var theme = require('./theme-CeDs6Hcv.js');
|
|
@@ -232,14 +233,6 @@ const Input = class {
|
|
|
232
233
|
componentWillLoad() {
|
|
233
234
|
this.inheritedAttributes = Object.assign(Object.assign({}, helpers.inheritAriaAttributes(this.el)), helpers.inheritAttributes(this.el, ['tabindex', 'title', 'data-form-type', 'dir']));
|
|
234
235
|
}
|
|
235
|
-
/**
|
|
236
|
-
* Checks if the input is in an invalid state based on Ionic validation classes
|
|
237
|
-
*/
|
|
238
|
-
checkInvalidState() {
|
|
239
|
-
const hasIonTouched = this.el.classList.contains('ion-touched');
|
|
240
|
-
const hasIonInvalid = this.el.classList.contains('ion-invalid');
|
|
241
|
-
return hasIonTouched && hasIonInvalid;
|
|
242
|
-
}
|
|
243
236
|
connectedCallback() {
|
|
244
237
|
const { el } = this;
|
|
245
238
|
this.slotMutationController = input_utils.createSlotMutationController(el, ['label', 'start', 'end'], () => index.forceUpdate(this));
|
|
@@ -247,7 +240,7 @@ const Input = class {
|
|
|
247
240
|
// Watch for class changes to update validation state
|
|
248
241
|
if (typeof MutationObserver !== 'undefined') {
|
|
249
242
|
this.validationObserver = new MutationObserver(() => {
|
|
250
|
-
const newIsInvalid =
|
|
243
|
+
const newIsInvalid = validity.checkInvalidState(el);
|
|
251
244
|
if (this.isInvalid !== newIsInvalid) {
|
|
252
245
|
this.isInvalid = newIsInvalid;
|
|
253
246
|
// Force a re-render to update aria-describedby immediately
|
|
@@ -260,7 +253,7 @@ const Input = class {
|
|
|
260
253
|
});
|
|
261
254
|
}
|
|
262
255
|
// Always set initial state
|
|
263
|
-
this.isInvalid =
|
|
256
|
+
this.isInvalid = validity.checkInvalidState(el);
|
|
264
257
|
this.debounceChanged();
|
|
265
258
|
{
|
|
266
259
|
document.dispatchEvent(new CustomEvent('ionInputDidLoad', {
|
|
@@ -524,7 +517,7 @@ const Input = class {
|
|
|
524
517
|
* TODO(FW-5592): Remove hasStartEndSlots condition
|
|
525
518
|
*/
|
|
526
519
|
const labelShouldFloat = labelPlacement === 'stacked' || (labelPlacement === 'floating' && (hasValue || hasFocus || hasStartEndSlots));
|
|
527
|
-
return (index.h(index.Host, { key: '
|
|
520
|
+
return (index.h(index.Host, { key: '97b5308021064d9e7434ef2d3d96f27045c1b0c4', class: theme.createColorClasses(this.color, {
|
|
528
521
|
[mode]: true,
|
|
529
522
|
'has-value': hasValue,
|
|
530
523
|
'has-focus': hasFocus,
|
|
@@ -535,14 +528,14 @@ const Input = class {
|
|
|
535
528
|
'in-item': inItem,
|
|
536
529
|
'in-item-color': theme.hostContext('ion-item.ion-color', this.el),
|
|
537
530
|
'input-disabled': disabled,
|
|
538
|
-
}) }, index.h("label", { key: '
|
|
531
|
+
}) }, index.h("label", { key: '353f68726ce180299bd9adc81e5ff7d26a48f54f', class: "input-wrapper", htmlFor: inputId, onClick: this.onLabelClick }, this.renderLabelContainer(), index.h("div", { key: '2034b4bad04fc157f3298a1805819216b6f439d0', class: "native-wrapper", onClick: this.onLabelClick }, index.h("slot", { key: '96bb5e30176b2bd76dfb75bfbf6c1c3d4403f4bb', name: "start" }), index.h("input", Object.assign({ key: '1a1d75b0e414a95c89d5a760757c33548d234aca', 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 && (index.h("button", { key: '95f3df17b7691d9a2e7dcd4a51f16a94aa3ca36f', "aria-label": "reset", type: "button", class: "input-clear-icon", onPointerDown: (ev) => {
|
|
539
532
|
/**
|
|
540
533
|
* This prevents mobile browsers from
|
|
541
534
|
* blurring the input when the clear
|
|
542
535
|
* button is activated.
|
|
543
536
|
*/
|
|
544
537
|
ev.preventDefault();
|
|
545
|
-
}, onClick: this.clearTextInput }, index.h("ion-icon", { key: '
|
|
538
|
+
}, onClick: this.clearTextInput }, index.h("ion-icon", { key: '16b0af75eed50c8115fb5597f73b5fbf71c2530e', "aria-hidden": "true", icon: clearIconData }))), index.h("slot", { key: 'c48da0f8ddb3764ac43efa705bb4a6bb2d9cc2fd', name: "end" })), shouldRenderHighlight && index.h("div", { key: 'f15238481fc20de56ca7ecb6e350b3c024cc755e', class: "input-highlight" })), this.renderBottomContent()));
|
|
546
539
|
}
|
|
547
540
|
get el() { return index.getElement(this); }
|
|
548
541
|
static get watchers() { return {
|
|
@@ -11,7 +11,7 @@ var lockController = require('./lock-controller-aDB9wrEf.js');
|
|
|
11
11
|
var capacitor = require('./capacitor-DmA66EwP.js');
|
|
12
12
|
var overlays = require('./overlays-DxIZwUXI.js');
|
|
13
13
|
var theme = require('./theme-CeDs6Hcv.js');
|
|
14
|
-
var index$4 = require('./index-
|
|
14
|
+
var index$4 = require('./index-094mMFB-.js');
|
|
15
15
|
var ionicGlobal = require('./ionic-global-HMVqOFGO.js');
|
|
16
16
|
var keyboard = require('./keyboard-hHzlEQpk.js');
|
|
17
17
|
var animation = require('./animation-Bt3H9L1C.js');
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
var index = require('./index-D6Wc6v08.js');
|
|
7
7
|
var cubicBezier = require('./cubic-bezier-DAjy1V-e.js');
|
|
8
8
|
var helpers = require('./helpers-DrTqNghc.js');
|
|
9
|
-
var index$1 = require('./index-
|
|
9
|
+
var index$1 = require('./index-094mMFB-.js');
|
|
10
10
|
var ionicGlobal = require('./ionic-global-HMVqOFGO.js');
|
|
11
11
|
var frameworkDelegate = require('./framework-delegate-DMJRBuDi.js');
|
|
12
12
|
|
|
@@ -10,7 +10,7 @@ var helpers = require('./helpers-DrTqNghc.js');
|
|
|
10
10
|
var lockController = require('./lock-controller-aDB9wrEf.js');
|
|
11
11
|
var ionicGlobal = require('./ionic-global-HMVqOFGO.js');
|
|
12
12
|
var theme = require('./theme-CeDs6Hcv.js');
|
|
13
|
-
var index$1 = require('./index-
|
|
13
|
+
var index$1 = require('./index-094mMFB-.js');
|
|
14
14
|
var animation = require('./animation-Bt3H9L1C.js');
|
|
15
15
|
require('./index-DkNv4J_i.js');
|
|
16
16
|
require('./hardware-back-button-VCK4V3mG.js');
|
|
@@ -8,6 +8,7 @@ var helpers = require('./helpers-DrTqNghc.js');
|
|
|
8
8
|
var compareWithUtils = require('./compare-with-utils-DSicavqM.js');
|
|
9
9
|
var theme = require('./theme-CeDs6Hcv.js');
|
|
10
10
|
var ionicGlobal = require('./ionic-global-HMVqOFGO.js');
|
|
11
|
+
var validity = require('./validity-BpS37YFM.js');
|
|
11
12
|
|
|
12
13
|
const radioIosCss = ":host{--inner-border-radius:50%;display:inline-block;position:relative;max-width:100%;min-height:inherit;cursor:pointer;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;z-index:2;-webkit-box-sizing:border-box;box-sizing:border-box}:host(.radio-disabled){pointer-events:none}.radio-icon{display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center;-ms-flex-pack:center;justify-content:center;width:100%;height:100%;contain:layout size style}.radio-icon,.radio-inner{-webkit-box-sizing:border-box;box-sizing:border-box}input{position:absolute;top:0;left:0;right:0;bottom:0;width:100%;height:100%;margin:0;padding:0;border:0;outline:0;clip:rect(0 0 0 0);opacity:0;overflow:hidden;-webkit-appearance:none;-moz-appearance:none}:host(:focus){outline:none}:host(.in-item){-ms-flex:1 1 0px;flex:1 1 0;width:100%;height:100%}:host([slot=start]),:host([slot=end]){-ms-flex:initial;flex:initial;width:auto}.radio-wrapper{display:-ms-flexbox;display:flex;position:relative;-ms-flex-positive:1;flex-grow:1;-ms-flex-align:center;align-items:center;-ms-flex-pack:justify;justify-content:space-between;height:inherit;min-height:inherit;cursor:inherit}.label-text-wrapper{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}:host(.in-item) .label-text-wrapper{margin-top:10px;margin-bottom:10px}:host(.in-item.radio-label-placement-stacked) .label-text-wrapper{margin-top:10px;margin-bottom:16px}:host(.in-item.radio-label-placement-stacked) .native-wrapper{margin-bottom:10px}.label-text-wrapper-hidden{display:none}.native-wrapper{display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center}:host(.radio-justify-space-between) .radio-wrapper{-ms-flex-pack:justify;justify-content:space-between}:host(.radio-justify-start) .radio-wrapper{-ms-flex-pack:start;justify-content:start}:host(.radio-justify-end) .radio-wrapper{-ms-flex-pack:end;justify-content:end}:host(.radio-alignment-start) .radio-wrapper{-ms-flex-align:start;align-items:start}:host(.radio-alignment-center) .radio-wrapper{-ms-flex-align:center;align-items:center}:host(.radio-justify-space-between),:host(.radio-justify-start),:host(.radio-justify-end),:host(.radio-alignment-start),:host(.radio-alignment-center){display:block}:host(.radio-label-placement-start) .radio-wrapper{-ms-flex-direction:row;flex-direction:row}:host(.radio-label-placement-start) .label-text-wrapper{-webkit-margin-start:0;margin-inline-start:0;-webkit-margin-end:16px;margin-inline-end:16px}:host(.radio-label-placement-end) .radio-wrapper{-ms-flex-direction:row-reverse;flex-direction:row-reverse}:host(.radio-label-placement-end) .label-text-wrapper{-webkit-margin-start:16px;margin-inline-start:16px;-webkit-margin-end:0;margin-inline-end:0}:host(.radio-label-placement-fixed) .label-text-wrapper{-webkit-margin-start:0;margin-inline-start:0;-webkit-margin-end:16px;margin-inline-end:16px}:host(.radio-label-placement-fixed) .label-text-wrapper{-ms-flex:0 0 100px;flex:0 0 100px;width:100px;min-width:100px}:host(.radio-label-placement-stacked) .radio-wrapper{-ms-flex-direction:column;flex-direction:column}:host(.radio-label-placement-stacked) .label-text-wrapper{-webkit-transform:scale(0.75);transform:scale(0.75);margin-left:0;margin-right:0;margin-bottom:16px;max-width:calc(100% / 0.75)}:host(.radio-label-placement-stacked.radio-alignment-start) .label-text-wrapper{-webkit-transform-origin:left top;transform-origin:left top}:host-context([dir=rtl]):host(.radio-label-placement-stacked.radio-alignment-start) .label-text-wrapper,:host-context([dir=rtl]).radio-label-placement-stacked.radio-alignment-start .label-text-wrapper{-webkit-transform-origin:right top;transform-origin:right top}@supports selector(:dir(rtl)){:host(.radio-label-placement-stacked.radio-alignment-start:dir(rtl)) .label-text-wrapper{-webkit-transform-origin:right top;transform-origin:right top}}:host(.radio-label-placement-stacked.radio-alignment-center) .label-text-wrapper{-webkit-transform-origin:center top;transform-origin:center top}:host-context([dir=rtl]):host(.radio-label-placement-stacked.radio-alignment-center) .label-text-wrapper,:host-context([dir=rtl]).radio-label-placement-stacked.radio-alignment-center .label-text-wrapper{-webkit-transform-origin:calc(100% - center) top;transform-origin:calc(100% - center) top}@supports selector(:dir(rtl)){:host(.radio-label-placement-stacked.radio-alignment-center:dir(rtl)) .label-text-wrapper{-webkit-transform-origin:calc(100% - center) top;transform-origin:calc(100% - center) top}}:host{--color-checked:var(--ion-color-primary, #0054e9)}:host(.ion-color.radio-checked) .radio-inner{border-color:var(--ion-color-base)}.item-radio.item-ios ion-label{-webkit-margin-start:0;margin-inline-start:0}.radio-inner{width:33%;height:50%}:host(.radio-checked) .radio-inner{-webkit-transform:rotate(45deg);transform:rotate(45deg);border-width:0.125rem;border-top-width:0;border-left-width:0;border-style:solid;border-color:var(--color-checked)}:host(.radio-disabled){opacity:0.3}:host(.ion-focused) .radio-icon::after{border-radius:var(--inner-border-radius);top:-8px;display:block;position:absolute;width:36px;height:36px;background:var(--ion-color-primary-tint, #1a65eb);content:\"\";opacity:0.2}:host(.ion-focused) .radio-icon::after{inset-inline-start:-9px}.native-wrapper .radio-icon{width:0.9375rem;height:1.5rem}";
|
|
13
14
|
|
|
@@ -177,6 +178,10 @@ const RadioGroup = class {
|
|
|
177
178
|
this.helperTextId = `${this.inputId}-helper-text`;
|
|
178
179
|
this.errorTextId = `${this.inputId}-error-text`;
|
|
179
180
|
this.labelId = `${this.inputId}-lbl`;
|
|
181
|
+
/**
|
|
182
|
+
* Track validation state for proper aria-live announcements.
|
|
183
|
+
*/
|
|
184
|
+
this.isInvalid = false;
|
|
180
185
|
/**
|
|
181
186
|
* If `true`, the radios can be deselected.
|
|
182
187
|
*/
|
|
@@ -258,6 +263,52 @@ const RadioGroup = class {
|
|
|
258
263
|
this.labelId = label.id = this.name + '-lbl';
|
|
259
264
|
}
|
|
260
265
|
}
|
|
266
|
+
// Watch for class changes to update validation state.
|
|
267
|
+
if (typeof MutationObserver !== 'undefined') {
|
|
268
|
+
this.validationObserver = new MutationObserver(() => {
|
|
269
|
+
const newIsInvalid = validity.checkInvalidState(this.el);
|
|
270
|
+
if (this.isInvalid !== newIsInvalid) {
|
|
271
|
+
this.isInvalid = newIsInvalid;
|
|
272
|
+
/**
|
|
273
|
+
* Screen readers tend to announce changes
|
|
274
|
+
* to `aria-describedby` when the attribute
|
|
275
|
+
* is changed during a blur event for a
|
|
276
|
+
* native form control.
|
|
277
|
+
* However, the announcement can be spotty
|
|
278
|
+
* when using a non-native form control
|
|
279
|
+
* and `forceUpdate()`.
|
|
280
|
+
* This is due to `forceUpdate()` internally
|
|
281
|
+
* rescheduling the DOM update to a lower
|
|
282
|
+
* priority queue regardless if it's called
|
|
283
|
+
* inside a Promise or not, thus causing
|
|
284
|
+
* the screen reader to potentially miss the
|
|
285
|
+
* change.
|
|
286
|
+
* By using a State variable inside a Promise,
|
|
287
|
+
* it guarantees a re-render immediately at
|
|
288
|
+
* a higher priority.
|
|
289
|
+
*/
|
|
290
|
+
Promise.resolve().then(() => {
|
|
291
|
+
this.hintTextId = this.getHintTextId();
|
|
292
|
+
});
|
|
293
|
+
}
|
|
294
|
+
});
|
|
295
|
+
this.validationObserver.observe(this.el, {
|
|
296
|
+
attributes: true,
|
|
297
|
+
attributeFilter: ['class'],
|
|
298
|
+
});
|
|
299
|
+
}
|
|
300
|
+
// Always set initial state
|
|
301
|
+
this.isInvalid = validity.checkInvalidState(this.el);
|
|
302
|
+
}
|
|
303
|
+
componentWillLoad() {
|
|
304
|
+
this.hintTextId = this.getHintTextId();
|
|
305
|
+
}
|
|
306
|
+
disconnectedCallback() {
|
|
307
|
+
// Clean up validation observer to prevent memory leaks.
|
|
308
|
+
if (this.validationObserver) {
|
|
309
|
+
this.validationObserver.disconnect();
|
|
310
|
+
this.validationObserver = undefined;
|
|
311
|
+
}
|
|
261
312
|
}
|
|
262
313
|
getRadios() {
|
|
263
314
|
return Array.from(this.el.querySelectorAll('ion-radio'));
|
|
@@ -333,16 +384,16 @@ const RadioGroup = class {
|
|
|
333
384
|
* Renders the helper text or error text values
|
|
334
385
|
*/
|
|
335
386
|
renderHintText() {
|
|
336
|
-
const { helperText, errorText, helperTextId, errorTextId } = this;
|
|
387
|
+
const { helperText, errorText, helperTextId, errorTextId, isInvalid } = this;
|
|
337
388
|
const hasHintText = !!helperText || !!errorText;
|
|
338
389
|
if (!hasHintText) {
|
|
339
390
|
return;
|
|
340
391
|
}
|
|
341
|
-
return (index.h("div", { class: "radio-group-top" }, index.h("div", { id: helperTextId, class: "helper-text" }, helperText), index.h("div", { id: errorTextId, class: "error-text" }, errorText)));
|
|
392
|
+
return (index.h("div", { class: "radio-group-top" }, index.h("div", { id: helperTextId, class: "helper-text", "aria-live": "polite" }, !isInvalid ? helperText : null), index.h("div", { id: errorTextId, class: "error-text", role: "alert" }, isInvalid ? errorText : null)));
|
|
342
393
|
}
|
|
343
|
-
|
|
344
|
-
const {
|
|
345
|
-
if (
|
|
394
|
+
getHintTextId() {
|
|
395
|
+
const { helperText, errorText, helperTextId, errorTextId, isInvalid } = this;
|
|
396
|
+
if (isInvalid && errorText) {
|
|
346
397
|
return errorTextId;
|
|
347
398
|
}
|
|
348
399
|
if (helperText) {
|
|
@@ -354,7 +405,7 @@ const RadioGroup = class {
|
|
|
354
405
|
const { label, labelId, el, name, value } = this;
|
|
355
406
|
const mode = ionicGlobal.getIonMode(this);
|
|
356
407
|
helpers.renderHiddenInput(true, el, name, value, false);
|
|
357
|
-
return (index.h(index.Host, { key: '
|
|
408
|
+
return (index.h(index.Host, { key: 'db593b3ed511e9395e3c7bfd91b787328692cd6d', role: "radiogroup", "aria-labelledby": label ? labelId : null, "aria-describedby": this.hintTextId, "aria-invalid": this.isInvalid ? 'true' : undefined, onClick: this.onClick, class: mode }, this.renderHintText(), index.h("div", { key: '85045b45a0100a45f3b9a35d1c5a25ec63d525c4', class: "radio-group-wrapper" }, index.h("slot", { key: '53dacb87ce62398e78771fb2efaf839ab922d946' }))));
|
|
358
409
|
}
|
|
359
410
|
get el() { return index.getElement(this); }
|
|
360
411
|
static get watchers() { return {
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
var index = require('./index-D6Wc6v08.js');
|
|
7
7
|
var notchController = require('./notch-controller-Bzqhjm4f.js');
|
|
8
8
|
var compareWithUtils = require('./compare-with-utils-DSicavqM.js');
|
|
9
|
+
var validity = require('./validity-BpS37YFM.js');
|
|
9
10
|
var helpers = require('./helpers-DrTqNghc.js');
|
|
10
11
|
var overlays = require('./overlays-DxIZwUXI.js');
|
|
11
12
|
var dir = require('./dir-Cn0z1rJH.js');
|
|
@@ -45,6 +46,10 @@ const Select = class {
|
|
|
45
46
|
* is applied in both cases.
|
|
46
47
|
*/
|
|
47
48
|
this.hasFocus = false;
|
|
49
|
+
/**
|
|
50
|
+
* Track validation state for proper aria-live announcements.
|
|
51
|
+
*/
|
|
52
|
+
this.isInvalid = false;
|
|
48
53
|
/**
|
|
49
54
|
* The text to display on the cancel button.
|
|
50
55
|
*/
|
|
@@ -174,9 +179,46 @@ const Select = class {
|
|
|
174
179
|
*/
|
|
175
180
|
index.forceUpdate(this);
|
|
176
181
|
});
|
|
182
|
+
// Watch for class changes to update validation state.
|
|
183
|
+
if (typeof MutationObserver !== 'undefined') {
|
|
184
|
+
this.validationObserver = new MutationObserver(() => {
|
|
185
|
+
const newIsInvalid = validity.checkInvalidState(this.el);
|
|
186
|
+
if (this.isInvalid !== newIsInvalid) {
|
|
187
|
+
this.isInvalid = newIsInvalid;
|
|
188
|
+
/**
|
|
189
|
+
* Screen readers tend to announce changes
|
|
190
|
+
* to `aria-describedby` when the attribute
|
|
191
|
+
* is changed during a blur event for a
|
|
192
|
+
* native form control.
|
|
193
|
+
* However, the announcement can be spotty
|
|
194
|
+
* when using a non-native form control
|
|
195
|
+
* and `forceUpdate()`.
|
|
196
|
+
* This is due to `forceUpdate()` internally
|
|
197
|
+
* rescheduling the DOM update to a lower
|
|
198
|
+
* priority queue regardless if it's called
|
|
199
|
+
* inside a Promise or not, thus causing
|
|
200
|
+
* the screen reader to potentially miss the
|
|
201
|
+
* change.
|
|
202
|
+
* By using a State variable inside a Promise,
|
|
203
|
+
* it guarantees a re-render immediately at
|
|
204
|
+
* a higher priority.
|
|
205
|
+
*/
|
|
206
|
+
Promise.resolve().then(() => {
|
|
207
|
+
this.hintTextId = this.getHintTextId();
|
|
208
|
+
});
|
|
209
|
+
}
|
|
210
|
+
});
|
|
211
|
+
this.validationObserver.observe(el, {
|
|
212
|
+
attributes: true,
|
|
213
|
+
attributeFilter: ['class'],
|
|
214
|
+
});
|
|
215
|
+
}
|
|
216
|
+
// Always set initial state
|
|
217
|
+
this.isInvalid = validity.checkInvalidState(this.el);
|
|
177
218
|
}
|
|
178
219
|
componentWillLoad() {
|
|
179
220
|
this.inheritedAttributes = helpers.inheritAttributes(this.el, ['aria-label']);
|
|
221
|
+
this.hintTextId = this.getHintTextId();
|
|
180
222
|
}
|
|
181
223
|
componentDidLoad() {
|
|
182
224
|
/**
|
|
@@ -200,6 +242,11 @@ const Select = class {
|
|
|
200
242
|
this.notchController.destroy();
|
|
201
243
|
this.notchController = undefined;
|
|
202
244
|
}
|
|
245
|
+
// Clean up validation observer to prevent memory leaks.
|
|
246
|
+
if (this.validationObserver) {
|
|
247
|
+
this.validationObserver.disconnect();
|
|
248
|
+
this.validationObserver = undefined;
|
|
249
|
+
}
|
|
203
250
|
}
|
|
204
251
|
/**
|
|
205
252
|
* Open the select overlay. The overlay is either an alert, action sheet, or popover,
|
|
@@ -670,11 +717,11 @@ const Select = class {
|
|
|
670
717
|
}
|
|
671
718
|
renderListbox() {
|
|
672
719
|
const { disabled, inputId, isExpanded, required } = this;
|
|
673
|
-
return (index.h("button", { disabled: disabled, id: inputId, "aria-label": this.ariaLabel, "aria-haspopup": "dialog", "aria-expanded": `${isExpanded}`, "aria-describedby": this.
|
|
720
|
+
return (index.h("button", { disabled: disabled, id: inputId, "aria-label": this.ariaLabel, "aria-haspopup": "dialog", "aria-expanded": `${isExpanded}`, "aria-describedby": this.hintTextId, "aria-invalid": this.isInvalid ? 'true' : undefined, "aria-required": `${required}`, onFocus: this.onFocus, onBlur: this.onBlur, ref: (focusEl) => (this.focusEl = focusEl) }));
|
|
674
721
|
}
|
|
675
|
-
|
|
676
|
-
const {
|
|
677
|
-
if (
|
|
722
|
+
getHintTextId() {
|
|
723
|
+
const { helperText, errorText, helperTextId, errorTextId, isInvalid } = this;
|
|
724
|
+
if (isInvalid && errorText) {
|
|
678
725
|
return errorTextId;
|
|
679
726
|
}
|
|
680
727
|
if (helperText) {
|
|
@@ -686,10 +733,10 @@ const Select = class {
|
|
|
686
733
|
* Renders the helper text or error text values
|
|
687
734
|
*/
|
|
688
735
|
renderHintText() {
|
|
689
|
-
const { helperText, errorText, helperTextId, errorTextId } = this;
|
|
736
|
+
const { helperText, errorText, helperTextId, errorTextId, isInvalid } = this;
|
|
690
737
|
return [
|
|
691
|
-
index.h("div", { id: helperTextId, class: "helper-text", part: "supporting-text helper-text" }, helperText),
|
|
692
|
-
index.h("div", { id: errorTextId, class: "error-text", part: "supporting-text error-text" }, errorText),
|
|
738
|
+
index.h("div", { id: helperTextId, class: "helper-text", part: "supporting-text helper-text", "aria-live": "polite" }, !isInvalid ? helperText : null),
|
|
739
|
+
index.h("div", { id: errorTextId, class: "error-text", part: "supporting-text error-text", role: "alert" }, isInvalid ? errorText : null),
|
|
693
740
|
];
|
|
694
741
|
}
|
|
695
742
|
/**
|
|
@@ -737,7 +784,7 @@ const Select = class {
|
|
|
737
784
|
* TODO(FW-5592): Remove hasStartEndSlots condition
|
|
738
785
|
*/
|
|
739
786
|
const labelShouldFloat = labelPlacement === 'stacked' || (labelPlacement === 'floating' && (hasValue || isExpanded || hasStartEndSlots));
|
|
740
|
-
return (index.h(index.Host, { key: '
|
|
787
|
+
return (index.h(index.Host, { key: '35b5e18e6f79a802ff2d46d1242e80ff755cc0b9', onClick: this.onClick, class: theme.createColorClasses(this.color, {
|
|
741
788
|
[mode]: true,
|
|
742
789
|
'in-item': inItem,
|
|
743
790
|
'in-item-color': theme.hostContext('ion-item.ion-color', el),
|
|
@@ -755,7 +802,7 @@ const Select = class {
|
|
|
755
802
|
[`select-justify-${justify}`]: justifyEnabled,
|
|
756
803
|
[`select-shape-${shape}`]: shape !== undefined,
|
|
757
804
|
[`select-label-placement-${labelPlacement}`]: true,
|
|
758
|
-
}) }, index.h("label", { key: '
|
|
805
|
+
}) }, index.h("label", { key: '6005b34a0c50bc4d7653a4276bc232ecd02e083c', class: "select-wrapper", id: "select-label", onClick: this.onLabelClick }, this.renderLabelContainer(), index.h("div", { key: 'c7e07aa81ae856c057f16275dd058f37c5670a47', class: "select-wrapper-inner" }, index.h("slot", { key: '7fc2deefe0424404caacdbbd9e08ed43ba55d28a', name: "start" }), index.h("div", { key: '157d74ee717b1bc30b5f1c233a09b0c8456aa68e', class: "native-wrapper", ref: (el) => (this.nativeWrapperEl = el), part: "container" }, this.renderSelectText(), this.renderListbox()), index.h("slot", { key: 'ea66db304528b82bf9317730b6dce3db2612f235', name: "end" }), !hasFloatingOrStackedLabel && this.renderSelectIcon()), hasFloatingOrStackedLabel && this.renderSelectIcon(), shouldRenderHighlight && index.h("div", { key: '786eb1530b7476f0615d4e7c0bf4e7e4dc66509c', class: "select-highlight" })), this.renderBottomContent()));
|
|
759
806
|
}
|
|
760
807
|
get el() { return index.getElement(this); }
|
|
761
808
|
static get watchers() { return {
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
|
|
6
6
|
var index = require('./index-D6Wc6v08.js');
|
|
7
7
|
var notchController = require('./notch-controller-Bzqhjm4f.js');
|
|
8
|
+
var validity = require('./validity-BpS37YFM.js');
|
|
8
9
|
var helpers = require('./helpers-DrTqNghc.js');
|
|
9
10
|
var input_utils = require('./input.utils-B_QROI2g.js');
|
|
10
11
|
var theme = require('./theme-CeDs6Hcv.js');
|
|
@@ -192,14 +193,6 @@ const Textarea = class {
|
|
|
192
193
|
this.el.click();
|
|
193
194
|
}
|
|
194
195
|
}
|
|
195
|
-
/**
|
|
196
|
-
* Checks if the textarea is in an invalid state based on Ionic validation classes
|
|
197
|
-
*/
|
|
198
|
-
checkValidationState() {
|
|
199
|
-
const hasIonTouched = this.el.classList.contains('ion-touched');
|
|
200
|
-
const hasIonInvalid = this.el.classList.contains('ion-invalid');
|
|
201
|
-
return hasIonTouched && hasIonInvalid;
|
|
202
|
-
}
|
|
203
196
|
connectedCallback() {
|
|
204
197
|
const { el } = this;
|
|
205
198
|
this.slotMutationController = input_utils.createSlotMutationController(el, ['label', 'start', 'end'], () => index.forceUpdate(this));
|
|
@@ -207,7 +200,7 @@ const Textarea = class {
|
|
|
207
200
|
// Watch for class changes to update validation state
|
|
208
201
|
if (typeof MutationObserver !== 'undefined') {
|
|
209
202
|
this.validationObserver = new MutationObserver(() => {
|
|
210
|
-
const newIsInvalid = this.
|
|
203
|
+
const newIsInvalid = validity.checkInvalidState(this.el);
|
|
211
204
|
if (this.isInvalid !== newIsInvalid) {
|
|
212
205
|
this.isInvalid = newIsInvalid;
|
|
213
206
|
// Force a re-render to update aria-describedby immediately
|
|
@@ -220,7 +213,7 @@ const Textarea = class {
|
|
|
220
213
|
});
|
|
221
214
|
}
|
|
222
215
|
// Always set initial state
|
|
223
|
-
this.isInvalid = this.
|
|
216
|
+
this.isInvalid = validity.checkInvalidState(this.el);
|
|
224
217
|
this.debounceChanged();
|
|
225
218
|
{
|
|
226
219
|
document.dispatchEvent(new CustomEvent('ionInputDidLoad', {
|
|
@@ -484,7 +477,7 @@ const Textarea = class {
|
|
|
484
477
|
* TODO(FW-5592): Remove hasStartEndSlots condition
|
|
485
478
|
*/
|
|
486
479
|
const labelShouldFloat = labelPlacement === 'stacked' || (labelPlacement === 'floating' && (hasValue || hasFocus || hasStartEndSlots));
|
|
487
|
-
return (index.h(index.Host, { key: '
|
|
480
|
+
return (index.h(index.Host, { key: 'a70a62d7aae3831a50acd74f60b930925ada1326', class: theme.createColorClasses(this.color, {
|
|
488
481
|
[mode]: true,
|
|
489
482
|
'has-value': hasValue,
|
|
490
483
|
'has-focus': hasFocus,
|
|
@@ -493,7 +486,7 @@ const Textarea = class {
|
|
|
493
486
|
[`textarea-shape-${shape}`]: shape !== undefined,
|
|
494
487
|
[`textarea-label-placement-${labelPlacement}`]: true,
|
|
495
488
|
'textarea-disabled': disabled,
|
|
496
|
-
}) }, index.h("label", { key: '
|
|
489
|
+
}) }, index.h("label", { key: '8a2dd59a60f7469df84018eb0ede3a9ec3862703', class: "textarea-wrapper", htmlFor: inputId, onClick: this.onLabelClick }, this.renderLabelContainer(), index.h("div", { key: '1bfc368236e3da7a225a45118c27fbfc1fe5fa46', class: "textarea-wrapper-inner" }, index.h("div", { key: '215cbb2635ff52e31a8973376989b85e7245d40f', class: "start-slot-wrapper" }, index.h("slot", { key: '9f6b461cdee9d629deb695d2bea054ece2f32305', name: "start" })), index.h("div", { key: 'c1af35a2d5bc452bebe0b22a26d15ff52b4e9fc8', class: "native-wrapper", ref: (el) => (this.textareaWrapper = el) }, index.h("textarea", Object.assign({ key: '69a69b3cf0932baafbe37e6e846f1a571608d3f2', 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)), index.h("div", { key: 'c053ea8b865d0e29763aed2e4939cc9c9e374c15', class: "end-slot-wrapper" }, index.h("slot", { key: '930aa641833b0df54b9ea10368fc2f46d5f491f6', name: "end" }))), shouldRenderHighlight && index.h("div", { key: '8d12597d15f5f429d80e8272ea99e64ed924e482', class: "textarea-highlight" })), this.renderBottomContent()));
|
|
497
490
|
}
|
|
498
491
|
get el() { return index.getElement(this); }
|
|
499
492
|
static get watchers() { return {
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
|
|
6
6
|
var index = require('./index-D6Wc6v08.js');
|
|
7
7
|
var helpers = require('./helpers-DrTqNghc.js');
|
|
8
|
+
var validity = require('./validity-BpS37YFM.js');
|
|
8
9
|
var haptic = require('./haptic-ClPPQ_PS.js');
|
|
9
10
|
var ionicGlobal = require('./ionic-global-HMVqOFGO.js');
|
|
10
11
|
var dir = require('./dir-Cn0z1rJH.js');
|
|
@@ -31,6 +32,10 @@ const Toggle = class {
|
|
|
31
32
|
this.inheritedAttributes = {};
|
|
32
33
|
this.didLoad = false;
|
|
33
34
|
this.activated = false;
|
|
35
|
+
/**
|
|
36
|
+
* Track validation state for proper aria-live announcements.
|
|
37
|
+
*/
|
|
38
|
+
this.isInvalid = false;
|
|
34
39
|
/**
|
|
35
40
|
* The name of the control, which is submitted with the form data.
|
|
36
41
|
*/
|
|
@@ -138,22 +143,58 @@ const Toggle = class {
|
|
|
138
143
|
const { checked, value } = this;
|
|
139
144
|
const isNowChecked = !checked;
|
|
140
145
|
this.checked = isNowChecked;
|
|
141
|
-
this.setFocus();
|
|
142
146
|
this.ionChange.emit({
|
|
143
147
|
checked: isNowChecked,
|
|
144
148
|
value,
|
|
145
149
|
});
|
|
146
150
|
}
|
|
147
151
|
async connectedCallback() {
|
|
152
|
+
const { didLoad, el } = this;
|
|
148
153
|
/**
|
|
149
154
|
* If we have not yet rendered
|
|
150
155
|
* ion-toggle, then toggleTrack is not defined.
|
|
151
156
|
* But if we are moving ion-toggle via appendChild,
|
|
152
157
|
* then toggleTrack will be defined.
|
|
153
158
|
*/
|
|
154
|
-
if (
|
|
159
|
+
if (didLoad) {
|
|
155
160
|
this.setupGesture();
|
|
156
161
|
}
|
|
162
|
+
// Watch for class changes to update validation state.
|
|
163
|
+
if (typeof MutationObserver !== 'undefined') {
|
|
164
|
+
this.validationObserver = new MutationObserver(() => {
|
|
165
|
+
const newIsInvalid = validity.checkInvalidState(el);
|
|
166
|
+
if (this.isInvalid !== newIsInvalid) {
|
|
167
|
+
this.isInvalid = newIsInvalid;
|
|
168
|
+
/**
|
|
169
|
+
* Screen readers tend to announce changes
|
|
170
|
+
* to `aria-describedby` when the attribute
|
|
171
|
+
* is changed during a blur event for a
|
|
172
|
+
* native form control.
|
|
173
|
+
* However, the announcement can be spotty
|
|
174
|
+
* when using a non-native form control
|
|
175
|
+
* and `forceUpdate()`.
|
|
176
|
+
* This is due to `forceUpdate()` internally
|
|
177
|
+
* rescheduling the DOM update to a lower
|
|
178
|
+
* priority queue regardless if it's called
|
|
179
|
+
* inside a Promise or not, thus causing
|
|
180
|
+
* the screen reader to potentially miss the
|
|
181
|
+
* change.
|
|
182
|
+
* By using a State variable inside a Promise,
|
|
183
|
+
* it guarantees a re-render immediately at
|
|
184
|
+
* a higher priority.
|
|
185
|
+
*/
|
|
186
|
+
Promise.resolve().then(() => {
|
|
187
|
+
this.hintTextId = this.getHintTextId();
|
|
188
|
+
});
|
|
189
|
+
}
|
|
190
|
+
});
|
|
191
|
+
this.validationObserver.observe(el, {
|
|
192
|
+
attributes: true,
|
|
193
|
+
attributeFilter: ['class'],
|
|
194
|
+
});
|
|
195
|
+
}
|
|
196
|
+
// Always set initial state
|
|
197
|
+
this.isInvalid = validity.checkInvalidState(el);
|
|
157
198
|
}
|
|
158
199
|
componentDidLoad() {
|
|
159
200
|
this.setupGesture();
|
|
@@ -164,9 +205,15 @@ const Toggle = class {
|
|
|
164
205
|
this.gesture.destroy();
|
|
165
206
|
this.gesture = undefined;
|
|
166
207
|
}
|
|
208
|
+
// Clean up validation observer to prevent memory leaks.
|
|
209
|
+
if (this.validationObserver) {
|
|
210
|
+
this.validationObserver.disconnect();
|
|
211
|
+
this.validationObserver = undefined;
|
|
212
|
+
}
|
|
167
213
|
}
|
|
168
214
|
componentWillLoad() {
|
|
169
215
|
this.inheritedAttributes = Object.assign({}, helpers.inheritAriaAttributes(this.el));
|
|
216
|
+
this.hintTextId = this.getHintTextId();
|
|
170
217
|
}
|
|
171
218
|
onStart() {
|
|
172
219
|
this.activated = true;
|
|
@@ -189,9 +236,7 @@ const Toggle = class {
|
|
|
189
236
|
return this.value || '';
|
|
190
237
|
}
|
|
191
238
|
setFocus() {
|
|
192
|
-
|
|
193
|
-
this.focusEl.focus();
|
|
194
|
-
}
|
|
239
|
+
this.el.focus();
|
|
195
240
|
}
|
|
196
241
|
renderOnOffSwitchLabels(mode, checked) {
|
|
197
242
|
const icon = this.getSwitchLabelIcon(mode, checked);
|
|
@@ -209,9 +254,9 @@ const Toggle = class {
|
|
|
209
254
|
get hasLabel() {
|
|
210
255
|
return this.el.textContent !== '';
|
|
211
256
|
}
|
|
212
|
-
|
|
213
|
-
const {
|
|
214
|
-
if (
|
|
257
|
+
getHintTextId() {
|
|
258
|
+
const { helperText, errorText, helperTextId, errorTextId, isInvalid } = this;
|
|
259
|
+
if (isInvalid && errorText) {
|
|
215
260
|
return errorTextId;
|
|
216
261
|
}
|
|
217
262
|
if (helperText) {
|
|
@@ -224,7 +269,7 @@ const Toggle = class {
|
|
|
224
269
|
* This element should only be rendered if hint text is set.
|
|
225
270
|
*/
|
|
226
271
|
renderHintText() {
|
|
227
|
-
const { helperText, errorText, helperTextId, errorTextId } = this;
|
|
272
|
+
const { helperText, errorText, helperTextId, errorTextId, isInvalid } = this;
|
|
228
273
|
/**
|
|
229
274
|
* undefined and empty string values should
|
|
230
275
|
* be treated as not having helper/error text.
|
|
@@ -233,15 +278,15 @@ const Toggle = class {
|
|
|
233
278
|
if (!hasHintText) {
|
|
234
279
|
return;
|
|
235
280
|
}
|
|
236
|
-
return (index.h("div", { class: "toggle-bottom" }, index.h("div", { id: helperTextId, class: "helper-text", part: "supporting-text helper-text" }, helperText), index.h("div", { id: errorTextId, class: "error-text", part: "supporting-text error-text" }, errorText)));
|
|
281
|
+
return (index.h("div", { class: "toggle-bottom" }, index.h("div", { id: helperTextId, class: "helper-text", part: "supporting-text helper-text", "aria-live": "polite" }, !isInvalid ? helperText : null), index.h("div", { id: errorTextId, class: "error-text", part: "supporting-text error-text", role: "alert" }, isInvalid ? errorText : null)));
|
|
237
282
|
}
|
|
238
283
|
render() {
|
|
239
|
-
const { activated, alignment, checked, color, disabled, el,
|
|
284
|
+
const { activated, alignment, checked, color, disabled, el, hasLabel, inheritedAttributes, inputId, inputLabelId, justify, labelPlacement, name, required, } = this;
|
|
240
285
|
const mode = ionicGlobal.getIonMode(this);
|
|
241
286
|
const value = this.getValue();
|
|
242
287
|
const rtl = dir.isRTL(el) ? 'rtl' : 'ltr';
|
|
243
288
|
helpers.renderHiddenInput(true, el, name, checked ? value : '', disabled);
|
|
244
|
-
return (index.h(index.Host, { key: '
|
|
289
|
+
return (index.h(index.Host, { key: 'f569148edd89ee041a4719ffc4733c16b05229bd', role: "switch", "aria-checked": `${checked}`, "aria-describedby": this.hintTextId, "aria-invalid": this.isInvalid ? 'true' : undefined, onClick: this.onClick, "aria-labelledby": hasLabel ? inputLabelId : null, "aria-label": inheritedAttributes['aria-label'] || null, "aria-disabled": disabled ? 'true' : null, "aria-required": required ? 'true' : undefined, tabindex: disabled ? undefined : 0, onKeyDown: this.onKeyDown, onFocus: this.onFocus, onBlur: this.onBlur, class: theme.createColorClasses(color, {
|
|
245
290
|
[mode]: true,
|
|
246
291
|
'in-item': theme.hostContext('ion-item', el),
|
|
247
292
|
'toggle-activated': activated,
|
|
@@ -251,10 +296,10 @@ const Toggle = class {
|
|
|
251
296
|
[`toggle-alignment-${alignment}`]: alignment !== undefined,
|
|
252
297
|
[`toggle-label-placement-${labelPlacement}`]: true,
|
|
253
298
|
[`toggle-${rtl}`]: true,
|
|
254
|
-
}) }, index.h("label", { key: '
|
|
299
|
+
}) }, index.h("label", { key: '3027f2ac4be6de422a14486d847fbee77f615db1', class: "toggle-wrapper", htmlFor: inputId }, index.h("input", Object.assign({ key: '4b0304c9e879e432b80184b4e5de37d55c11b436', type: "checkbox", role: "switch", "aria-checked": `${checked}`, checked: checked, disabled: disabled, id: inputId, required: required }, inheritedAttributes)), index.h("div", { key: '8ef265ec942e7f01ff31cbb202ed146c6bf94e02', class: {
|
|
255
300
|
'label-text-wrapper': true,
|
|
256
301
|
'label-text-wrapper-hidden': !hasLabel,
|
|
257
|
-
}, part: "label", id: inputLabelId, onClick: this.onDivLabelClick }, index.h("slot", { key: '
|
|
302
|
+
}, part: "label", id: inputLabelId, onClick: this.onDivLabelClick }, index.h("slot", { key: '7b162b7dd27199cca2a4c995276a18b9f8e44aaf' }), this.renderHintText()), index.h("div", { key: 'd13c34bd42fca01cc73ddb4ea7e471b33a282a3e', class: "native-wrapper" }, this.renderToggleControl()))));
|
|
258
303
|
}
|
|
259
304
|
get el() { return index.getElement(this); }
|
|
260
305
|
static get watchers() { return {
|