@ionic/core 8.7.16-dev.11767028735.16932cea → 8.7.16-dev.11767032989.1ae720d0

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.
@@ -28,6 +28,7 @@ const Input = /*@__PURE__*/ proxyCustomElement(class Input extends HTMLElement {
28
28
  this.inputId = `ion-input-${inputIds++}`;
29
29
  this.helperTextId = `${this.inputId}-helper-text`;
30
30
  this.errorTextId = `${this.inputId}-error-text`;
31
+ this.labelTextId = `${this.inputId}-label`;
31
32
  this.inheritedAttributes = {};
32
33
  this.isComposing = false;
33
34
  /**
@@ -236,7 +237,11 @@ const Input = /*@__PURE__*/ proxyCustomElement(class Input extends HTMLElement {
236
237
  }
237
238
  connectedCallback() {
238
239
  const { el } = this;
239
- this.slotMutationController = createSlotMutationController(el, ['label', 'start', 'end'], () => forceUpdate(this));
240
+ this.slotMutationController = createSlotMutationController(el, ['label', 'start', 'end'], () => {
241
+ this.setSlottedLabelId();
242
+ forceUpdate(this);
243
+ });
244
+ this.setSlottedLabelId();
240
245
  this.notchController = createNotchController(el, () => this.notchSpacerEl, () => this.labelSlot);
241
246
  // Watch for class changes to update validation state
242
247
  if (Build.isBrowser && typeof MutationObserver !== 'undefined') {
@@ -439,11 +444,11 @@ const Input = /*@__PURE__*/ proxyCustomElement(class Input extends HTMLElement {
439
444
  return (h("div", { class: "input-bottom" }, this.renderHintText(), this.renderCounter()));
440
445
  }
441
446
  renderLabel() {
442
- const { label } = this;
447
+ const { label, labelTextId } = this;
443
448
  return (h("div", { class: {
444
449
  'label-text-wrapper': true,
445
450
  'label-text-wrapper-hidden': !this.hasLabel,
446
- } }, label === undefined ? h("slot", { name: "label" }) : h("div", { class: "label-text" }, label)));
451
+ }, "aria-hidden": this.hasLabel ? 'true' : null }, label === undefined ? (h("slot", { name: "label" })) : (h("div", { class: "label-text", id: labelTextId }, label))));
447
452
  }
448
453
  /**
449
454
  * Gets any content passed into the `label` slot,
@@ -452,6 +457,30 @@ const Input = /*@__PURE__*/ proxyCustomElement(class Input extends HTMLElement {
452
457
  get labelSlot() {
453
458
  return this.el.querySelector('[slot="label"]');
454
459
  }
460
+ /**
461
+ * Ensures the slotted label element has an ID for aria-labelledby.
462
+ * If no ID exists, we assign one using our generated labelTextId.
463
+ */
464
+ setSlottedLabelId() {
465
+ const slottedLabel = this.labelSlot;
466
+ if (slottedLabel && !slottedLabel.id) {
467
+ slottedLabel.id = this.labelTextId;
468
+ }
469
+ }
470
+ /**
471
+ * Returns the ID to use for aria-labelledby on the native input,
472
+ * or undefined if aria-label is explicitly set (to avoid conflicts).
473
+ */
474
+ getLabelledById() {
475
+ var _a;
476
+ if (this.inheritedAttributes['aria-label']) {
477
+ return undefined;
478
+ }
479
+ if (this.label !== undefined) {
480
+ return this.labelTextId;
481
+ }
482
+ return ((_a = this.labelSlot) === null || _a === void 0 ? void 0 : _a.id) || undefined;
483
+ }
455
484
  /**
456
485
  * Returns `true` if label content is provided
457
486
  * either by a prop or a content. If you want
@@ -518,7 +547,7 @@ const Input = /*@__PURE__*/ proxyCustomElement(class Input extends HTMLElement {
518
547
  * TODO(FW-5592): Remove hasStartEndSlots condition
519
548
  */
520
549
  const labelShouldFloat = labelPlacement === 'stacked' || (labelPlacement === 'floating' && (hasValue || hasFocus || hasStartEndSlots));
521
- return (h(Host, { key: '97b5308021064d9e7434ef2d3d96f27045c1b0c4', class: createColorClasses(this.color, {
550
+ return (h(Host, { key: '9ba9cf425b573d2ca9ac34455a0e6b8474c4de6d', class: createColorClasses(this.color, {
522
551
  [mode]: true,
523
552
  'has-value': hasValue,
524
553
  'has-focus': hasFocus,
@@ -529,14 +558,14 @@ const Input = /*@__PURE__*/ proxyCustomElement(class Input extends HTMLElement {
529
558
  'in-item': inItem,
530
559
  'in-item-color': hostContext('ion-item.ion-color', this.el),
531
560
  'input-disabled': disabled,
532
- }) }, h("label", { key: '353f68726ce180299bd9adc81e5ff7d26a48f54f', class: "input-wrapper", htmlFor: inputId, onClick: this.onLabelClick }, this.renderLabelContainer(), h("div", { key: '2034b4bad04fc157f3298a1805819216b6f439d0', class: "native-wrapper", onClick: this.onLabelClick }, h("slot", { key: '96bb5e30176b2bd76dfb75bfbf6c1c3d4403f4bb', name: "start" }), 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 && (h("button", { key: '95f3df17b7691d9a2e7dcd4a51f16a94aa3ca36f', "aria-label": "reset", type: "button", class: "input-clear-icon", onPointerDown: (ev) => {
561
+ }) }, h("label", { key: '74b989d0aa5ab38f29f952519868f05119df6005', class: "input-wrapper", htmlFor: inputId, onClick: this.onLabelClick }, this.renderLabelContainer(), h("div", { key: '47f2b42e2f74ea866b4f871026e08ab375d7a726', class: "native-wrapper", onClick: this.onLabelClick }, h("slot", { key: 'eaabe5a4a329a356cac3294d15c087d0d131fff2', name: "start" }), h("input", Object.assign({ key: 'c821a984a8a9b7f96f30892c06d8deda093ff24b', 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, "aria-labelledby": this.getLabelledById() }, this.inheritedAttributes)), this.clearInput && !readonly && !disabled && (h("button", { key: '62069c11016ee190dc46ab941372e1c4ad8a36ed', "aria-label": "reset", type: "button", class: "input-clear-icon", onPointerDown: (ev) => {
533
562
  /**
534
563
  * This prevents mobile browsers from
535
564
  * blurring the input when the clear
536
565
  * button is activated.
537
566
  */
538
567
  ev.preventDefault();
539
- }, onClick: this.clearTextInput }, h("ion-icon", { key: '16b0af75eed50c8115fb5597f73b5fbf71c2530e', "aria-hidden": "true", icon: clearIconData }))), h("slot", { key: 'c48da0f8ddb3764ac43efa705bb4a6bb2d9cc2fd', name: "end" })), shouldRenderHighlight && h("div", { key: 'f15238481fc20de56ca7ecb6e350b3c024cc755e', class: "input-highlight" })), this.renderBottomContent()));
568
+ }, onClick: this.clearTextInput }, h("ion-icon", { key: 'dd75a516d32110d85382b664c663bd41f177ce12', "aria-hidden": "true", icon: clearIconData }))), h("slot", { key: '330d4b9389f2c62223a5ee24003e96ef3e6b2473', name: "end" })), shouldRenderHighlight && h("div", { key: '8e442bed130ddc84976ab70fd3f8578d6bcc6316', class: "input-highlight" })), this.renderBottomContent()));
540
569
  }
541
570
  get el() { return this; }
542
571
  static get watchers() { return {
@@ -2256,10 +2256,6 @@ const Modal = /*@__PURE__*/ proxyCustomElement(class Modal extends HTMLElement {
2256
2256
  this.currentViewIsPortrait = window.innerWidth < 768;
2257
2257
  }
2258
2258
  handleViewTransition() {
2259
- // Only run view transitions when the modal is presented
2260
- if (!this.presented) {
2261
- return;
2262
- }
2263
2259
  const isPortrait = window.innerWidth < 768;
2264
2260
  // Only transition if view state actually changed
2265
2261
  if (this.currentViewIsPortrait === isPortrait) {
@@ -2424,20 +2420,20 @@ const Modal = /*@__PURE__*/ proxyCustomElement(class Modal extends HTMLElement {
2424
2420
  const isCardModal = presentingElement !== undefined && mode === 'ios';
2425
2421
  const isHandleCycle = handleBehavior === 'cycle';
2426
2422
  const isSheetModalWithHandle = isSheetModal && showHandle;
2427
- return (h(Host, Object.assign({ key: '87328006ea6c75ebc518ace300438492a567223e', "no-router": true,
2423
+ return (h(Host, Object.assign({ key: '9a75095a13de0cfc96f1fa69fd92777d25da8daa', "no-router": true,
2428
2424
  // Allow the modal to be navigable when the handle is focusable
2429
2425
  tabIndex: isHandleCycle && isSheetModalWithHandle ? 0 : -1 }, htmlAttributes, { style: {
2430
2426
  zIndex: `${20000 + this.overlayIndex}`,
2431
- }, class: Object.assign({ [mode]: true, ['modal-default']: !isCardModal && !isSheetModal, [`modal-card`]: isCardModal, [`modal-sheet`]: isSheetModal, [`modal-no-expand-scroll`]: isSheetModal && !expandToScroll, 'overlay-hidden': true, [FOCUS_TRAP_DISABLE_CLASS]: focusTrap === false }, getClassMap(this.cssClass)), onIonBackdropTap: this.onBackdropTap, onIonModalDidPresent: this.onLifecycle, onIonModalWillPresent: this.onLifecycle, onIonModalWillDismiss: this.onLifecycle, onIonModalDidDismiss: this.onLifecycle, onFocus: this.onModalFocus }), h("ion-backdrop", { key: 'ee94ff8e09b691dd4ad4e4db1720f06bc3c5a469', ref: (el) => (this.backdropEl = el), visible: this.showBackdrop, tappable: this.backdropDismiss, part: "backdrop" }), mode === 'ios' && h("div", { key: 'bffd69b4635c22d9f249725bd952c1e93d5615c7', class: "modal-shadow" }), h("div", Object.assign({ key: '1d394d3c68916e464ff1fbf5242419f4a3d3cca1',
2427
+ }, class: Object.assign({ [mode]: true, ['modal-default']: !isCardModal && !isSheetModal, [`modal-card`]: isCardModal, [`modal-sheet`]: isSheetModal, [`modal-no-expand-scroll`]: isSheetModal && !expandToScroll, 'overlay-hidden': true, [FOCUS_TRAP_DISABLE_CLASS]: focusTrap === false }, getClassMap(this.cssClass)), onIonBackdropTap: this.onBackdropTap, onIonModalDidPresent: this.onLifecycle, onIonModalWillPresent: this.onLifecycle, onIonModalWillDismiss: this.onLifecycle, onIonModalDidDismiss: this.onLifecycle, onFocus: this.onModalFocus }), h("ion-backdrop", { key: 'd02612d8063ef20f59f173ff47795f71cdaaf63e', ref: (el) => (this.backdropEl = el), visible: this.showBackdrop, tappable: this.backdropDismiss, part: "backdrop" }), mode === 'ios' && h("div", { key: '708761b70a93e34c08faae079569f444c7416a4c', class: "modal-shadow" }), h("div", Object.assign({ key: 'a72226ff1a98229f9bfd9207b98fc57e02baa430',
2432
2428
  /*
2433
2429
  role and aria-modal must be used on the
2434
2430
  same element. They must also be set inside the
2435
2431
  shadow DOM otherwise ion-button will not be highlighted
2436
2432
  when using VoiceOver: https://bugs.webkit.org/show_bug.cgi?id=247134
2437
2433
  */
2438
- role: "dialog" }, inheritedAttributes, { "aria-modal": "true", class: "modal-wrapper ion-overlay-wrapper", part: "content", ref: (el) => (this.wrapperEl = el) }), showHandle && (h("button", { key: '2dcf58792018e557e0c323baad2d672bc99c0bb1', class: "modal-handle",
2434
+ role: "dialog" }, inheritedAttributes, { "aria-modal": "true", class: "modal-wrapper ion-overlay-wrapper", part: "content", ref: (el) => (this.wrapperEl = el) }), showHandle && (h("button", { key: '0547f32323882660221385d84d492929caa77c6b', class: "modal-handle",
2439
2435
  // Prevents the handle from receiving keyboard focus when it does not cycle
2440
- tabIndex: !isHandleCycle ? -1 : 0, "aria-label": "Activate to adjust the size of the dialog overlaying the screen", onClick: isHandleCycle ? this.onHandleClick : undefined, part: "handle", ref: (el) => (this.dragHandleEl = el) })), h("slot", { key: '44164b1e8710c3895400ad9f44ecd99873874ad5', onSlotchange: this.onSlotChange }))));
2436
+ tabIndex: !isHandleCycle ? -1 : 0, "aria-label": "Activate to adjust the size of the dialog overlaying the screen", onClick: isHandleCycle ? this.onHandleClick : undefined, part: "handle", ref: (el) => (this.dragHandleEl = el) })), h("slot", { key: 'fccbd64518b6fa22f9e874deb6b4ba55d8d89c3b', onSlotchange: this.onSlotChange }))));
2441
2437
  }
2442
2438
  get el() { return this; }
2443
2439
  static get watchers() { return {
@@ -27,6 +27,7 @@ const Input = class {
27
27
  this.inputId = `ion-input-${inputIds++}`;
28
28
  this.helperTextId = `${this.inputId}-helper-text`;
29
29
  this.errorTextId = `${this.inputId}-error-text`;
30
+ this.labelTextId = `${this.inputId}-label`;
30
31
  this.inheritedAttributes = {};
31
32
  this.isComposing = false;
32
33
  /**
@@ -235,7 +236,11 @@ const Input = class {
235
236
  }
236
237
  connectedCallback() {
237
238
  const { el } = this;
238
- this.slotMutationController = input_utils.createSlotMutationController(el, ['label', 'start', 'end'], () => index.forceUpdate(this));
239
+ this.slotMutationController = input_utils.createSlotMutationController(el, ['label', 'start', 'end'], () => {
240
+ this.setSlottedLabelId();
241
+ index.forceUpdate(this);
242
+ });
243
+ this.setSlottedLabelId();
239
244
  this.notchController = notchController.createNotchController(el, () => this.notchSpacerEl, () => this.labelSlot);
240
245
  // Watch for class changes to update validation state
241
246
  if (typeof MutationObserver !== 'undefined') {
@@ -438,11 +443,11 @@ const Input = class {
438
443
  return (index.h("div", { class: "input-bottom" }, this.renderHintText(), this.renderCounter()));
439
444
  }
440
445
  renderLabel() {
441
- const { label } = this;
446
+ const { label, labelTextId } = this;
442
447
  return (index.h("div", { class: {
443
448
  'label-text-wrapper': true,
444
449
  'label-text-wrapper-hidden': !this.hasLabel,
445
- } }, label === undefined ? index.h("slot", { name: "label" }) : index.h("div", { class: "label-text" }, label)));
450
+ }, "aria-hidden": this.hasLabel ? 'true' : null }, label === undefined ? (index.h("slot", { name: "label" })) : (index.h("div", { class: "label-text", id: labelTextId }, label))));
446
451
  }
447
452
  /**
448
453
  * Gets any content passed into the `label` slot,
@@ -451,6 +456,30 @@ const Input = class {
451
456
  get labelSlot() {
452
457
  return this.el.querySelector('[slot="label"]');
453
458
  }
459
+ /**
460
+ * Ensures the slotted label element has an ID for aria-labelledby.
461
+ * If no ID exists, we assign one using our generated labelTextId.
462
+ */
463
+ setSlottedLabelId() {
464
+ const slottedLabel = this.labelSlot;
465
+ if (slottedLabel && !slottedLabel.id) {
466
+ slottedLabel.id = this.labelTextId;
467
+ }
468
+ }
469
+ /**
470
+ * Returns the ID to use for aria-labelledby on the native input,
471
+ * or undefined if aria-label is explicitly set (to avoid conflicts).
472
+ */
473
+ getLabelledById() {
474
+ var _a;
475
+ if (this.inheritedAttributes['aria-label']) {
476
+ return undefined;
477
+ }
478
+ if (this.label !== undefined) {
479
+ return this.labelTextId;
480
+ }
481
+ return ((_a = this.labelSlot) === null || _a === void 0 ? void 0 : _a.id) || undefined;
482
+ }
454
483
  /**
455
484
  * Returns `true` if label content is provided
456
485
  * either by a prop or a content. If you want
@@ -517,7 +546,7 @@ const Input = class {
517
546
  * TODO(FW-5592): Remove hasStartEndSlots condition
518
547
  */
519
548
  const labelShouldFloat = labelPlacement === 'stacked' || (labelPlacement === 'floating' && (hasValue || hasFocus || hasStartEndSlots));
520
- return (index.h(index.Host, { key: '97b5308021064d9e7434ef2d3d96f27045c1b0c4', class: theme.createColorClasses(this.color, {
549
+ return (index.h(index.Host, { key: '9ba9cf425b573d2ca9ac34455a0e6b8474c4de6d', class: theme.createColorClasses(this.color, {
521
550
  [mode]: true,
522
551
  'has-value': hasValue,
523
552
  'has-focus': hasFocus,
@@ -528,14 +557,14 @@ const Input = class {
528
557
  'in-item': inItem,
529
558
  'in-item-color': theme.hostContext('ion-item.ion-color', this.el),
530
559
  'input-disabled': disabled,
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) => {
560
+ }) }, index.h("label", { key: '74b989d0aa5ab38f29f952519868f05119df6005', class: "input-wrapper", htmlFor: inputId, onClick: this.onLabelClick }, this.renderLabelContainer(), index.h("div", { key: '47f2b42e2f74ea866b4f871026e08ab375d7a726', class: "native-wrapper", onClick: this.onLabelClick }, index.h("slot", { key: 'eaabe5a4a329a356cac3294d15c087d0d131fff2', name: "start" }), index.h("input", Object.assign({ key: 'c821a984a8a9b7f96f30892c06d8deda093ff24b', 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, "aria-labelledby": this.getLabelledById() }, this.inheritedAttributes)), this.clearInput && !readonly && !disabled && (index.h("button", { key: '62069c11016ee190dc46ab941372e1c4ad8a36ed', "aria-label": "reset", type: "button", class: "input-clear-icon", onPointerDown: (ev) => {
532
561
  /**
533
562
  * This prevents mobile browsers from
534
563
  * blurring the input when the clear
535
564
  * button is activated.
536
565
  */
537
566
  ev.preventDefault();
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()));
567
+ }, onClick: this.clearTextInput }, index.h("ion-icon", { key: 'dd75a516d32110d85382b664c663bd41f177ce12', "aria-hidden": "true", icon: clearIconData }))), index.h("slot", { key: '330d4b9389f2c62223a5ee24003e96ef3e6b2473', name: "end" })), shouldRenderHighlight && index.h("div", { key: '8e442bed130ddc84976ab70fd3f8578d6bcc6316', class: "input-highlight" })), this.renderBottomContent()));
539
568
  }
540
569
  get el() { return index.getElement(this); }
541
570
  static get watchers() { return {
@@ -2255,10 +2255,6 @@ const Modal = class {
2255
2255
  this.currentViewIsPortrait = window.innerWidth < 768;
2256
2256
  }
2257
2257
  handleViewTransition() {
2258
- // Only run view transitions when the modal is presented
2259
- if (!this.presented) {
2260
- return;
2261
- }
2262
2258
  const isPortrait = window.innerWidth < 768;
2263
2259
  // Only transition if view state actually changed
2264
2260
  if (this.currentViewIsPortrait === isPortrait) {
@@ -2423,20 +2419,20 @@ const Modal = class {
2423
2419
  const isCardModal = presentingElement !== undefined && mode === 'ios';
2424
2420
  const isHandleCycle = handleBehavior === 'cycle';
2425
2421
  const isSheetModalWithHandle = isSheetModal && showHandle;
2426
- return (index$3.h(index$3.Host, Object.assign({ key: '87328006ea6c75ebc518ace300438492a567223e', "no-router": true,
2422
+ return (index$3.h(index$3.Host, Object.assign({ key: '9a75095a13de0cfc96f1fa69fd92777d25da8daa', "no-router": true,
2427
2423
  // Allow the modal to be navigable when the handle is focusable
2428
2424
  tabIndex: isHandleCycle && isSheetModalWithHandle ? 0 : -1 }, htmlAttributes, { style: {
2429
2425
  zIndex: `${20000 + this.overlayIndex}`,
2430
- }, class: Object.assign({ [mode]: true, ['modal-default']: !isCardModal && !isSheetModal, [`modal-card`]: isCardModal, [`modal-sheet`]: isSheetModal, [`modal-no-expand-scroll`]: isSheetModal && !expandToScroll, 'overlay-hidden': true, [overlays.FOCUS_TRAP_DISABLE_CLASS]: focusTrap === false }, theme.getClassMap(this.cssClass)), onIonBackdropTap: this.onBackdropTap, onIonModalDidPresent: this.onLifecycle, onIonModalWillPresent: this.onLifecycle, onIonModalWillDismiss: this.onLifecycle, onIonModalDidDismiss: this.onLifecycle, onFocus: this.onModalFocus }), index$3.h("ion-backdrop", { key: 'ee94ff8e09b691dd4ad4e4db1720f06bc3c5a469', ref: (el) => (this.backdropEl = el), visible: this.showBackdrop, tappable: this.backdropDismiss, part: "backdrop" }), mode === 'ios' && index$3.h("div", { key: 'bffd69b4635c22d9f249725bd952c1e93d5615c7', class: "modal-shadow" }), index$3.h("div", Object.assign({ key: '1d394d3c68916e464ff1fbf5242419f4a3d3cca1',
2426
+ }, class: Object.assign({ [mode]: true, ['modal-default']: !isCardModal && !isSheetModal, [`modal-card`]: isCardModal, [`modal-sheet`]: isSheetModal, [`modal-no-expand-scroll`]: isSheetModal && !expandToScroll, 'overlay-hidden': true, [overlays.FOCUS_TRAP_DISABLE_CLASS]: focusTrap === false }, theme.getClassMap(this.cssClass)), onIonBackdropTap: this.onBackdropTap, onIonModalDidPresent: this.onLifecycle, onIonModalWillPresent: this.onLifecycle, onIonModalWillDismiss: this.onLifecycle, onIonModalDidDismiss: this.onLifecycle, onFocus: this.onModalFocus }), index$3.h("ion-backdrop", { key: 'd02612d8063ef20f59f173ff47795f71cdaaf63e', ref: (el) => (this.backdropEl = el), visible: this.showBackdrop, tappable: this.backdropDismiss, part: "backdrop" }), mode === 'ios' && index$3.h("div", { key: '708761b70a93e34c08faae079569f444c7416a4c', class: "modal-shadow" }), index$3.h("div", Object.assign({ key: 'a72226ff1a98229f9bfd9207b98fc57e02baa430',
2431
2427
  /*
2432
2428
  role and aria-modal must be used on the
2433
2429
  same element. They must also be set inside the
2434
2430
  shadow DOM otherwise ion-button will not be highlighted
2435
2431
  when using VoiceOver: https://bugs.webkit.org/show_bug.cgi?id=247134
2436
2432
  */
2437
- role: "dialog" }, inheritedAttributes, { "aria-modal": "true", class: "modal-wrapper ion-overlay-wrapper", part: "content", ref: (el) => (this.wrapperEl = el) }), showHandle && (index$3.h("button", { key: '2dcf58792018e557e0c323baad2d672bc99c0bb1', class: "modal-handle",
2433
+ role: "dialog" }, inheritedAttributes, { "aria-modal": "true", class: "modal-wrapper ion-overlay-wrapper", part: "content", ref: (el) => (this.wrapperEl = el) }), showHandle && (index$3.h("button", { key: '0547f32323882660221385d84d492929caa77c6b', class: "modal-handle",
2438
2434
  // Prevents the handle from receiving keyboard focus when it does not cycle
2439
- tabIndex: !isHandleCycle ? -1 : 0, "aria-label": "Activate to adjust the size of the dialog overlaying the screen", onClick: isHandleCycle ? this.onHandleClick : undefined, part: "handle", ref: (el) => (this.dragHandleEl = el) })), index$3.h("slot", { key: '44164b1e8710c3895400ad9f44ecd99873874ad5', onSlotchange: this.onSlotChange }))));
2435
+ tabIndex: !isHandleCycle ? -1 : 0, "aria-label": "Activate to adjust the size of the dialog overlaying the screen", onClick: isHandleCycle ? this.onHandleClick : undefined, part: "handle", ref: (el) => (this.dragHandleEl = el) })), index$3.h("slot", { key: 'fccbd64518b6fa22f9e874deb6b4ba55d8d89c3b', onSlotchange: this.onSlotChange }))));
2440
2436
  }
2441
2437
  get el() { return index$3.getElement(this); }
2442
2438
  static get watchers() { return {
@@ -21,6 +21,7 @@ export class Input {
21
21
  this.inputId = `ion-input-${inputIds++}`;
22
22
  this.helperTextId = `${this.inputId}-helper-text`;
23
23
  this.errorTextId = `${this.inputId}-error-text`;
24
+ this.labelTextId = `${this.inputId}-label`;
24
25
  this.inheritedAttributes = {};
25
26
  this.isComposing = false;
26
27
  /**
@@ -229,7 +230,11 @@ export class Input {
229
230
  }
230
231
  connectedCallback() {
231
232
  const { el } = this;
232
- this.slotMutationController = createSlotMutationController(el, ['label', 'start', 'end'], () => forceUpdate(this));
233
+ this.slotMutationController = createSlotMutationController(el, ['label', 'start', 'end'], () => {
234
+ this.setSlottedLabelId();
235
+ forceUpdate(this);
236
+ });
237
+ this.setSlottedLabelId();
233
238
  this.notchController = createNotchController(el, () => this.notchSpacerEl, () => this.labelSlot);
234
239
  // Watch for class changes to update validation state
235
240
  if (Build.isBrowser && typeof MutationObserver !== 'undefined') {
@@ -432,11 +437,11 @@ export class Input {
432
437
  return (h("div", { class: "input-bottom" }, this.renderHintText(), this.renderCounter()));
433
438
  }
434
439
  renderLabel() {
435
- const { label } = this;
440
+ const { label, labelTextId } = this;
436
441
  return (h("div", { class: {
437
442
  'label-text-wrapper': true,
438
443
  'label-text-wrapper-hidden': !this.hasLabel,
439
- } }, label === undefined ? h("slot", { name: "label" }) : h("div", { class: "label-text" }, label)));
444
+ }, "aria-hidden": this.hasLabel ? 'true' : null }, label === undefined ? (h("slot", { name: "label" })) : (h("div", { class: "label-text", id: labelTextId }, label))));
440
445
  }
441
446
  /**
442
447
  * Gets any content passed into the `label` slot,
@@ -445,6 +450,30 @@ export class Input {
445
450
  get labelSlot() {
446
451
  return this.el.querySelector('[slot="label"]');
447
452
  }
453
+ /**
454
+ * Ensures the slotted label element has an ID for aria-labelledby.
455
+ * If no ID exists, we assign one using our generated labelTextId.
456
+ */
457
+ setSlottedLabelId() {
458
+ const slottedLabel = this.labelSlot;
459
+ if (slottedLabel && !slottedLabel.id) {
460
+ slottedLabel.id = this.labelTextId;
461
+ }
462
+ }
463
+ /**
464
+ * Returns the ID to use for aria-labelledby on the native input,
465
+ * or undefined if aria-label is explicitly set (to avoid conflicts).
466
+ */
467
+ getLabelledById() {
468
+ var _a;
469
+ if (this.inheritedAttributes['aria-label']) {
470
+ return undefined;
471
+ }
472
+ if (this.label !== undefined) {
473
+ return this.labelTextId;
474
+ }
475
+ return ((_a = this.labelSlot) === null || _a === void 0 ? void 0 : _a.id) || undefined;
476
+ }
448
477
  /**
449
478
  * Returns `true` if label content is provided
450
479
  * either by a prop or a content. If you want
@@ -511,7 +540,7 @@ export class Input {
511
540
  * TODO(FW-5592): Remove hasStartEndSlots condition
512
541
  */
513
542
  const labelShouldFloat = labelPlacement === 'stacked' || (labelPlacement === 'floating' && (hasValue || hasFocus || hasStartEndSlots));
514
- return (h(Host, { key: '97b5308021064d9e7434ef2d3d96f27045c1b0c4', class: createColorClasses(this.color, {
543
+ return (h(Host, { key: '9ba9cf425b573d2ca9ac34455a0e6b8474c4de6d', class: createColorClasses(this.color, {
515
544
  [mode]: true,
516
545
  'has-value': hasValue,
517
546
  'has-focus': hasFocus,
@@ -522,14 +551,14 @@ export class Input {
522
551
  'in-item': inItem,
523
552
  'in-item-color': hostContext('ion-item.ion-color', this.el),
524
553
  'input-disabled': disabled,
525
- }) }, h("label", { key: '353f68726ce180299bd9adc81e5ff7d26a48f54f', class: "input-wrapper", htmlFor: inputId, onClick: this.onLabelClick }, this.renderLabelContainer(), h("div", { key: '2034b4bad04fc157f3298a1805819216b6f439d0', class: "native-wrapper", onClick: this.onLabelClick }, h("slot", { key: '96bb5e30176b2bd76dfb75bfbf6c1c3d4403f4bb', name: "start" }), 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 && (h("button", { key: '95f3df17b7691d9a2e7dcd4a51f16a94aa3ca36f', "aria-label": "reset", type: "button", class: "input-clear-icon", onPointerDown: (ev) => {
554
+ }) }, h("label", { key: '74b989d0aa5ab38f29f952519868f05119df6005', class: "input-wrapper", htmlFor: inputId, onClick: this.onLabelClick }, this.renderLabelContainer(), h("div", { key: '47f2b42e2f74ea866b4f871026e08ab375d7a726', class: "native-wrapper", onClick: this.onLabelClick }, h("slot", { key: 'eaabe5a4a329a356cac3294d15c087d0d131fff2', name: "start" }), h("input", Object.assign({ key: 'c821a984a8a9b7f96f30892c06d8deda093ff24b', 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, "aria-labelledby": this.getLabelledById() }, this.inheritedAttributes)), this.clearInput && !readonly && !disabled && (h("button", { key: '62069c11016ee190dc46ab941372e1c4ad8a36ed', "aria-label": "reset", type: "button", class: "input-clear-icon", onPointerDown: (ev) => {
526
555
  /**
527
556
  * This prevents mobile browsers from
528
557
  * blurring the input when the clear
529
558
  * button is activated.
530
559
  */
531
560
  ev.preventDefault();
532
- }, onClick: this.clearTextInput }, h("ion-icon", { key: '16b0af75eed50c8115fb5597f73b5fbf71c2530e', "aria-hidden": "true", icon: clearIconData }))), h("slot", { key: 'c48da0f8ddb3764ac43efa705bb4a6bb2d9cc2fd', name: "end" })), shouldRenderHighlight && h("div", { key: 'f15238481fc20de56ca7ecb6e350b3c024cc755e', class: "input-highlight" })), this.renderBottomContent()));
561
+ }, onClick: this.clearTextInput }, h("ion-icon", { key: 'dd75a516d32110d85382b664c663bd41f177ce12', "aria-hidden": "true", icon: clearIconData }))), h("slot", { key: '330d4b9389f2c62223a5ee24003e96ef3e6b2473', name: "end" })), shouldRenderHighlight && h("div", { key: '8e442bed130ddc84976ab70fd3f8578d6bcc6316', class: "input-highlight" })), this.renderBottomContent()));
533
562
  }
534
563
  static get is() { return "ion-input"; }
535
564
  static get encapsulation() { return "scoped"; }
@@ -798,10 +798,6 @@ export class Modal {
798
798
  this.currentViewIsPortrait = window.innerWidth < 768;
799
799
  }
800
800
  handleViewTransition() {
801
- // Only run view transitions when the modal is presented
802
- if (!this.presented) {
803
- return;
804
- }
805
801
  const isPortrait = window.innerWidth < 768;
806
802
  // Only transition if view state actually changed
807
803
  if (this.currentViewIsPortrait === isPortrait) {
@@ -974,20 +970,20 @@ export class Modal {
974
970
  const isCardModal = presentingElement !== undefined && mode === 'ios';
975
971
  const isHandleCycle = handleBehavior === 'cycle';
976
972
  const isSheetModalWithHandle = isSheetModal && showHandle;
977
- return (h(Host, Object.assign({ key: '87328006ea6c75ebc518ace300438492a567223e', "no-router": true,
973
+ return (h(Host, Object.assign({ key: '9a75095a13de0cfc96f1fa69fd92777d25da8daa', "no-router": true,
978
974
  // Allow the modal to be navigable when the handle is focusable
979
975
  tabIndex: isHandleCycle && isSheetModalWithHandle ? 0 : -1 }, htmlAttributes, { style: {
980
976
  zIndex: `${20000 + this.overlayIndex}`,
981
- }, class: Object.assign({ [mode]: true, ['modal-default']: !isCardModal && !isSheetModal, [`modal-card`]: isCardModal, [`modal-sheet`]: isSheetModal, [`modal-no-expand-scroll`]: isSheetModal && !expandToScroll, 'overlay-hidden': true, [FOCUS_TRAP_DISABLE_CLASS]: focusTrap === false }, getClassMap(this.cssClass)), onIonBackdropTap: this.onBackdropTap, onIonModalDidPresent: this.onLifecycle, onIonModalWillPresent: this.onLifecycle, onIonModalWillDismiss: this.onLifecycle, onIonModalDidDismiss: this.onLifecycle, onFocus: this.onModalFocus }), h("ion-backdrop", { key: 'ee94ff8e09b691dd4ad4e4db1720f06bc3c5a469', ref: (el) => (this.backdropEl = el), visible: this.showBackdrop, tappable: this.backdropDismiss, part: "backdrop" }), mode === 'ios' && h("div", { key: 'bffd69b4635c22d9f249725bd952c1e93d5615c7', class: "modal-shadow" }), h("div", Object.assign({ key: '1d394d3c68916e464ff1fbf5242419f4a3d3cca1',
977
+ }, class: Object.assign({ [mode]: true, ['modal-default']: !isCardModal && !isSheetModal, [`modal-card`]: isCardModal, [`modal-sheet`]: isSheetModal, [`modal-no-expand-scroll`]: isSheetModal && !expandToScroll, 'overlay-hidden': true, [FOCUS_TRAP_DISABLE_CLASS]: focusTrap === false }, getClassMap(this.cssClass)), onIonBackdropTap: this.onBackdropTap, onIonModalDidPresent: this.onLifecycle, onIonModalWillPresent: this.onLifecycle, onIonModalWillDismiss: this.onLifecycle, onIonModalDidDismiss: this.onLifecycle, onFocus: this.onModalFocus }), h("ion-backdrop", { key: 'd02612d8063ef20f59f173ff47795f71cdaaf63e', ref: (el) => (this.backdropEl = el), visible: this.showBackdrop, tappable: this.backdropDismiss, part: "backdrop" }), mode === 'ios' && h("div", { key: '708761b70a93e34c08faae079569f444c7416a4c', class: "modal-shadow" }), h("div", Object.assign({ key: 'a72226ff1a98229f9bfd9207b98fc57e02baa430',
982
978
  /*
983
979
  role and aria-modal must be used on the
984
980
  same element. They must also be set inside the
985
981
  shadow DOM otherwise ion-button will not be highlighted
986
982
  when using VoiceOver: https://bugs.webkit.org/show_bug.cgi?id=247134
987
983
  */
988
- role: "dialog" }, inheritedAttributes, { "aria-modal": "true", class: "modal-wrapper ion-overlay-wrapper", part: "content", ref: (el) => (this.wrapperEl = el) }), showHandle && (h("button", { key: '2dcf58792018e557e0c323baad2d672bc99c0bb1', class: "modal-handle",
984
+ role: "dialog" }, inheritedAttributes, { "aria-modal": "true", class: "modal-wrapper ion-overlay-wrapper", part: "content", ref: (el) => (this.wrapperEl = el) }), showHandle && (h("button", { key: '0547f32323882660221385d84d492929caa77c6b', class: "modal-handle",
989
985
  // Prevents the handle from receiving keyboard focus when it does not cycle
990
- tabIndex: !isHandleCycle ? -1 : 0, "aria-label": "Activate to adjust the size of the dialog overlaying the screen", onClick: isHandleCycle ? this.onHandleClick : undefined, part: "handle", ref: (el) => (this.dragHandleEl = el) })), h("slot", { key: '44164b1e8710c3895400ad9f44ecd99873874ad5', onSlotchange: this.onSlotChange }))));
986
+ tabIndex: !isHandleCycle ? -1 : 0, "aria-label": "Activate to adjust the size of the dialog overlaying the screen", onClick: isHandleCycle ? this.onHandleClick : undefined, part: "handle", ref: (el) => (this.dragHandleEl = el) })), h("slot", { key: 'fccbd64518b6fa22f9e874deb6b4ba55d8d89c3b', onSlotchange: this.onSlotChange }))));
991
987
  }
992
988
  static get is() { return "ion-modal"; }
993
989
  static get encapsulation() { return "shadow"; }
package/dist/docs.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "timestamp": "2025-12-29T17:20:47",
2
+ "timestamp": "2025-12-29T18:31:40",
3
3
  "compiler": {
4
4
  "name": "@stencil/core",
5
5
  "version": "4.38.0",
@@ -25,6 +25,7 @@ const Input = class {
25
25
  this.inputId = `ion-input-${inputIds++}`;
26
26
  this.helperTextId = `${this.inputId}-helper-text`;
27
27
  this.errorTextId = `${this.inputId}-error-text`;
28
+ this.labelTextId = `${this.inputId}-label`;
28
29
  this.inheritedAttributes = {};
29
30
  this.isComposing = false;
30
31
  /**
@@ -233,7 +234,11 @@ const Input = class {
233
234
  }
234
235
  connectedCallback() {
235
236
  const { el } = this;
236
- this.slotMutationController = createSlotMutationController(el, ['label', 'start', 'end'], () => forceUpdate(this));
237
+ this.slotMutationController = createSlotMutationController(el, ['label', 'start', 'end'], () => {
238
+ this.setSlottedLabelId();
239
+ forceUpdate(this);
240
+ });
241
+ this.setSlottedLabelId();
237
242
  this.notchController = createNotchController(el, () => this.notchSpacerEl, () => this.labelSlot);
238
243
  // Watch for class changes to update validation state
239
244
  if (typeof MutationObserver !== 'undefined') {
@@ -436,11 +441,11 @@ const Input = class {
436
441
  return (h("div", { class: "input-bottom" }, this.renderHintText(), this.renderCounter()));
437
442
  }
438
443
  renderLabel() {
439
- const { label } = this;
444
+ const { label, labelTextId } = this;
440
445
  return (h("div", { class: {
441
446
  'label-text-wrapper': true,
442
447
  'label-text-wrapper-hidden': !this.hasLabel,
443
- } }, label === undefined ? h("slot", { name: "label" }) : h("div", { class: "label-text" }, label)));
448
+ }, "aria-hidden": this.hasLabel ? 'true' : null }, label === undefined ? (h("slot", { name: "label" })) : (h("div", { class: "label-text", id: labelTextId }, label))));
444
449
  }
445
450
  /**
446
451
  * Gets any content passed into the `label` slot,
@@ -449,6 +454,30 @@ const Input = class {
449
454
  get labelSlot() {
450
455
  return this.el.querySelector('[slot="label"]');
451
456
  }
457
+ /**
458
+ * Ensures the slotted label element has an ID for aria-labelledby.
459
+ * If no ID exists, we assign one using our generated labelTextId.
460
+ */
461
+ setSlottedLabelId() {
462
+ const slottedLabel = this.labelSlot;
463
+ if (slottedLabel && !slottedLabel.id) {
464
+ slottedLabel.id = this.labelTextId;
465
+ }
466
+ }
467
+ /**
468
+ * Returns the ID to use for aria-labelledby on the native input,
469
+ * or undefined if aria-label is explicitly set (to avoid conflicts).
470
+ */
471
+ getLabelledById() {
472
+ var _a;
473
+ if (this.inheritedAttributes['aria-label']) {
474
+ return undefined;
475
+ }
476
+ if (this.label !== undefined) {
477
+ return this.labelTextId;
478
+ }
479
+ return ((_a = this.labelSlot) === null || _a === void 0 ? void 0 : _a.id) || undefined;
480
+ }
452
481
  /**
453
482
  * Returns `true` if label content is provided
454
483
  * either by a prop or a content. If you want
@@ -515,7 +544,7 @@ const Input = class {
515
544
  * TODO(FW-5592): Remove hasStartEndSlots condition
516
545
  */
517
546
  const labelShouldFloat = labelPlacement === 'stacked' || (labelPlacement === 'floating' && (hasValue || hasFocus || hasStartEndSlots));
518
- return (h(Host, { key: '97b5308021064d9e7434ef2d3d96f27045c1b0c4', class: createColorClasses(this.color, {
547
+ return (h(Host, { key: '9ba9cf425b573d2ca9ac34455a0e6b8474c4de6d', class: createColorClasses(this.color, {
519
548
  [mode]: true,
520
549
  'has-value': hasValue,
521
550
  'has-focus': hasFocus,
@@ -526,14 +555,14 @@ const Input = class {
526
555
  'in-item': inItem,
527
556
  'in-item-color': hostContext('ion-item.ion-color', this.el),
528
557
  'input-disabled': disabled,
529
- }) }, h("label", { key: '353f68726ce180299bd9adc81e5ff7d26a48f54f', class: "input-wrapper", htmlFor: inputId, onClick: this.onLabelClick }, this.renderLabelContainer(), h("div", { key: '2034b4bad04fc157f3298a1805819216b6f439d0', class: "native-wrapper", onClick: this.onLabelClick }, h("slot", { key: '96bb5e30176b2bd76dfb75bfbf6c1c3d4403f4bb', name: "start" }), 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 && (h("button", { key: '95f3df17b7691d9a2e7dcd4a51f16a94aa3ca36f', "aria-label": "reset", type: "button", class: "input-clear-icon", onPointerDown: (ev) => {
558
+ }) }, h("label", { key: '74b989d0aa5ab38f29f952519868f05119df6005', class: "input-wrapper", htmlFor: inputId, onClick: this.onLabelClick }, this.renderLabelContainer(), h("div", { key: '47f2b42e2f74ea866b4f871026e08ab375d7a726', class: "native-wrapper", onClick: this.onLabelClick }, h("slot", { key: 'eaabe5a4a329a356cac3294d15c087d0d131fff2', name: "start" }), h("input", Object.assign({ key: 'c821a984a8a9b7f96f30892c06d8deda093ff24b', 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, "aria-labelledby": this.getLabelledById() }, this.inheritedAttributes)), this.clearInput && !readonly && !disabled && (h("button", { key: '62069c11016ee190dc46ab941372e1c4ad8a36ed', "aria-label": "reset", type: "button", class: "input-clear-icon", onPointerDown: (ev) => {
530
559
  /**
531
560
  * This prevents mobile browsers from
532
561
  * blurring the input when the clear
533
562
  * button is activated.
534
563
  */
535
564
  ev.preventDefault();
536
- }, onClick: this.clearTextInput }, h("ion-icon", { key: '16b0af75eed50c8115fb5597f73b5fbf71c2530e', "aria-hidden": "true", icon: clearIconData }))), h("slot", { key: 'c48da0f8ddb3764ac43efa705bb4a6bb2d9cc2fd', name: "end" })), shouldRenderHighlight && h("div", { key: 'f15238481fc20de56ca7ecb6e350b3c024cc755e', class: "input-highlight" })), this.renderBottomContent()));
565
+ }, onClick: this.clearTextInput }, h("ion-icon", { key: 'dd75a516d32110d85382b664c663bd41f177ce12', "aria-hidden": "true", icon: clearIconData }))), h("slot", { key: '330d4b9389f2c62223a5ee24003e96ef3e6b2473', name: "end" })), shouldRenderHighlight && h("div", { key: '8e442bed130ddc84976ab70fd3f8578d6bcc6316', class: "input-highlight" })), this.renderBottomContent()));
537
566
  }
538
567
  get el() { return getElement(this); }
539
568
  static get watchers() { return {
@@ -2253,10 +2253,6 @@ const Modal = class {
2253
2253
  this.currentViewIsPortrait = window.innerWidth < 768;
2254
2254
  }
2255
2255
  handleViewTransition() {
2256
- // Only run view transitions when the modal is presented
2257
- if (!this.presented) {
2258
- return;
2259
- }
2260
2256
  const isPortrait = window.innerWidth < 768;
2261
2257
  // Only transition if view state actually changed
2262
2258
  if (this.currentViewIsPortrait === isPortrait) {
@@ -2421,20 +2417,20 @@ const Modal = class {
2421
2417
  const isCardModal = presentingElement !== undefined && mode === 'ios';
2422
2418
  const isHandleCycle = handleBehavior === 'cycle';
2423
2419
  const isSheetModalWithHandle = isSheetModal && showHandle;
2424
- return (h(Host, Object.assign({ key: '87328006ea6c75ebc518ace300438492a567223e', "no-router": true,
2420
+ return (h(Host, Object.assign({ key: '9a75095a13de0cfc96f1fa69fd92777d25da8daa', "no-router": true,
2425
2421
  // Allow the modal to be navigable when the handle is focusable
2426
2422
  tabIndex: isHandleCycle && isSheetModalWithHandle ? 0 : -1 }, htmlAttributes, { style: {
2427
2423
  zIndex: `${20000 + this.overlayIndex}`,
2428
- }, class: Object.assign({ [mode]: true, ['modal-default']: !isCardModal && !isSheetModal, [`modal-card`]: isCardModal, [`modal-sheet`]: isSheetModal, [`modal-no-expand-scroll`]: isSheetModal && !expandToScroll, 'overlay-hidden': true, [FOCUS_TRAP_DISABLE_CLASS]: focusTrap === false }, getClassMap(this.cssClass)), onIonBackdropTap: this.onBackdropTap, onIonModalDidPresent: this.onLifecycle, onIonModalWillPresent: this.onLifecycle, onIonModalWillDismiss: this.onLifecycle, onIonModalDidDismiss: this.onLifecycle, onFocus: this.onModalFocus }), h("ion-backdrop", { key: 'ee94ff8e09b691dd4ad4e4db1720f06bc3c5a469', ref: (el) => (this.backdropEl = el), visible: this.showBackdrop, tappable: this.backdropDismiss, part: "backdrop" }), mode === 'ios' && h("div", { key: 'bffd69b4635c22d9f249725bd952c1e93d5615c7', class: "modal-shadow" }), h("div", Object.assign({ key: '1d394d3c68916e464ff1fbf5242419f4a3d3cca1',
2424
+ }, class: Object.assign({ [mode]: true, ['modal-default']: !isCardModal && !isSheetModal, [`modal-card`]: isCardModal, [`modal-sheet`]: isSheetModal, [`modal-no-expand-scroll`]: isSheetModal && !expandToScroll, 'overlay-hidden': true, [FOCUS_TRAP_DISABLE_CLASS]: focusTrap === false }, getClassMap(this.cssClass)), onIonBackdropTap: this.onBackdropTap, onIonModalDidPresent: this.onLifecycle, onIonModalWillPresent: this.onLifecycle, onIonModalWillDismiss: this.onLifecycle, onIonModalDidDismiss: this.onLifecycle, onFocus: this.onModalFocus }), h("ion-backdrop", { key: 'd02612d8063ef20f59f173ff47795f71cdaaf63e', ref: (el) => (this.backdropEl = el), visible: this.showBackdrop, tappable: this.backdropDismiss, part: "backdrop" }), mode === 'ios' && h("div", { key: '708761b70a93e34c08faae079569f444c7416a4c', class: "modal-shadow" }), h("div", Object.assign({ key: 'a72226ff1a98229f9bfd9207b98fc57e02baa430',
2429
2425
  /*
2430
2426
  role and aria-modal must be used on the
2431
2427
  same element. They must also be set inside the
2432
2428
  shadow DOM otherwise ion-button will not be highlighted
2433
2429
  when using VoiceOver: https://bugs.webkit.org/show_bug.cgi?id=247134
2434
2430
  */
2435
- role: "dialog" }, inheritedAttributes, { "aria-modal": "true", class: "modal-wrapper ion-overlay-wrapper", part: "content", ref: (el) => (this.wrapperEl = el) }), showHandle && (h("button", { key: '2dcf58792018e557e0c323baad2d672bc99c0bb1', class: "modal-handle",
2431
+ role: "dialog" }, inheritedAttributes, { "aria-modal": "true", class: "modal-wrapper ion-overlay-wrapper", part: "content", ref: (el) => (this.wrapperEl = el) }), showHandle && (h("button", { key: '0547f32323882660221385d84d492929caa77c6b', class: "modal-handle",
2436
2432
  // Prevents the handle from receiving keyboard focus when it does not cycle
2437
- tabIndex: !isHandleCycle ? -1 : 0, "aria-label": "Activate to adjust the size of the dialog overlaying the screen", onClick: isHandleCycle ? this.onHandleClick : undefined, part: "handle", ref: (el) => (this.dragHandleEl = el) })), h("slot", { key: '44164b1e8710c3895400ad9f44ecd99873874ad5', onSlotchange: this.onSlotChange }))));
2433
+ tabIndex: !isHandleCycle ? -1 : 0, "aria-label": "Activate to adjust the size of the dialog overlaying the screen", onClick: isHandleCycle ? this.onHandleClick : undefined, part: "handle", ref: (el) => (this.dragHandleEl = el) })), h("slot", { key: 'fccbd64518b6fa22f9e874deb6b4ba55d8d89c3b', onSlotchange: this.onSlotChange }))));
2438
2434
  }
2439
2435
  get el() { return getElement(this); }
2440
2436
  static get watchers() { return {