@ionic/core 8.7.4-dev.11755800369.16c1f61b → 8.7.4-nightly.20250821
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-input.js +5 -51
- package/components/ion-textarea.js +4 -50
- package/dist/cjs/ion-input.cjs.entry.js +5 -50
- package/dist/cjs/ion-textarea.cjs.entry.js +4 -49
- package/dist/cjs/ionic.cjs.js +1 -1
- package/dist/cjs/loader.cjs.js +1 -1
- package/dist/collection/components/input/input.js +6 -52
- package/dist/collection/components/textarea/textarea.js +5 -51
- package/dist/docs.json +1 -1
- package/dist/esm/ion-input.entry.js +5 -50
- package/dist/esm/ion-textarea.entry.js +4 -49
- package/dist/esm/ionic.js +1 -1
- package/dist/esm/loader.js +1 -1
- package/dist/ionic/ionic.esm.js +1 -1
- package/dist/ionic/p-1488b7cc.entry.js +4 -0
- package/dist/ionic/p-c5210d3e.entry.js +4 -0
- package/dist/types/components/input/input.d.ts +0 -9
- package/dist/types/components/textarea/textarea.d.ts +0 -9
- package/hydrate/index.js +9 -69
- package/hydrate/index.mjs +9 -69
- package/package.json +1 -1
- package/dist/ionic/p-08493d32.entry.js +0 -4
- package/dist/ionic/p-a30b23cf.entry.js +0 -4
package/components/ion-input.js
CHANGED
|
@@ -43,10 +43,6 @@ const Input = /*@__PURE__*/ proxyCustomElement(class Input extends HTMLElement {
|
|
|
43
43
|
* is applied in both cases.
|
|
44
44
|
*/
|
|
45
45
|
this.hasFocus = false;
|
|
46
|
-
/**
|
|
47
|
-
* Track validation state for proper aria-live announcements
|
|
48
|
-
*/
|
|
49
|
-
this.isInvalid = false;
|
|
50
46
|
/**
|
|
51
47
|
* Indicates whether and how the text value should be automatically capitalized as it is entered/edited by the user.
|
|
52
48
|
* Available options: `"off"`, `"none"`, `"on"`, `"sentences"`, `"words"`, `"characters"`.
|
|
@@ -132,19 +128,6 @@ const Input = /*@__PURE__*/ proxyCustomElement(class Input extends HTMLElement {
|
|
|
132
128
|
}
|
|
133
129
|
this.didInputClearOnEdit = false;
|
|
134
130
|
this.ionBlur.emit(ev);
|
|
135
|
-
/**
|
|
136
|
-
* Check validation state after blur to handle framework-managed classes.
|
|
137
|
-
* Frameworks like Angular update classes asynchronously, often using
|
|
138
|
-
* requestAnimationFrame or promises. Using setTimeout ensures we check
|
|
139
|
-
* after all microtasks and animation frames have completed.
|
|
140
|
-
*/
|
|
141
|
-
setTimeout(() => {
|
|
142
|
-
const newIsInvalid = this.checkValidationState();
|
|
143
|
-
if (this.isInvalid !== newIsInvalid) {
|
|
144
|
-
this.isInvalid = newIsInvalid;
|
|
145
|
-
forceUpdate(this);
|
|
146
|
-
}
|
|
147
|
-
}, 100);
|
|
148
131
|
};
|
|
149
132
|
this.onFocus = (ev) => {
|
|
150
133
|
this.hasFocus = true;
|
|
@@ -244,33 +227,10 @@ const Input = /*@__PURE__*/ proxyCustomElement(class Input extends HTMLElement {
|
|
|
244
227
|
componentWillLoad() {
|
|
245
228
|
this.inheritedAttributes = Object.assign(Object.assign({}, inheritAriaAttributes(this.el)), inheritAttributes(this.el, ['tabindex', 'title', 'data-form-type', 'dir']));
|
|
246
229
|
}
|
|
247
|
-
/**
|
|
248
|
-
* Checks if the input is in an invalid state based on validation classes
|
|
249
|
-
*/
|
|
250
|
-
checkValidationState() {
|
|
251
|
-
return this.el.classList.contains('ion-touched') && this.el.classList.contains('ion-invalid');
|
|
252
|
-
}
|
|
253
230
|
connectedCallback() {
|
|
254
231
|
const { el } = this;
|
|
255
232
|
this.slotMutationController = createSlotMutationController(el, ['label', 'start', 'end'], () => forceUpdate(this));
|
|
256
233
|
this.notchController = createNotchController(el, () => this.notchSpacerEl, () => this.labelSlot);
|
|
257
|
-
// Watch for class changes to update validation state
|
|
258
|
-
if (Build.isBrowser && typeof MutationObserver !== 'undefined') {
|
|
259
|
-
this.validationObserver = new MutationObserver(() => {
|
|
260
|
-
const newIsInvalid = this.checkValidationState();
|
|
261
|
-
if (this.isInvalid !== newIsInvalid) {
|
|
262
|
-
this.isInvalid = newIsInvalid;
|
|
263
|
-
// Force a re-render to update aria-describedby immediately
|
|
264
|
-
forceUpdate(this);
|
|
265
|
-
}
|
|
266
|
-
});
|
|
267
|
-
this.validationObserver.observe(el, {
|
|
268
|
-
attributes: true,
|
|
269
|
-
attributeFilter: ['class'],
|
|
270
|
-
});
|
|
271
|
-
}
|
|
272
|
-
// Always set initial state
|
|
273
|
-
this.isInvalid = this.checkValidationState();
|
|
274
234
|
this.debounceChanged();
|
|
275
235
|
if (Build.isBrowser) {
|
|
276
236
|
document.dispatchEvent(new CustomEvent('ionInputDidLoad', {
|
|
@@ -307,11 +267,6 @@ const Input = /*@__PURE__*/ proxyCustomElement(class Input extends HTMLElement {
|
|
|
307
267
|
this.notchController.destroy();
|
|
308
268
|
this.notchController = undefined;
|
|
309
269
|
}
|
|
310
|
-
// Clean up validation observer to prevent memory leaks
|
|
311
|
-
if (this.validationObserver) {
|
|
312
|
-
this.validationObserver.disconnect();
|
|
313
|
-
this.validationObserver = undefined;
|
|
314
|
-
}
|
|
315
270
|
}
|
|
316
271
|
/**
|
|
317
272
|
* Sets focus on the native `input` in `ion-input`. Use this method instead of the global
|
|
@@ -420,8 +375,8 @@ const Input = /*@__PURE__*/ proxyCustomElement(class Input extends HTMLElement {
|
|
|
420
375
|
];
|
|
421
376
|
}
|
|
422
377
|
getHintTextID() {
|
|
423
|
-
const {
|
|
424
|
-
if (
|
|
378
|
+
const { el, helperText, errorText, helperTextId, errorTextId } = this;
|
|
379
|
+
if (el.classList.contains('ion-touched') && el.classList.contains('ion-invalid') && errorText) {
|
|
425
380
|
return errorTextId;
|
|
426
381
|
}
|
|
427
382
|
if (helperText) {
|
|
@@ -534,7 +489,7 @@ const Input = /*@__PURE__*/ proxyCustomElement(class Input extends HTMLElement {
|
|
|
534
489
|
* TODO(FW-5592): Remove hasStartEndSlots condition
|
|
535
490
|
*/
|
|
536
491
|
const labelShouldFloat = labelPlacement === 'stacked' || (labelPlacement === 'floating' && (hasValue || hasFocus || hasStartEndSlots));
|
|
537
|
-
return (h(Host, { key: '
|
|
492
|
+
return (h(Host, { key: '41b2526627e7d2773a80f011b123284203a71ca0', class: createColorClasses(this.color, {
|
|
538
493
|
[mode]: true,
|
|
539
494
|
'has-value': hasValue,
|
|
540
495
|
'has-focus': hasFocus,
|
|
@@ -545,14 +500,14 @@ const Input = /*@__PURE__*/ proxyCustomElement(class Input extends HTMLElement {
|
|
|
545
500
|
'in-item': inItem,
|
|
546
501
|
'in-item-color': hostContext('ion-item.ion-color', this.el),
|
|
547
502
|
'input-disabled': disabled,
|
|
548
|
-
}) }, h("label", { key: '
|
|
503
|
+
}) }, h("label", { key: '9ab078363e32528102b441ad1791d83f86fdcbdc', class: "input-wrapper", htmlFor: inputId, onClick: this.onLabelClick }, this.renderLabelContainer(), h("div", { key: 'e34b594980ec62e4c618e827fadf7669a39ad0d8', class: "native-wrapper", onClick: this.onLabelClick }, h("slot", { key: '12dc04ead5502e9e5736240e918bf9331bf7b5d9', name: "start" }), h("input", Object.assign({ key: 'df356eb4ced23109b2c0242f36dc043aba8782d6', class: "native-input", ref: (input) => (this.nativeInput = input), id: inputId, disabled: disabled, autoCapitalize: this.autocapitalize, autoComplete: this.autocomplete, autoCorrect: this.autocorrect, autoFocus: this.autofocus, enterKeyHint: this.enterkeyhint, inputMode: this.inputmode, min: this.min, max: this.max, minLength: this.minlength, maxLength: this.maxlength, multiple: this.multiple, name: this.name, pattern: this.pattern, placeholder: this.placeholder || '', readOnly: readonly, required: this.required, spellcheck: this.spellcheck, step: this.step, type: this.type, value: value, onInput: this.onInput, onChange: this.onChange, onBlur: this.onBlur, onFocus: this.onFocus, onKeyDown: this.onKeydown, onCompositionstart: this.onCompositionStart, onCompositionend: this.onCompositionEnd, "aria-describedby": this.getHintTextID(), "aria-invalid": this.getHintTextID() === this.errorTextId }, this.inheritedAttributes)), this.clearInput && !readonly && !disabled && (h("button", { key: 'f79f68cabcd4ea99419331174a377827db0c0741', "aria-label": "reset", type: "button", class: "input-clear-icon", onPointerDown: (ev) => {
|
|
549
504
|
/**
|
|
550
505
|
* This prevents mobile browsers from
|
|
551
506
|
* blurring the input when the clear
|
|
552
507
|
* button is activated.
|
|
553
508
|
*/
|
|
554
509
|
ev.preventDefault();
|
|
555
|
-
}, onClick: this.clearTextInput }, h("ion-icon", { key: '
|
|
510
|
+
}, onClick: this.clearTextInput }, h("ion-icon", { key: '237ec07ec2e10f08818a332bb596578c2c49f770', "aria-hidden": "true", icon: clearIconData }))), h("slot", { key: '1f0a3624aa3e8dc3c307a6762230ab698768a5e5', name: "end" })), shouldRenderHighlight && h("div", { key: '8a8cbb82695a722a0010b53dd0b1f1f97534a20b', class: "input-highlight" })), this.renderBottomContent()));
|
|
556
511
|
}
|
|
557
512
|
get el() { return this; }
|
|
558
513
|
static get watchers() { return {
|
|
@@ -601,7 +556,6 @@ const Input = /*@__PURE__*/ proxyCustomElement(class Input extends HTMLElement {
|
|
|
601
556
|
"type": [1],
|
|
602
557
|
"value": [1032],
|
|
603
558
|
"hasFocus": [32],
|
|
604
|
-
"isInvalid": [32],
|
|
605
559
|
"setFocus": [64],
|
|
606
560
|
"getInputElement": [64]
|
|
607
561
|
}, [[2, "click", "onClickCapture"]], {
|
|
@@ -40,10 +40,6 @@ const Textarea = /*@__PURE__*/ proxyCustomElement(class Textarea extends HTMLEle
|
|
|
40
40
|
* is applied in both cases.
|
|
41
41
|
*/
|
|
42
42
|
this.hasFocus = false;
|
|
43
|
-
/**
|
|
44
|
-
* Track validation state for proper aria-live announcements
|
|
45
|
-
*/
|
|
46
|
-
this.isInvalid = false;
|
|
47
43
|
/**
|
|
48
44
|
* Indicates whether and how the text value should be automatically capitalized as it is entered/edited by the user.
|
|
49
45
|
* Available options: `"off"`, `"none"`, `"on"`, `"sentences"`, `"words"`, `"characters"`.
|
|
@@ -133,19 +129,6 @@ const Textarea = /*@__PURE__*/ proxyCustomElement(class Textarea extends HTMLEle
|
|
|
133
129
|
}
|
|
134
130
|
this.didTextareaClearOnEdit = false;
|
|
135
131
|
this.ionBlur.emit(ev);
|
|
136
|
-
/**
|
|
137
|
-
* Check validation state after blur to handle framework-managed classes.
|
|
138
|
-
* Frameworks like Angular update classes asynchronously, often using
|
|
139
|
-
* requestAnimationFrame or promises. Using setTimeout ensures we check
|
|
140
|
-
* after all microtasks and animation frames have completed.
|
|
141
|
-
*/
|
|
142
|
-
setTimeout(() => {
|
|
143
|
-
const newIsInvalid = this.checkValidationState();
|
|
144
|
-
if (this.isInvalid !== newIsInvalid) {
|
|
145
|
-
this.isInvalid = newIsInvalid;
|
|
146
|
-
forceUpdate(this);
|
|
147
|
-
}
|
|
148
|
-
}, 100);
|
|
149
132
|
};
|
|
150
133
|
this.onKeyDown = (ev) => {
|
|
151
134
|
this.checkClearOnEdit(ev);
|
|
@@ -203,33 +186,10 @@ const Textarea = /*@__PURE__*/ proxyCustomElement(class Textarea extends HTMLEle
|
|
|
203
186
|
this.el.click();
|
|
204
187
|
}
|
|
205
188
|
}
|
|
206
|
-
/**
|
|
207
|
-
* Checks if the textarea is in an invalid state based on validation classes
|
|
208
|
-
*/
|
|
209
|
-
checkValidationState() {
|
|
210
|
-
return this.el.classList.contains('ion-touched') && this.el.classList.contains('ion-invalid');
|
|
211
|
-
}
|
|
212
189
|
connectedCallback() {
|
|
213
190
|
const { el } = this;
|
|
214
191
|
this.slotMutationController = createSlotMutationController(el, ['label', 'start', 'end'], () => forceUpdate(this));
|
|
215
192
|
this.notchController = createNotchController(el, () => this.notchSpacerEl, () => this.labelSlot);
|
|
216
|
-
// Watch for class changes to update validation state
|
|
217
|
-
if (Build.isBrowser && typeof MutationObserver !== 'undefined') {
|
|
218
|
-
this.validationObserver = new MutationObserver(() => {
|
|
219
|
-
const newIsInvalid = this.checkValidationState();
|
|
220
|
-
if (this.isInvalid !== newIsInvalid) {
|
|
221
|
-
this.isInvalid = newIsInvalid;
|
|
222
|
-
// Force a re-render to update aria-describedby immediately
|
|
223
|
-
forceUpdate(this);
|
|
224
|
-
}
|
|
225
|
-
});
|
|
226
|
-
this.validationObserver.observe(el, {
|
|
227
|
-
attributes: true,
|
|
228
|
-
attributeFilter: ['class'],
|
|
229
|
-
});
|
|
230
|
-
}
|
|
231
|
-
// Always set initial state
|
|
232
|
-
this.isInvalid = this.checkValidationState();
|
|
233
193
|
this.debounceChanged();
|
|
234
194
|
if (Build.isBrowser) {
|
|
235
195
|
document.dispatchEvent(new CustomEvent('ionInputDidLoad', {
|
|
@@ -251,11 +211,6 @@ const Textarea = /*@__PURE__*/ proxyCustomElement(class Textarea extends HTMLEle
|
|
|
251
211
|
this.notchController.destroy();
|
|
252
212
|
this.notchController = undefined;
|
|
253
213
|
}
|
|
254
|
-
// Clean up validation observer to prevent memory leaks
|
|
255
|
-
if (this.validationObserver) {
|
|
256
|
-
this.validationObserver.disconnect();
|
|
257
|
-
this.validationObserver = undefined;
|
|
258
|
-
}
|
|
259
214
|
}
|
|
260
215
|
componentWillLoad() {
|
|
261
216
|
this.inheritedAttributes = Object.assign(Object.assign({}, inheritAriaAttributes(this.el)), inheritAttributes(this.el, ['data-form-type', 'title', 'tabindex', 'dir']));
|
|
@@ -433,8 +388,8 @@ const Textarea = /*@__PURE__*/ proxyCustomElement(class Textarea extends HTMLEle
|
|
|
433
388
|
];
|
|
434
389
|
}
|
|
435
390
|
getHintTextID() {
|
|
436
|
-
const {
|
|
437
|
-
if (
|
|
391
|
+
const { el, helperText, errorText, helperTextId, errorTextId } = this;
|
|
392
|
+
if (el.classList.contains('ion-touched') && el.classList.contains('ion-invalid') && errorText) {
|
|
438
393
|
return errorTextId;
|
|
439
394
|
}
|
|
440
395
|
if (helperText) {
|
|
@@ -493,7 +448,7 @@ const Textarea = /*@__PURE__*/ proxyCustomElement(class Textarea extends HTMLEle
|
|
|
493
448
|
* TODO(FW-5592): Remove hasStartEndSlots condition
|
|
494
449
|
*/
|
|
495
450
|
const labelShouldFloat = labelPlacement === 'stacked' || (labelPlacement === 'floating' && (hasValue || hasFocus || hasStartEndSlots));
|
|
496
|
-
return (h(Host, { key: '
|
|
451
|
+
return (h(Host, { key: 'd9f2ede0107987fc42c99e310cd2336bad5a5755', class: createColorClasses(this.color, {
|
|
497
452
|
[mode]: true,
|
|
498
453
|
'has-value': hasValue,
|
|
499
454
|
'has-focus': hasFocus,
|
|
@@ -502,7 +457,7 @@ const Textarea = /*@__PURE__*/ proxyCustomElement(class Textarea extends HTMLEle
|
|
|
502
457
|
[`textarea-shape-${shape}`]: shape !== undefined,
|
|
503
458
|
[`textarea-label-placement-${labelPlacement}`]: true,
|
|
504
459
|
'textarea-disabled': disabled,
|
|
505
|
-
}) }, h("label", { key: '
|
|
460
|
+
}) }, h("label", { key: '9de598b95237462bb3bccffaefe83afbb43554b8', class: "textarea-wrapper", htmlFor: inputId, onClick: this.onLabelClick }, this.renderLabelContainer(), h("div", { key: 'e33c426c6541d723ccc246bb404c03687726ff83', class: "textarea-wrapper-inner" }, h("div", { key: '521e11af9d54d281b0a2b1c25bcfc6f742c18296', class: "start-slot-wrapper" }, h("slot", { key: '515523f6ca3ce0e5dd08f3275c21a190fb1ca177', name: "start" })), h("div", { key: '916e01e00de8400ae00ef06bc1fb62d8be2eee08', class: "native-wrapper", ref: (el) => (this.textareaWrapper = el) }, h("textarea", Object.assign({ key: '810271e6532d90e27dab1fcb26546113c1ce9cb0', 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.getHintTextID() === this.errorTextId }, this.inheritedAttributes), value)), h("div", { key: '80aca9ea9546dca9d38efd291a6b0be384bb6978', class: "end-slot-wrapper" }, h("slot", { key: '407fab16c66a9f4a542369bfecc0d9afa0065977', name: "end" }))), shouldRenderHighlight && h("div", { key: 'f00523a6698fac8a1996e04303487bef01d10f25', class: "textarea-highlight" })), this.renderBottomContent()));
|
|
506
461
|
}
|
|
507
462
|
get el() { return this; }
|
|
508
463
|
static get watchers() { return {
|
|
@@ -544,7 +499,6 @@ const Textarea = /*@__PURE__*/ proxyCustomElement(class Textarea extends HTMLEle
|
|
|
544
499
|
"labelPlacement": [1, "label-placement"],
|
|
545
500
|
"shape": [1],
|
|
546
501
|
"hasFocus": [32],
|
|
547
|
-
"isInvalid": [32],
|
|
548
502
|
"setFocus": [64],
|
|
549
503
|
"getInputElement": [64]
|
|
550
504
|
}, [[2, "click", "onClickCapture"]], {
|
|
@@ -44,10 +44,6 @@ const Input = class {
|
|
|
44
44
|
* is applied in both cases.
|
|
45
45
|
*/
|
|
46
46
|
this.hasFocus = false;
|
|
47
|
-
/**
|
|
48
|
-
* Track validation state for proper aria-live announcements
|
|
49
|
-
*/
|
|
50
|
-
this.isInvalid = false;
|
|
51
47
|
/**
|
|
52
48
|
* Indicates whether and how the text value should be automatically capitalized as it is entered/edited by the user.
|
|
53
49
|
* Available options: `"off"`, `"none"`, `"on"`, `"sentences"`, `"words"`, `"characters"`.
|
|
@@ -133,19 +129,6 @@ const Input = class {
|
|
|
133
129
|
}
|
|
134
130
|
this.didInputClearOnEdit = false;
|
|
135
131
|
this.ionBlur.emit(ev);
|
|
136
|
-
/**
|
|
137
|
-
* Check validation state after blur to handle framework-managed classes.
|
|
138
|
-
* Frameworks like Angular update classes asynchronously, often using
|
|
139
|
-
* requestAnimationFrame or promises. Using setTimeout ensures we check
|
|
140
|
-
* after all microtasks and animation frames have completed.
|
|
141
|
-
*/
|
|
142
|
-
setTimeout(() => {
|
|
143
|
-
const newIsInvalid = this.checkValidationState();
|
|
144
|
-
if (this.isInvalid !== newIsInvalid) {
|
|
145
|
-
this.isInvalid = newIsInvalid;
|
|
146
|
-
index.forceUpdate(this);
|
|
147
|
-
}
|
|
148
|
-
}, 100);
|
|
149
132
|
};
|
|
150
133
|
this.onFocus = (ev) => {
|
|
151
134
|
this.hasFocus = true;
|
|
@@ -245,33 +228,10 @@ const Input = class {
|
|
|
245
228
|
componentWillLoad() {
|
|
246
229
|
this.inheritedAttributes = Object.assign(Object.assign({}, helpers.inheritAriaAttributes(this.el)), helpers.inheritAttributes(this.el, ['tabindex', 'title', 'data-form-type', 'dir']));
|
|
247
230
|
}
|
|
248
|
-
/**
|
|
249
|
-
* Checks if the input is in an invalid state based on validation classes
|
|
250
|
-
*/
|
|
251
|
-
checkValidationState() {
|
|
252
|
-
return this.el.classList.contains('ion-touched') && this.el.classList.contains('ion-invalid');
|
|
253
|
-
}
|
|
254
231
|
connectedCallback() {
|
|
255
232
|
const { el } = this;
|
|
256
233
|
this.slotMutationController = input_utils.createSlotMutationController(el, ['label', 'start', 'end'], () => index.forceUpdate(this));
|
|
257
234
|
this.notchController = notchController.createNotchController(el, () => this.notchSpacerEl, () => this.labelSlot);
|
|
258
|
-
// Watch for class changes to update validation state
|
|
259
|
-
if (typeof MutationObserver !== 'undefined') {
|
|
260
|
-
this.validationObserver = new MutationObserver(() => {
|
|
261
|
-
const newIsInvalid = this.checkValidationState();
|
|
262
|
-
if (this.isInvalid !== newIsInvalid) {
|
|
263
|
-
this.isInvalid = newIsInvalid;
|
|
264
|
-
// Force a re-render to update aria-describedby immediately
|
|
265
|
-
index.forceUpdate(this);
|
|
266
|
-
}
|
|
267
|
-
});
|
|
268
|
-
this.validationObserver.observe(el, {
|
|
269
|
-
attributes: true,
|
|
270
|
-
attributeFilter: ['class'],
|
|
271
|
-
});
|
|
272
|
-
}
|
|
273
|
-
// Always set initial state
|
|
274
|
-
this.isInvalid = this.checkValidationState();
|
|
275
235
|
this.debounceChanged();
|
|
276
236
|
{
|
|
277
237
|
document.dispatchEvent(new CustomEvent('ionInputDidLoad', {
|
|
@@ -308,11 +268,6 @@ const Input = class {
|
|
|
308
268
|
this.notchController.destroy();
|
|
309
269
|
this.notchController = undefined;
|
|
310
270
|
}
|
|
311
|
-
// Clean up validation observer to prevent memory leaks
|
|
312
|
-
if (this.validationObserver) {
|
|
313
|
-
this.validationObserver.disconnect();
|
|
314
|
-
this.validationObserver = undefined;
|
|
315
|
-
}
|
|
316
271
|
}
|
|
317
272
|
/**
|
|
318
273
|
* Sets focus on the native `input` in `ion-input`. Use this method instead of the global
|
|
@@ -421,8 +376,8 @@ const Input = class {
|
|
|
421
376
|
];
|
|
422
377
|
}
|
|
423
378
|
getHintTextID() {
|
|
424
|
-
const {
|
|
425
|
-
if (
|
|
379
|
+
const { el, helperText, errorText, helperTextId, errorTextId } = this;
|
|
380
|
+
if (el.classList.contains('ion-touched') && el.classList.contains('ion-invalid') && errorText) {
|
|
426
381
|
return errorTextId;
|
|
427
382
|
}
|
|
428
383
|
if (helperText) {
|
|
@@ -535,7 +490,7 @@ const Input = class {
|
|
|
535
490
|
* TODO(FW-5592): Remove hasStartEndSlots condition
|
|
536
491
|
*/
|
|
537
492
|
const labelShouldFloat = labelPlacement === 'stacked' || (labelPlacement === 'floating' && (hasValue || hasFocus || hasStartEndSlots));
|
|
538
|
-
return (index.h(index.Host, { key: '
|
|
493
|
+
return (index.h(index.Host, { key: '41b2526627e7d2773a80f011b123284203a71ca0', class: theme.createColorClasses(this.color, {
|
|
539
494
|
[mode]: true,
|
|
540
495
|
'has-value': hasValue,
|
|
541
496
|
'has-focus': hasFocus,
|
|
@@ -546,14 +501,14 @@ const Input = class {
|
|
|
546
501
|
'in-item': inItem,
|
|
547
502
|
'in-item-color': theme.hostContext('ion-item.ion-color', this.el),
|
|
548
503
|
'input-disabled': disabled,
|
|
549
|
-
}) }, index.h("label", { key: '
|
|
504
|
+
}) }, index.h("label", { key: '9ab078363e32528102b441ad1791d83f86fdcbdc', class: "input-wrapper", htmlFor: inputId, onClick: this.onLabelClick }, this.renderLabelContainer(), index.h("div", { key: 'e34b594980ec62e4c618e827fadf7669a39ad0d8', class: "native-wrapper", onClick: this.onLabelClick }, index.h("slot", { key: '12dc04ead5502e9e5736240e918bf9331bf7b5d9', name: "start" }), index.h("input", Object.assign({ key: 'df356eb4ced23109b2c0242f36dc043aba8782d6', class: "native-input", ref: (input) => (this.nativeInput = input), id: inputId, disabled: disabled, autoCapitalize: this.autocapitalize, autoComplete: this.autocomplete, autoCorrect: this.autocorrect, autoFocus: this.autofocus, enterKeyHint: this.enterkeyhint, inputMode: this.inputmode, min: this.min, max: this.max, minLength: this.minlength, maxLength: this.maxlength, multiple: this.multiple, name: this.name, pattern: this.pattern, placeholder: this.placeholder || '', readOnly: readonly, required: this.required, spellcheck: this.spellcheck, step: this.step, type: this.type, value: value, onInput: this.onInput, onChange: this.onChange, onBlur: this.onBlur, onFocus: this.onFocus, onKeyDown: this.onKeydown, onCompositionstart: this.onCompositionStart, onCompositionend: this.onCompositionEnd, "aria-describedby": this.getHintTextID(), "aria-invalid": this.getHintTextID() === this.errorTextId }, this.inheritedAttributes)), this.clearInput && !readonly && !disabled && (index.h("button", { key: 'f79f68cabcd4ea99419331174a377827db0c0741', "aria-label": "reset", type: "button", class: "input-clear-icon", onPointerDown: (ev) => {
|
|
550
505
|
/**
|
|
551
506
|
* This prevents mobile browsers from
|
|
552
507
|
* blurring the input when the clear
|
|
553
508
|
* button is activated.
|
|
554
509
|
*/
|
|
555
510
|
ev.preventDefault();
|
|
556
|
-
}, onClick: this.clearTextInput }, index.h("ion-icon", { key: '
|
|
511
|
+
}, onClick: this.clearTextInput }, index.h("ion-icon", { key: '237ec07ec2e10f08818a332bb596578c2c49f770', "aria-hidden": "true", icon: clearIconData }))), index.h("slot", { key: '1f0a3624aa3e8dc3c307a6762230ab698768a5e5', name: "end" })), shouldRenderHighlight && index.h("div", { key: '8a8cbb82695a722a0010b53dd0b1f1f97534a20b', class: "input-highlight" })), this.renderBottomContent()));
|
|
557
512
|
}
|
|
558
513
|
get el() { return index.getElement(this); }
|
|
559
514
|
static get watchers() { return {
|
|
@@ -42,10 +42,6 @@ const Textarea = class {
|
|
|
42
42
|
* is applied in both cases.
|
|
43
43
|
*/
|
|
44
44
|
this.hasFocus = false;
|
|
45
|
-
/**
|
|
46
|
-
* Track validation state for proper aria-live announcements
|
|
47
|
-
*/
|
|
48
|
-
this.isInvalid = false;
|
|
49
45
|
/**
|
|
50
46
|
* Indicates whether and how the text value should be automatically capitalized as it is entered/edited by the user.
|
|
51
47
|
* Available options: `"off"`, `"none"`, `"on"`, `"sentences"`, `"words"`, `"characters"`.
|
|
@@ -135,19 +131,6 @@ const Textarea = class {
|
|
|
135
131
|
}
|
|
136
132
|
this.didTextareaClearOnEdit = false;
|
|
137
133
|
this.ionBlur.emit(ev);
|
|
138
|
-
/**
|
|
139
|
-
* Check validation state after blur to handle framework-managed classes.
|
|
140
|
-
* Frameworks like Angular update classes asynchronously, often using
|
|
141
|
-
* requestAnimationFrame or promises. Using setTimeout ensures we check
|
|
142
|
-
* after all microtasks and animation frames have completed.
|
|
143
|
-
*/
|
|
144
|
-
setTimeout(() => {
|
|
145
|
-
const newIsInvalid = this.checkValidationState();
|
|
146
|
-
if (this.isInvalid !== newIsInvalid) {
|
|
147
|
-
this.isInvalid = newIsInvalid;
|
|
148
|
-
index.forceUpdate(this);
|
|
149
|
-
}
|
|
150
|
-
}, 100);
|
|
151
134
|
};
|
|
152
135
|
this.onKeyDown = (ev) => {
|
|
153
136
|
this.checkClearOnEdit(ev);
|
|
@@ -205,33 +188,10 @@ const Textarea = class {
|
|
|
205
188
|
this.el.click();
|
|
206
189
|
}
|
|
207
190
|
}
|
|
208
|
-
/**
|
|
209
|
-
* Checks if the textarea is in an invalid state based on validation classes
|
|
210
|
-
*/
|
|
211
|
-
checkValidationState() {
|
|
212
|
-
return this.el.classList.contains('ion-touched') && this.el.classList.contains('ion-invalid');
|
|
213
|
-
}
|
|
214
191
|
connectedCallback() {
|
|
215
192
|
const { el } = this;
|
|
216
193
|
this.slotMutationController = input_utils.createSlotMutationController(el, ['label', 'start', 'end'], () => index.forceUpdate(this));
|
|
217
194
|
this.notchController = notchController.createNotchController(el, () => this.notchSpacerEl, () => this.labelSlot);
|
|
218
|
-
// Watch for class changes to update validation state
|
|
219
|
-
if (typeof MutationObserver !== 'undefined') {
|
|
220
|
-
this.validationObserver = new MutationObserver(() => {
|
|
221
|
-
const newIsInvalid = this.checkValidationState();
|
|
222
|
-
if (this.isInvalid !== newIsInvalid) {
|
|
223
|
-
this.isInvalid = newIsInvalid;
|
|
224
|
-
// Force a re-render to update aria-describedby immediately
|
|
225
|
-
index.forceUpdate(this);
|
|
226
|
-
}
|
|
227
|
-
});
|
|
228
|
-
this.validationObserver.observe(el, {
|
|
229
|
-
attributes: true,
|
|
230
|
-
attributeFilter: ['class'],
|
|
231
|
-
});
|
|
232
|
-
}
|
|
233
|
-
// Always set initial state
|
|
234
|
-
this.isInvalid = this.checkValidationState();
|
|
235
195
|
this.debounceChanged();
|
|
236
196
|
{
|
|
237
197
|
document.dispatchEvent(new CustomEvent('ionInputDidLoad', {
|
|
@@ -253,11 +213,6 @@ const Textarea = class {
|
|
|
253
213
|
this.notchController.destroy();
|
|
254
214
|
this.notchController = undefined;
|
|
255
215
|
}
|
|
256
|
-
// Clean up validation observer to prevent memory leaks
|
|
257
|
-
if (this.validationObserver) {
|
|
258
|
-
this.validationObserver.disconnect();
|
|
259
|
-
this.validationObserver = undefined;
|
|
260
|
-
}
|
|
261
216
|
}
|
|
262
217
|
componentWillLoad() {
|
|
263
218
|
this.inheritedAttributes = Object.assign(Object.assign({}, helpers.inheritAriaAttributes(this.el)), helpers.inheritAttributes(this.el, ['data-form-type', 'title', 'tabindex', 'dir']));
|
|
@@ -435,8 +390,8 @@ const Textarea = class {
|
|
|
435
390
|
];
|
|
436
391
|
}
|
|
437
392
|
getHintTextID() {
|
|
438
|
-
const {
|
|
439
|
-
if (
|
|
393
|
+
const { el, helperText, errorText, helperTextId, errorTextId } = this;
|
|
394
|
+
if (el.classList.contains('ion-touched') && el.classList.contains('ion-invalid') && errorText) {
|
|
440
395
|
return errorTextId;
|
|
441
396
|
}
|
|
442
397
|
if (helperText) {
|
|
@@ -495,7 +450,7 @@ const Textarea = class {
|
|
|
495
450
|
* TODO(FW-5592): Remove hasStartEndSlots condition
|
|
496
451
|
*/
|
|
497
452
|
const labelShouldFloat = labelPlacement === 'stacked' || (labelPlacement === 'floating' && (hasValue || hasFocus || hasStartEndSlots));
|
|
498
|
-
return (index.h(index.Host, { key: '
|
|
453
|
+
return (index.h(index.Host, { key: 'd9f2ede0107987fc42c99e310cd2336bad5a5755', class: theme.createColorClasses(this.color, {
|
|
499
454
|
[mode]: true,
|
|
500
455
|
'has-value': hasValue,
|
|
501
456
|
'has-focus': hasFocus,
|
|
@@ -504,7 +459,7 @@ const Textarea = class {
|
|
|
504
459
|
[`textarea-shape-${shape}`]: shape !== undefined,
|
|
505
460
|
[`textarea-label-placement-${labelPlacement}`]: true,
|
|
506
461
|
'textarea-disabled': disabled,
|
|
507
|
-
}) }, index.h("label", { key: '
|
|
462
|
+
}) }, index.h("label", { key: '9de598b95237462bb3bccffaefe83afbb43554b8', class: "textarea-wrapper", htmlFor: inputId, onClick: this.onLabelClick }, this.renderLabelContainer(), index.h("div", { key: 'e33c426c6541d723ccc246bb404c03687726ff83', class: "textarea-wrapper-inner" }, index.h("div", { key: '521e11af9d54d281b0a2b1c25bcfc6f742c18296', class: "start-slot-wrapper" }, index.h("slot", { key: '515523f6ca3ce0e5dd08f3275c21a190fb1ca177', name: "start" })), index.h("div", { key: '916e01e00de8400ae00ef06bc1fb62d8be2eee08', class: "native-wrapper", ref: (el) => (this.textareaWrapper = el) }, index.h("textarea", Object.assign({ key: '810271e6532d90e27dab1fcb26546113c1ce9cb0', 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.getHintTextID() === this.errorTextId }, this.inheritedAttributes), value)), index.h("div", { key: '80aca9ea9546dca9d38efd291a6b0be384bb6978', class: "end-slot-wrapper" }, index.h("slot", { key: '407fab16c66a9f4a542369bfecc0d9afa0065977', name: "end" }))), shouldRenderHighlight && index.h("div", { key: 'f00523a6698fac8a1996e04303487bef01d10f25', class: "textarea-highlight" })), this.renderBottomContent()));
|
|
508
463
|
}
|
|
509
464
|
get el() { return index.getElement(this); }
|
|
510
465
|
static get watchers() { return {
|