@ionic/core 8.7.7-nightly.20251014 → 8.7.7
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/header.js +42 -4
- package/components/index2.js +74 -3
- package/components/ion-input.js +6 -14
- package/components/ion-select.js +58 -10
- package/components/ion-textarea.js +5 -13
- package/components/{notch-controller.js → validity.js} +14 -1
- package/dist/cjs/{index-CD5Rjp23.js → index-094mMFB-.js} +76 -5
- package/dist/cjs/index.cjs.js +3 -3
- 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-input.cjs.entry.js +7 -15
- 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-select_3.cjs.entry.js +56 -10
- package/dist/cjs/ion-textarea.cjs.entry.js +6 -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/{notch-controller-Bzqhjm4f.js → validity-C8QoAYT2.js} +14 -0
- package/dist/collection/components/button/button.js +3 -7
- 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/select/select.js +59 -11
- package/dist/collection/components/textarea/textarea.js +5 -13
- package/dist/collection/utils/forms/index.js +1 -0
- package/dist/collection/utils/forms/validity.js +15 -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-app_8.entry.js +43 -5
- package/dist/esm/ion-button_2.entry.js +3 -7
- package/dist/esm/ion-input.entry.js +6 -14
- 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-select_3.entry.js +55 -9
- package/dist/esm/ion-textarea.entry.js +5 -13
- 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/{notch-controller-BwelN_JM.js → validity-B8oWougr.js} +14 -1
- package/dist/ionic/index.esm.js +1 -1
- package/dist/ionic/ionic.esm.js +1 -1
- package/dist/ionic/p-43ed1ef5.entry.js +4 -0
- package/dist/ionic/p-4c85d268.entry.js +4 -0
- package/dist/ionic/p-4cc26913.entry.js +4 -0
- package/dist/ionic/p-8bdfc8f6.entry.js +4 -0
- package/dist/ionic/{p-DPhQmGJN.js → p-C7hRNDhM.js} +1 -1
- package/dist/ionic/p-DUt5fQmA.js +4 -0
- package/dist/ionic/{p-9R1XyICs.js → p-DZRJwG4S.js} +1 -1
- package/dist/ionic/{p-DCv9sLH2.js → p-DieJyvMP.js} +1 -1
- package/dist/ionic/{p-c59314fd.entry.js → p-a80f1b04.entry.js} +1 -1
- package/dist/ionic/{p-c85c40ee.entry.js → p-dbbe606a.entry.js} +1 -1
- package/dist/ionic/{p-de7b5fa3.entry.js → p-e16b69e1.entry.js} +1 -1
- package/dist/ionic/p-f65f9308.entry.js +4 -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/select/select.d.ts +6 -0
- package/dist/types/components/textarea/textarea.d.ts +0 -4
- 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 +161 -45
- package/hydrate/index.mjs +161 -45
- package/package.json +2 -2
- package/dist/ionic/p-1c8a476d.entry.js +0 -4
- package/dist/ionic/p-49f0149c.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-913a7c1e.entry.js +0 -4
- package/dist/ionic/p-CMhMiYSX.js +0 -4
package/hydrate/index.js
CHANGED
|
@@ -9263,11 +9263,7 @@ class Button {
|
|
|
9263
9263
|
target,
|
|
9264
9264
|
};
|
|
9265
9265
|
let fill = this.fill;
|
|
9266
|
-
|
|
9267
|
-
* We check both undefined and null to
|
|
9268
|
-
* work around https://github.com/ionic-team/stencil/issues/3586.
|
|
9269
|
-
*/
|
|
9270
|
-
if (fill == null) {
|
|
9266
|
+
if (fill === undefined) {
|
|
9271
9267
|
fill = this.inToolbar || this.inListHeader ? 'clear' : 'solid';
|
|
9272
9268
|
}
|
|
9273
9269
|
/**
|
|
@@ -9280,7 +9276,7 @@ class Button {
|
|
|
9280
9276
|
{
|
|
9281
9277
|
type !== 'button' && this.renderHiddenButton();
|
|
9282
9278
|
}
|
|
9283
|
-
return (hAsync(Host, { key: '
|
|
9279
|
+
return (hAsync(Host, { key: 'ed82ea53705523f9afc5f1a9addff44cc6424f27', onClick: this.handleClick, "aria-disabled": disabled ? 'true' : null, class: createColorClasses$1(color, {
|
|
9284
9280
|
[mode]: true,
|
|
9285
9281
|
[buttonType]: true,
|
|
9286
9282
|
[`${buttonType}-${expand}`]: expand !== undefined,
|
|
@@ -9295,7 +9291,7 @@ class Button {
|
|
|
9295
9291
|
'button-disabled': disabled,
|
|
9296
9292
|
'ion-activatable': true,
|
|
9297
9293
|
'ion-focusable': true,
|
|
9298
|
-
}) }, hAsync(TagType, Object.assign({ key: '
|
|
9294
|
+
}) }, hAsync(TagType, Object.assign({ key: 'fadec13053469dd0405bbbc61b70ced568aa4826' }, attrs, { class: "button-native", part: "native", disabled: disabled, onFocus: this.onFocus, onBlur: this.onBlur }, inheritedAttributes), hAsync("span", { key: '6bf0e5144fb1148002e88038522402b789689d2c', class: "button-inner" }, hAsync("slot", { key: '25da0ca155cfa9e2754842c34f4fd09f576ac2d2', name: "icon-only", onSlotchange: this.slotChanged }), hAsync("slot", { key: '51414065bb11953ec9d818f8d9353589bc9072c5', name: "start" }), hAsync("slot", { key: 'c9b5f8842aeabd20628df2f4600f1257ea913d8d' }), hAsync("slot", { key: '478dd3671c7be1909fc84e672f0fa8dfe6082263', name: "end" })), mode === 'md' && hAsync("ion-ripple-effect", { key: 'e1d55f85a55144d743f58a5914cd116cb065fa8c', type: this.rippleType }))));
|
|
9299
9295
|
}
|
|
9300
9296
|
get el() { return getElement(this); }
|
|
9301
9297
|
static get watchers() { return {
|
|
@@ -15229,6 +15225,8 @@ class Grid {
|
|
|
15229
15225
|
}
|
|
15230
15226
|
|
|
15231
15227
|
const TRANSITION = 'all 0.2s ease-in-out';
|
|
15228
|
+
const ROLE_NONE = 'none';
|
|
15229
|
+
const ROLE_BANNER = 'banner';
|
|
15232
15230
|
const cloneElement = (tagName) => {
|
|
15233
15231
|
const getCachedEl = document.querySelector(`${tagName}.ion-cloned-element`);
|
|
15234
15232
|
if (getCachedEl !== null) {
|
|
@@ -15355,6 +15353,7 @@ const setHeaderActive = (headerIndex, active = true) => {
|
|
|
15355
15353
|
const toolbars = headerIndex.toolbars;
|
|
15356
15354
|
const ionTitles = toolbars.map((toolbar) => toolbar.ionTitleEl);
|
|
15357
15355
|
if (active) {
|
|
15356
|
+
headerEl.setAttribute('role', ROLE_BANNER);
|
|
15358
15357
|
headerEl.classList.remove('header-collapse-condense-inactive');
|
|
15359
15358
|
ionTitles.forEach((ionTitle) => {
|
|
15360
15359
|
if (ionTitle) {
|
|
@@ -15363,6 +15362,16 @@ const setHeaderActive = (headerIndex, active = true) => {
|
|
|
15363
15362
|
});
|
|
15364
15363
|
}
|
|
15365
15364
|
else {
|
|
15365
|
+
/**
|
|
15366
|
+
* There can only be one banner landmark per page.
|
|
15367
|
+
* By default, all ion-headers have the banner role.
|
|
15368
|
+
* This causes an accessibility issue when using a
|
|
15369
|
+
* condensed header since there are two ion-headers
|
|
15370
|
+
* on the page at once (active and inactive).
|
|
15371
|
+
* To solve this, the role needs to be toggled
|
|
15372
|
+
* based on which header is active.
|
|
15373
|
+
*/
|
|
15374
|
+
headerEl.setAttribute('role', ROLE_NONE);
|
|
15366
15375
|
headerEl.classList.add('header-collapse-condense-inactive');
|
|
15367
15376
|
/**
|
|
15368
15377
|
* The small title should only be accessed by screen readers
|
|
@@ -15422,8 +15431,32 @@ const handleHeaderFade = (scrollEl, baseEl, condenseHeader) => {
|
|
|
15422
15431
|
});
|
|
15423
15432
|
});
|
|
15424
15433
|
};
|
|
15434
|
+
/**
|
|
15435
|
+
* Get the role type for the ion-header.
|
|
15436
|
+
*
|
|
15437
|
+
* @param isInsideMenu If ion-header is inside ion-menu.
|
|
15438
|
+
* @param isCondensed If ion-header has collapse="condense".
|
|
15439
|
+
* @param mode The current mode.
|
|
15440
|
+
* @returns 'none' if inside ion-menu or if condensed in md
|
|
15441
|
+
* mode, otherwise 'banner'.
|
|
15442
|
+
*/
|
|
15443
|
+
const getRoleType = (isInsideMenu, isCondensed, mode) => {
|
|
15444
|
+
// If the header is inside a menu, it should not have the banner role.
|
|
15445
|
+
if (isInsideMenu) {
|
|
15446
|
+
return ROLE_NONE;
|
|
15447
|
+
}
|
|
15448
|
+
/**
|
|
15449
|
+
* Only apply role="none" to `md` mode condensed headers
|
|
15450
|
+
* since the large header is never shown.
|
|
15451
|
+
*/
|
|
15452
|
+
if (isCondensed && mode === 'md') {
|
|
15453
|
+
return ROLE_NONE;
|
|
15454
|
+
}
|
|
15455
|
+
// Default to banner role.
|
|
15456
|
+
return ROLE_BANNER;
|
|
15457
|
+
};
|
|
15425
15458
|
|
|
15426
|
-
const headerIosCss = "ion-header{display:block;position:relative;-ms-flex-order:-1;order:-1;width:100%;z-index:10}ion-header ion-toolbar:first-of-type{padding-top:var(--ion-safe-area-top, 0)}.header-ios ion-toolbar:last-of-type{--border-width:0 0 0.55px}@supports ((-webkit-backdrop-filter: blur(0)) or (backdrop-filter: blur(0))){.header-background{left:0;right:0;top:0;bottom:0;position:absolute;-webkit-backdrop-filter:saturate(180%) blur(20px);backdrop-filter:saturate(180%) blur(20px)}.header-translucent-ios ion-toolbar{--opacity:.8}.header-collapse-condense-inactive .header-background{-webkit-backdrop-filter:blur(20px);backdrop-filter:blur(20px)}}.header-ios.ion-no-border ion-toolbar:last-of-type{--border-width:0}.header-collapse-fade ion-toolbar{--opacity-scale:inherit}.header-collapse-condense{z-index:9}.header-collapse-condense ion-toolbar{position:-webkit-sticky;position:sticky;top:0}.header-collapse-condense ion-toolbar:first-of-type{padding-top:0px;z-index:1}.header-collapse-condense ion-toolbar{
|
|
15459
|
+
const headerIosCss = "ion-header{display:block;position:relative;-ms-flex-order:-1;order:-1;width:100%;z-index:10}ion-header ion-toolbar:first-of-type{padding-top:var(--ion-safe-area-top, 0)}.header-ios ion-toolbar:last-of-type{--border-width:0 0 0.55px}@supports ((-webkit-backdrop-filter: blur(0)) or (backdrop-filter: blur(0))){.header-background{left:0;right:0;top:0;bottom:0;position:absolute;-webkit-backdrop-filter:saturate(180%) blur(20px);backdrop-filter:saturate(180%) blur(20px)}.header-translucent-ios ion-toolbar{--opacity:.8}.header-collapse-condense-inactive .header-background{-webkit-backdrop-filter:blur(20px);backdrop-filter:blur(20px)}}.header-ios.ion-no-border ion-toolbar:last-of-type{--border-width:0}.header-collapse-fade ion-toolbar{--opacity-scale:inherit}.header-collapse-fade.header-transitioning ion-toolbar{--background:transparent;--border-style:none}.header-collapse-condense{z-index:9}.header-collapse-condense ion-toolbar{position:-webkit-sticky;position:sticky;top:0}.header-collapse-condense ion-toolbar:first-of-type{padding-top:0px;z-index:1}.header-collapse-condense ion-toolbar{z-index:0}.header-collapse-condense ion-toolbar:last-of-type{--border-width:0px}.header-collapse-condense ion-toolbar ion-searchbar{padding-top:0px;padding-bottom:13px}.header-collapse-main{--opacity-scale:1}.header-collapse-main ion-toolbar{--opacity-scale:inherit}.header-collapse-main ion-toolbar.in-toolbar ion-title,.header-collapse-main ion-toolbar.in-toolbar ion-buttons{-webkit-transition:all 0.2s ease-in-out;transition:all 0.2s ease-in-out}.header-collapse-condense ion-toolbar,.header-collapse-condense-inactive.header-transitioning:not(.header-collapse-condense) ion-toolbar{--background:var(--ion-background-color, #fff)}.header-collapse-condense-inactive.header-transitioning:not(.header-collapse-condense) ion-toolbar{--border-style:none;--opacity-scale:1}.header-collapse-condense-inactive:not(.header-collapse-condense) ion-toolbar.in-toolbar ion-title,.header-collapse-condense-inactive:not(.header-collapse-condense) ion-toolbar.in-toolbar ion-buttons.buttons-collapse{opacity:0;pointer-events:none}.header-collapse-condense-inactive.header-collapse-condense ion-toolbar.in-toolbar ion-title,.header-collapse-condense-inactive.header-collapse-condense ion-toolbar.in-toolbar ion-buttons.buttons-collapse{visibility:hidden}ion-header.header-ios:not(.header-collapse-main):has(~ion-content ion-header.header-ios[collapse=condense],~ion-content ion-header.header-ios.header-collapse-condense){opacity:0}";
|
|
15427
15460
|
|
|
15428
15461
|
const headerMdCss = "ion-header{display:block;position:relative;-ms-flex-order:-1;order:-1;width:100%;z-index:10}ion-header ion-toolbar:first-of-type{padding-top:var(--ion-safe-area-top, 0)}.header-md{-webkit-box-shadow:0 2px 4px -1px rgba(0, 0, 0, 0.2), 0 4px 5px 0 rgba(0, 0, 0, 0.14), 0 1px 10px 0 rgba(0, 0, 0, 0.12);box-shadow:0 2px 4px -1px rgba(0, 0, 0, 0.2), 0 4px 5px 0 rgba(0, 0, 0, 0.14), 0 1px 10px 0 rgba(0, 0, 0, 0.12)}.header-collapse-condense{display:none}.header-md.ion-no-border{-webkit-box-shadow:none;box-shadow:none}";
|
|
15429
15462
|
|
|
@@ -15566,16 +15599,17 @@ class Header {
|
|
|
15566
15599
|
const { translucent, inheritedAttributes } = this;
|
|
15567
15600
|
const mode = getIonMode$1(this);
|
|
15568
15601
|
const collapse = this.collapse || 'none';
|
|
15602
|
+
const isCondensed = collapse === 'condense';
|
|
15569
15603
|
// banner role must be at top level, so remove role if inside a menu
|
|
15570
|
-
const roleType = hostContext('ion-menu', this.el)
|
|
15571
|
-
return (hAsync(Host, Object.assign({ key: '
|
|
15604
|
+
const roleType = getRoleType(hostContext('ion-menu', this.el), isCondensed, mode);
|
|
15605
|
+
return (hAsync(Host, Object.assign({ key: '863c4568cd7b8c0ec55109f193bbbaed68a1346e', role: roleType, class: {
|
|
15572
15606
|
[mode]: true,
|
|
15573
15607
|
// Used internally for styling
|
|
15574
15608
|
[`header-${mode}`]: true,
|
|
15575
15609
|
[`header-translucent`]: this.translucent,
|
|
15576
15610
|
[`header-collapse-${collapse}`]: true,
|
|
15577
15611
|
[`header-translucent-${mode}`]: this.translucent,
|
|
15578
|
-
} }, inheritedAttributes), mode === 'ios' && translucent && hAsync("div", { key: '
|
|
15612
|
+
} }, inheritedAttributes), mode === 'ios' && translucent && hAsync("div", { key: '25c3bdce328b0b35607d154c8b8374679313d881', class: "header-background" }), hAsync("slot", { key: 'b44fab0a9be7920b9650da26117c783e751e1702' })));
|
|
15579
15613
|
}
|
|
15580
15614
|
get el() { return getElement(this); }
|
|
15581
15615
|
static get style() { return {
|
|
@@ -16387,6 +16421,19 @@ const isOptionSelected = (currentValue, compareValue, compareWith) => {
|
|
|
16387
16421
|
}
|
|
16388
16422
|
};
|
|
16389
16423
|
|
|
16424
|
+
/**
|
|
16425
|
+
* Checks if the form element is in an invalid state based on
|
|
16426
|
+
* Ionic validation classes.
|
|
16427
|
+
*
|
|
16428
|
+
* @param el The form element to check.
|
|
16429
|
+
* @returns `true` if the element is invalid, `false` otherwise.
|
|
16430
|
+
*/
|
|
16431
|
+
const checkInvalidState = (el) => {
|
|
16432
|
+
const hasIonTouched = el.classList.contains('ion-touched');
|
|
16433
|
+
const hasIonInvalid = el.classList.contains('ion-invalid');
|
|
16434
|
+
return hasIonTouched && hasIonInvalid;
|
|
16435
|
+
};
|
|
16436
|
+
|
|
16390
16437
|
/**
|
|
16391
16438
|
* Used to update a scoped component that uses emulated slots. This fires when
|
|
16392
16439
|
* content is passed into the slot or when the content inside of a slot changes.
|
|
@@ -16752,20 +16799,12 @@ class Input {
|
|
|
16752
16799
|
componentWillLoad() {
|
|
16753
16800
|
this.inheritedAttributes = Object.assign(Object.assign({}, inheritAriaAttributes(this.el)), inheritAttributes$1(this.el, ['tabindex', 'title', 'data-form-type', 'dir']));
|
|
16754
16801
|
}
|
|
16755
|
-
/**
|
|
16756
|
-
* Checks if the input is in an invalid state based on Ionic validation classes
|
|
16757
|
-
*/
|
|
16758
|
-
checkInvalidState() {
|
|
16759
|
-
const hasIonTouched = this.el.classList.contains('ion-touched');
|
|
16760
|
-
const hasIonInvalid = this.el.classList.contains('ion-invalid');
|
|
16761
|
-
return hasIonTouched && hasIonInvalid;
|
|
16762
|
-
}
|
|
16763
16802
|
connectedCallback() {
|
|
16764
16803
|
const { el } = this;
|
|
16765
16804
|
this.slotMutationController = createSlotMutationController(el, ['label', 'start', 'end'], () => forceUpdate());
|
|
16766
16805
|
this.notchController = createNotchController(el, () => this.notchSpacerEl, () => this.labelSlot);
|
|
16767
16806
|
// Always set initial state
|
|
16768
|
-
this.isInvalid =
|
|
16807
|
+
this.isInvalid = checkInvalidState(el);
|
|
16769
16808
|
this.debounceChanged();
|
|
16770
16809
|
}
|
|
16771
16810
|
componentDidLoad() {
|
|
@@ -17019,7 +17058,7 @@ class Input {
|
|
|
17019
17058
|
* TODO(FW-5592): Remove hasStartEndSlots condition
|
|
17020
17059
|
*/
|
|
17021
17060
|
const labelShouldFloat = labelPlacement === 'stacked' || (labelPlacement === 'floating' && (hasValue || hasFocus || hasStartEndSlots));
|
|
17022
|
-
return (hAsync(Host, { key: '
|
|
17061
|
+
return (hAsync(Host, { key: '97b5308021064d9e7434ef2d3d96f27045c1b0c4', class: createColorClasses$1(this.color, {
|
|
17023
17062
|
[mode]: true,
|
|
17024
17063
|
'has-value': hasValue,
|
|
17025
17064
|
'has-focus': hasFocus,
|
|
@@ -17030,14 +17069,14 @@ class Input {
|
|
|
17030
17069
|
'in-item': inItem,
|
|
17031
17070
|
'in-item-color': hostContext('ion-item.ion-color', this.el),
|
|
17032
17071
|
'input-disabled': disabled,
|
|
17033
|
-
}) }, hAsync("label", { key: '
|
|
17072
|
+
}) }, hAsync("label", { key: '353f68726ce180299bd9adc81e5ff7d26a48f54f', class: "input-wrapper", htmlFor: inputId, onClick: this.onLabelClick }, this.renderLabelContainer(), hAsync("div", { key: '2034b4bad04fc157f3298a1805819216b6f439d0', class: "native-wrapper", onClick: this.onLabelClick }, hAsync("slot", { key: '96bb5e30176b2bd76dfb75bfbf6c1c3d4403f4bb', name: "start" }), hAsync("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 && (hAsync("button", { key: '95f3df17b7691d9a2e7dcd4a51f16a94aa3ca36f', "aria-label": "reset", type: "button", class: "input-clear-icon", onPointerDown: (ev) => {
|
|
17034
17073
|
/**
|
|
17035
17074
|
* This prevents mobile browsers from
|
|
17036
17075
|
* blurring the input when the clear
|
|
17037
17076
|
* button is activated.
|
|
17038
17077
|
*/
|
|
17039
17078
|
ev.preventDefault();
|
|
17040
|
-
}, onClick: this.clearTextInput }, hAsync("ion-icon", { key: '
|
|
17079
|
+
}, onClick: this.clearTextInput }, hAsync("ion-icon", { key: '16b0af75eed50c8115fb5597f73b5fbf71c2530e', "aria-hidden": "true", icon: clearIconData }))), hAsync("slot", { key: 'c48da0f8ddb3764ac43efa705bb4a6bb2d9cc2fd', name: "end" })), shouldRenderHighlight && hAsync("div", { key: 'f15238481fc20de56ca7ecb6e350b3c024cc755e', class: "input-highlight" })), this.renderBottomContent()));
|
|
17041
17080
|
}
|
|
17042
17081
|
get el() { return getElement(this); }
|
|
17043
17082
|
static get watchers() { return {
|
|
@@ -20676,11 +20715,22 @@ const iosTransitionAnimation$1 = () => Promise.resolve().then(function () { retu
|
|
|
20676
20715
|
const mdTransitionAnimation$1 = () => Promise.resolve().then(function () { return md_transition; });
|
|
20677
20716
|
const focusController = createFocusController();
|
|
20678
20717
|
// TODO(FW-2832): types
|
|
20718
|
+
/**
|
|
20719
|
+
* Executes the main page transition.
|
|
20720
|
+
* It also manages the lifecycle of header visibility (if any)
|
|
20721
|
+
* to prevent visual flickering in iOS. The flickering only
|
|
20722
|
+
* occurs for a condensed header that is placed above the content.
|
|
20723
|
+
*
|
|
20724
|
+
* @param opts Options for the transition.
|
|
20725
|
+
* @returns A promise that resolves when the transition is complete.
|
|
20726
|
+
*/
|
|
20679
20727
|
const transition = (opts) => {
|
|
20680
20728
|
return new Promise((resolve, reject) => {
|
|
20681
20729
|
writeTask(() => {
|
|
20682
|
-
|
|
20683
|
-
|
|
20730
|
+
const transitioningInactiveHeader = getIosIonHeader(opts);
|
|
20731
|
+
beforeTransition(opts, transitioningInactiveHeader);
|
|
20732
|
+
runTransition(opts)
|
|
20733
|
+
.then((result) => {
|
|
20684
20734
|
if (result.animation) {
|
|
20685
20735
|
result.animation.destroy();
|
|
20686
20736
|
}
|
|
@@ -20689,15 +20739,21 @@ const transition = (opts) => {
|
|
|
20689
20739
|
}, (error) => {
|
|
20690
20740
|
afterTransition(opts);
|
|
20691
20741
|
reject(error);
|
|
20742
|
+
})
|
|
20743
|
+
.finally(() => {
|
|
20744
|
+
// Ensure that the header is restored to its original state.
|
|
20745
|
+
setHeaderTransitionClass(transitioningInactiveHeader, false);
|
|
20692
20746
|
});
|
|
20693
20747
|
});
|
|
20694
20748
|
});
|
|
20695
20749
|
};
|
|
20696
|
-
const beforeTransition = (opts) => {
|
|
20750
|
+
const beforeTransition = (opts, transitioningInactiveHeader) => {
|
|
20697
20751
|
const enteringEl = opts.enteringEl;
|
|
20698
20752
|
const leavingEl = opts.leavingEl;
|
|
20699
20753
|
focusController.saveViewFocus(leavingEl);
|
|
20700
20754
|
setZIndex(enteringEl, leavingEl, opts.direction);
|
|
20755
|
+
// Prevent flickering of the header by adding a class.
|
|
20756
|
+
setHeaderTransitionClass(transitioningInactiveHeader, true);
|
|
20701
20757
|
if (opts.showGoBack) {
|
|
20702
20758
|
enteringEl.classList.add('can-go-back');
|
|
20703
20759
|
}
|
|
@@ -20886,6 +20942,39 @@ const setZIndex = (enteringEl, leavingEl, direction) => {
|
|
|
20886
20942
|
leavingEl.style.zIndex = '100';
|
|
20887
20943
|
}
|
|
20888
20944
|
};
|
|
20945
|
+
/**
|
|
20946
|
+
* Add a class to ensure that the header (if any)
|
|
20947
|
+
* does not flicker during the transition. By adding the
|
|
20948
|
+
* transitioning class, we ensure that the header has
|
|
20949
|
+
* the necessary styles to prevent the following flickers:
|
|
20950
|
+
* 1. When entering a page with a condensed header, the
|
|
20951
|
+
* header should never be visible. However,
|
|
20952
|
+
* it briefly renders the background color while
|
|
20953
|
+
* the transition is occurring.
|
|
20954
|
+
* 2. When leaving a page with a condensed header, the
|
|
20955
|
+
* header has an opacity of 0 and the pages
|
|
20956
|
+
* have a z-index which causes the entering page to
|
|
20957
|
+
* briefly show it's content underneath the leaving page.
|
|
20958
|
+
* 3. When entering a page or leaving a page with a fade
|
|
20959
|
+
* header, the header should not have a background color.
|
|
20960
|
+
* However, it briefly shows the background color while
|
|
20961
|
+
* the transition is occurring.
|
|
20962
|
+
*
|
|
20963
|
+
* @param header The header element to modify.
|
|
20964
|
+
* @param isTransitioning Whether the transition is occurring.
|
|
20965
|
+
*/
|
|
20966
|
+
const setHeaderTransitionClass = (header, isTransitioning) => {
|
|
20967
|
+
if (!header) {
|
|
20968
|
+
return;
|
|
20969
|
+
}
|
|
20970
|
+
const transitionClass = 'header-transitioning';
|
|
20971
|
+
if (isTransitioning) {
|
|
20972
|
+
header.classList.add(transitionClass);
|
|
20973
|
+
}
|
|
20974
|
+
else {
|
|
20975
|
+
header.classList.remove(transitionClass);
|
|
20976
|
+
}
|
|
20977
|
+
};
|
|
20889
20978
|
const getIonPageElement = (element) => {
|
|
20890
20979
|
if (element.classList.contains('ion-page')) {
|
|
20891
20980
|
return element;
|
|
@@ -20897,6 +20986,27 @@ const getIonPageElement = (element) => {
|
|
|
20897
20986
|
// idk, return the original element so at least something animates and we don't have a null pointer
|
|
20898
20987
|
return element;
|
|
20899
20988
|
};
|
|
20989
|
+
/**
|
|
20990
|
+
* Retrieves the ion-header element from a page based on the
|
|
20991
|
+
* direction of the transition.
|
|
20992
|
+
*
|
|
20993
|
+
* @param opts Options for the transition.
|
|
20994
|
+
* @returns The ion-header element or null if not found or not in 'ios' mode.
|
|
20995
|
+
*/
|
|
20996
|
+
const getIosIonHeader = (opts) => {
|
|
20997
|
+
const enteringEl = opts.enteringEl;
|
|
20998
|
+
const leavingEl = opts.leavingEl;
|
|
20999
|
+
const direction = opts.direction;
|
|
21000
|
+
const mode = opts.mode;
|
|
21001
|
+
if (mode !== 'ios') {
|
|
21002
|
+
return null;
|
|
21003
|
+
}
|
|
21004
|
+
const element = direction === 'back' ? leavingEl : enteringEl;
|
|
21005
|
+
if (!element) {
|
|
21006
|
+
return null;
|
|
21007
|
+
}
|
|
21008
|
+
return element.querySelector('ion-header');
|
|
21009
|
+
};
|
|
20900
21010
|
|
|
20901
21011
|
const KEYBOARD_DID_OPEN = 'ionKeyboardDidShow';
|
|
20902
21012
|
|
|
@@ -33058,6 +33168,10 @@ class Select {
|
|
|
33058
33168
|
* is applied in both cases.
|
|
33059
33169
|
*/
|
|
33060
33170
|
this.hasFocus = false;
|
|
33171
|
+
/**
|
|
33172
|
+
* Track validation state for proper aria-live announcements.
|
|
33173
|
+
*/
|
|
33174
|
+
this.isInvalid = false;
|
|
33061
33175
|
/**
|
|
33062
33176
|
* The text to display on the cancel button.
|
|
33063
33177
|
*/
|
|
@@ -33180,9 +33294,12 @@ class Select {
|
|
|
33180
33294
|
this.mutationO = watchForOptions(this.el, 'ion-select-option', async () => {
|
|
33181
33295
|
this.updateOverlayOptions();
|
|
33182
33296
|
});
|
|
33297
|
+
// Always set initial state
|
|
33298
|
+
this.isInvalid = checkInvalidState(this.el);
|
|
33183
33299
|
}
|
|
33184
33300
|
componentWillLoad() {
|
|
33185
33301
|
this.inheritedAttributes = inheritAttributes$1(this.el, ['aria-label']);
|
|
33302
|
+
this.hintTextID = this.getHintTextID();
|
|
33186
33303
|
}
|
|
33187
33304
|
componentDidLoad() {
|
|
33188
33305
|
/**
|
|
@@ -33206,6 +33323,11 @@ class Select {
|
|
|
33206
33323
|
this.notchController.destroy();
|
|
33207
33324
|
this.notchController = undefined;
|
|
33208
33325
|
}
|
|
33326
|
+
// Clean up validation observer to prevent memory leaks.
|
|
33327
|
+
if (this.validationObserver) {
|
|
33328
|
+
this.validationObserver.disconnect();
|
|
33329
|
+
this.validationObserver = undefined;
|
|
33330
|
+
}
|
|
33209
33331
|
}
|
|
33210
33332
|
/**
|
|
33211
33333
|
* Open the select overlay. The overlay is either an alert, action sheet, or popover,
|
|
@@ -33676,11 +33798,11 @@ class Select {
|
|
|
33676
33798
|
}
|
|
33677
33799
|
renderListbox() {
|
|
33678
33800
|
const { disabled, inputId, isExpanded, required } = this;
|
|
33679
|
-
return (hAsync("button", { disabled: disabled, id: inputId, "aria-label": this.ariaLabel, "aria-haspopup": "dialog", "aria-expanded": `${isExpanded}`, "aria-describedby": this.
|
|
33801
|
+
return (hAsync("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) }));
|
|
33680
33802
|
}
|
|
33681
33803
|
getHintTextID() {
|
|
33682
|
-
const {
|
|
33683
|
-
if (
|
|
33804
|
+
const { helperText, errorText, helperTextId, errorTextId, isInvalid } = this;
|
|
33805
|
+
if (isInvalid && errorText) {
|
|
33684
33806
|
return errorTextId;
|
|
33685
33807
|
}
|
|
33686
33808
|
if (helperText) {
|
|
@@ -33692,10 +33814,10 @@ class Select {
|
|
|
33692
33814
|
* Renders the helper text or error text values
|
|
33693
33815
|
*/
|
|
33694
33816
|
renderHintText() {
|
|
33695
|
-
const { helperText, errorText, helperTextId, errorTextId } = this;
|
|
33817
|
+
const { helperText, errorText, helperTextId, errorTextId, isInvalid } = this;
|
|
33696
33818
|
return [
|
|
33697
|
-
hAsync("div", { id: helperTextId, class: "helper-text", part: "supporting-text helper-text" }, helperText),
|
|
33698
|
-
hAsync("div", { id: errorTextId, class: "error-text", part: "supporting-text error-text" }, errorText),
|
|
33819
|
+
hAsync("div", { id: helperTextId, class: "helper-text", part: "supporting-text helper-text", "aria-live": "polite" }, !isInvalid ? helperText : null),
|
|
33820
|
+
hAsync("div", { id: errorTextId, class: "error-text", part: "supporting-text error-text", role: "alert" }, isInvalid ? errorText : null),
|
|
33699
33821
|
];
|
|
33700
33822
|
}
|
|
33701
33823
|
/**
|
|
@@ -33743,7 +33865,7 @@ class Select {
|
|
|
33743
33865
|
* TODO(FW-5592): Remove hasStartEndSlots condition
|
|
33744
33866
|
*/
|
|
33745
33867
|
const labelShouldFloat = labelPlacement === 'stacked' || (labelPlacement === 'floating' && (hasValue || isExpanded || hasStartEndSlots));
|
|
33746
|
-
return (hAsync(Host, { key: '
|
|
33868
|
+
return (hAsync(Host, { key: '35b5e18e6f79a802ff2d46d1242e80ff755cc0b9', onClick: this.onClick, class: createColorClasses$1(this.color, {
|
|
33747
33869
|
[mode]: true,
|
|
33748
33870
|
'in-item': inItem,
|
|
33749
33871
|
'in-item-color': hostContext('ion-item.ion-color', el),
|
|
@@ -33761,7 +33883,7 @@ class Select {
|
|
|
33761
33883
|
[`select-justify-${justify}`]: justifyEnabled,
|
|
33762
33884
|
[`select-shape-${shape}`]: shape !== undefined,
|
|
33763
33885
|
[`select-label-placement-${labelPlacement}`]: true,
|
|
33764
|
-
}) }, hAsync("label", { key: '
|
|
33886
|
+
}) }, hAsync("label", { key: '6005b34a0c50bc4d7653a4276bc232ecd02e083c', class: "select-wrapper", id: "select-label", onClick: this.onLabelClick }, this.renderLabelContainer(), hAsync("div", { key: 'c7e07aa81ae856c057f16275dd058f37c5670a47', class: "select-wrapper-inner" }, hAsync("slot", { key: '7fc2deefe0424404caacdbbd9e08ed43ba55d28a', name: "start" }), hAsync("div", { key: '157d74ee717b1bc30b5f1c233a09b0c8456aa68e', class: "native-wrapper", ref: (el) => (this.nativeWrapperEl = el), part: "container" }, this.renderSelectText(), this.renderListbox()), hAsync("slot", { key: 'ea66db304528b82bf9317730b6dce3db2612f235', name: "end" }), !hasFloatingOrStackedLabel && this.renderSelectIcon()), hasFloatingOrStackedLabel && this.renderSelectIcon(), shouldRenderHighlight && hAsync("div", { key: '786eb1530b7476f0615d4e7c0bf4e7e4dc66509c', class: "select-highlight" })), this.renderBottomContent()));
|
|
33765
33887
|
}
|
|
33766
33888
|
get el() { return getElement(this); }
|
|
33767
33889
|
static get watchers() { return {
|
|
@@ -33802,6 +33924,8 @@ class Select {
|
|
|
33802
33924
|
"required": [4],
|
|
33803
33925
|
"isExpanded": [32],
|
|
33804
33926
|
"hasFocus": [32],
|
|
33927
|
+
"isInvalid": [32],
|
|
33928
|
+
"hintTextID": [32],
|
|
33805
33929
|
"open": [64]
|
|
33806
33930
|
},
|
|
33807
33931
|
"$listeners$": undefined,
|
|
@@ -34989,20 +35113,12 @@ class Textarea {
|
|
|
34989
35113
|
this.el.click();
|
|
34990
35114
|
}
|
|
34991
35115
|
}
|
|
34992
|
-
/**
|
|
34993
|
-
* Checks if the textarea is in an invalid state based on Ionic validation classes
|
|
34994
|
-
*/
|
|
34995
|
-
checkValidationState() {
|
|
34996
|
-
const hasIonTouched = this.el.classList.contains('ion-touched');
|
|
34997
|
-
const hasIonInvalid = this.el.classList.contains('ion-invalid');
|
|
34998
|
-
return hasIonTouched && hasIonInvalid;
|
|
34999
|
-
}
|
|
35000
35116
|
connectedCallback() {
|
|
35001
35117
|
const { el } = this;
|
|
35002
35118
|
this.slotMutationController = createSlotMutationController(el, ['label', 'start', 'end'], () => forceUpdate());
|
|
35003
35119
|
this.notchController = createNotchController(el, () => this.notchSpacerEl, () => this.labelSlot);
|
|
35004
35120
|
// Always set initial state
|
|
35005
|
-
this.isInvalid = this.
|
|
35121
|
+
this.isInvalid = checkInvalidState(this.el);
|
|
35006
35122
|
this.debounceChanged();
|
|
35007
35123
|
}
|
|
35008
35124
|
disconnectedCallback() {
|
|
@@ -35256,7 +35372,7 @@ class Textarea {
|
|
|
35256
35372
|
* TODO(FW-5592): Remove hasStartEndSlots condition
|
|
35257
35373
|
*/
|
|
35258
35374
|
const labelShouldFloat = labelPlacement === 'stacked' || (labelPlacement === 'floating' && (hasValue || hasFocus || hasStartEndSlots));
|
|
35259
|
-
return (hAsync(Host, { key: '
|
|
35375
|
+
return (hAsync(Host, { key: 'a70a62d7aae3831a50acd74f60b930925ada1326', class: createColorClasses$1(this.color, {
|
|
35260
35376
|
[mode]: true,
|
|
35261
35377
|
'has-value': hasValue,
|
|
35262
35378
|
'has-focus': hasFocus,
|
|
@@ -35265,7 +35381,7 @@ class Textarea {
|
|
|
35265
35381
|
[`textarea-shape-${shape}`]: shape !== undefined,
|
|
35266
35382
|
[`textarea-label-placement-${labelPlacement}`]: true,
|
|
35267
35383
|
'textarea-disabled': disabled,
|
|
35268
|
-
}) }, hAsync("label", { key: '
|
|
35384
|
+
}) }, hAsync("label", { key: '8a2dd59a60f7469df84018eb0ede3a9ec3862703', class: "textarea-wrapper", htmlFor: inputId, onClick: this.onLabelClick }, this.renderLabelContainer(), hAsync("div", { key: '1bfc368236e3da7a225a45118c27fbfc1fe5fa46', class: "textarea-wrapper-inner" }, hAsync("div", { key: '215cbb2635ff52e31a8973376989b85e7245d40f', class: "start-slot-wrapper" }, hAsync("slot", { key: '9f6b461cdee9d629deb695d2bea054ece2f32305', name: "start" })), hAsync("div", { key: 'c1af35a2d5bc452bebe0b22a26d15ff52b4e9fc8', class: "native-wrapper", ref: (el) => (this.textareaWrapper = el) }, hAsync("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)), hAsync("div", { key: 'c053ea8b865d0e29763aed2e4939cc9c9e374c15', class: "end-slot-wrapper" }, hAsync("slot", { key: '930aa641833b0df54b9ea10368fc2f46d5f491f6', name: "end" }))), shouldRenderHighlight && hAsync("div", { key: '8d12597d15f5f429d80e8272ea99e64ed924e482', class: "textarea-highlight" })), this.renderBottomContent()));
|
|
35269
35385
|
}
|
|
35270
35386
|
get el() { return getElement(this); }
|
|
35271
35387
|
static get watchers() { return {
|