voyager-ionic-core 8.7.6 → 8.7.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/components/button.js +3 -7
- package/components/checkbox.js +64 -13
- package/components/header.js +42 -4
- package/components/index2.js +74 -3
- package/components/ion-accordion.js +93 -14
- package/components/ion-datetime.js +35 -2
- package/components/ion-input.js +6 -13
- package/components/ion-select.js +59 -10
- package/components/ion-textarea.js +5 -12
- package/components/ion-toggle.js +63 -16
- package/components/radio-group.js +60 -7
- package/components/validity.js +17 -0
- package/dist/cjs/{index-CD5Rjp23.js → index-094mMFB-.js} +76 -5
- package/dist/cjs/index.cjs.js +3 -3
- package/dist/cjs/ion-accordion_2.cjs.entry.js +91 -13
- package/dist/cjs/ion-app_8.cjs.entry.js +43 -5
- package/dist/cjs/ion-button_2.cjs.entry.js +3 -7
- package/dist/cjs/ion-checkbox.cjs.entry.js +61 -12
- package/dist/cjs/ion-datetime_3.cjs.entry.js +35 -2
- package/dist/cjs/ion-input.cjs.entry.js +6 -13
- package/dist/cjs/ion-modal.cjs.entry.js +1 -1
- package/dist/cjs/ion-nav_2.cjs.entry.js +1 -1
- package/dist/cjs/ion-popover.cjs.entry.js +1 -1
- package/dist/cjs/ion-radio_2.cjs.entry.js +57 -6
- package/dist/cjs/ion-select_3.cjs.entry.js +56 -9
- package/dist/cjs/ion-textarea.cjs.entry.js +5 -12
- package/dist/cjs/ion-toggle.cjs.entry.js +59 -14
- package/dist/cjs/ionic.cjs.js +1 -1
- package/dist/cjs/{ios.transition-j9CclgEW.js → ios.transition-BOt_uW73.js} +1 -1
- package/dist/cjs/loader.cjs.js +1 -1
- package/dist/cjs/{md.transition-CwFyRSfv.js → md.transition-Dt968VXB.js} +1 -1
- package/dist/cjs/validity-BpS37YFM.js +19 -0
- package/dist/collection/components/accordion/accordion.js +93 -14
- package/dist/collection/components/button/button.js +3 -7
- package/dist/collection/components/checkbox/checkbox.js +68 -13
- package/dist/collection/components/datetime/datetime.js +35 -2
- package/dist/collection/components/header/header.ios.css +27 -1
- package/dist/collection/components/header/header.js +5 -4
- package/dist/collection/components/header/header.utils.js +37 -0
- package/dist/collection/components/input/input.js +6 -14
- package/dist/collection/components/radio-group/radio-group.js +64 -7
- package/dist/collection/components/select/select.js +60 -12
- package/dist/collection/components/textarea/textarea.js +5 -13
- package/dist/collection/components/toggle/toggle.js +63 -16
- package/dist/collection/utils/forms/index.js +1 -0
- package/dist/collection/utils/forms/validity.js +15 -0
- package/dist/collection/utils/test/playwright/page/utils/set-content.js +7 -0
- package/dist/collection/utils/test/playwright/page/utils/spy-on-event.js +32 -0
- package/dist/collection/utils/transition/index.js +74 -3
- package/dist/docs.json +1 -1
- package/dist/esm/{index-D6G2seR8.js → index-r2D9DEro.js} +76 -5
- package/dist/esm/index.js +3 -3
- package/dist/esm/ion-accordion_2.entry.js +91 -13
- package/dist/esm/ion-app_8.entry.js +43 -5
- package/dist/esm/ion-button_2.entry.js +3 -7
- package/dist/esm/ion-checkbox.entry.js +61 -12
- package/dist/esm/ion-datetime_3.entry.js +35 -2
- package/dist/esm/ion-input.entry.js +6 -13
- package/dist/esm/ion-modal.entry.js +1 -1
- package/dist/esm/ion-nav_2.entry.js +1 -1
- package/dist/esm/ion-popover.entry.js +1 -1
- package/dist/esm/ion-radio_2.entry.js +57 -6
- package/dist/esm/ion-select_3.entry.js +56 -9
- package/dist/esm/ion-textarea.entry.js +5 -12
- package/dist/esm/ion-toggle.entry.js +59 -14
- package/dist/esm/ionic.js +1 -1
- package/dist/esm/{ios.transition-Bpq9ixwv.js → ios.transition-BDzw0_Hm.js} +1 -1
- package/dist/esm/loader.js +1 -1
- package/dist/esm/{md.transition-zOA0oanq.js → md.transition-BzDYi3qq.js} +1 -1
- package/dist/esm/validity-DJztqcrH.js +17 -0
- package/dist/ionic/index.esm.js +1 -1
- package/dist/ionic/ionic.esm.js +1 -1
- package/dist/ionic/p-40c261a3.entry.js +4 -0
- package/dist/ionic/p-43ed1ef5.entry.js +4 -0
- package/dist/ionic/p-4e41ea20.entry.js +4 -0
- package/dist/ionic/{p-323421af.entry.js → p-5a39a99a.entry.js} +1 -1
- package/dist/ionic/p-5fb517e4.entry.js +4 -0
- package/dist/ionic/p-7380261c.entry.js +4 -0
- package/dist/ionic/{p-9a36e2e7.entry.js → p-95bddd49.entry.js} +1 -1
- package/dist/ionic/{p-DPhQmGJN.js → p-C7hRNDhM.js} +1 -1
- package/dist/ionic/p-DJztqcrH.js +4 -0
- package/dist/ionic/p-DUt5fQmA.js +4 -0
- package/dist/ionic/{p-9R1XyICs.js → p-DZRJwG4S.js} +1 -1
- package/dist/ionic/p-c19f63d0.entry.js +4 -0
- package/dist/ionic/p-cb93126d.entry.js +4 -0
- package/dist/ionic/p-d0a2a1ab.entry.js +4 -0
- package/dist/ionic/p-d1f54e28.entry.js +4 -0
- package/dist/ionic/p-d3014190.entry.js +4 -0
- package/dist/ionic/{p-de7b5fa3.entry.js → p-e16b69e1.entry.js} +1 -1
- package/dist/ionic/svg/checkbox-outline.svg +1 -0
- package/dist/ionic/svg/checkbox-sharp.svg +1 -0
- package/dist/ionic/svg/checkbox.svg +1 -0
- package/dist/ionic/svg/checkmark-circle-outline.svg +1 -0
- package/dist/ionic/svg/checkmark-circle-sharp.svg +1 -0
- package/dist/ionic/svg/checkmark-circle.svg +1 -0
- package/dist/ionic/svg/checkmark-done-circle-outline.svg +1 -0
- package/dist/ionic/svg/checkmark-done-circle-sharp.svg +1 -0
- package/dist/ionic/svg/checkmark-done-circle.svg +1 -0
- package/dist/ionic/svg/checkmark-done-outline.svg +1 -0
- package/dist/ionic/svg/checkmark-done-sharp.svg +1 -0
- package/dist/ionic/svg/checkmark-done.svg +1 -0
- package/dist/ionic/svg/checkmark-outline.svg +1 -0
- package/dist/ionic/svg/checkmark-sharp.svg +1 -0
- package/dist/ionic/svg/checkmark.svg +1 -0
- package/dist/ionic/svg/chevron-back-circle-outline.svg +1 -0
- package/dist/ionic/svg/chevron-back-circle-sharp.svg +1 -0
- package/dist/ionic/svg/chevron-back-circle.svg +1 -0
- package/dist/ionic/svg/chevron-back-outline.svg +1 -0
- package/dist/ionic/svg/chevron-back-sharp.svg +1 -0
- package/dist/ionic/svg/chevron-back.svg +1 -0
- package/dist/ionic/svg/chevron-collapse-outline.svg +1 -0
- package/dist/ionic/svg/chevron-collapse-sharp.svg +1 -0
- package/dist/ionic/svg/chevron-collapse.svg +1 -0
- package/dist/ionic/svg/chevron-down-circle-outline.svg +1 -0
- package/dist/ionic/svg/chevron-down-circle-sharp.svg +1 -0
- package/dist/ionic/svg/chevron-down-circle.svg +1 -0
- package/dist/ionic/svg/chevron-down-outline.svg +1 -0
- package/dist/ionic/svg/chevron-down-sharp.svg +1 -0
- package/dist/ionic/svg/chevron-down.svg +1 -0
- package/dist/ionic/svg/chevron-expand-outline.svg +1 -0
- package/dist/ionic/svg/chevron-expand-sharp.svg +1 -0
- package/dist/ionic/svg/chevron-expand.svg +1 -0
- package/dist/ionic/svg/chevron-forward-circle-outline.svg +1 -0
- package/dist/ionic/svg/chevron-forward-circle-sharp.svg +1 -0
- package/dist/ionic/svg/chevron-forward-circle.svg +1 -0
- package/dist/ionic/svg/chevron-forward-outline.svg +1 -0
- package/dist/ionic/svg/chevron-forward-sharp.svg +1 -0
- package/dist/ionic/svg/chevron-forward.svg +1 -0
- package/dist/ionic/svg/chevron-up-circle-outline.svg +1 -0
- package/dist/ionic/svg/chevron-up-circle-sharp.svg +1 -0
- package/dist/ionic/svg/chevron-up-circle.svg +1 -0
- package/dist/ionic/svg/chevron-up-outline.svg +1 -0
- package/dist/ionic/svg/chevron-up-sharp.svg +1 -0
- package/dist/ionic/svg/chevron-up.svg +1 -0
- package/dist/ionic/svg/clipboard-outline.svg +1 -0
- package/dist/ionic/svg/clipboard-sharp.svg +1 -0
- package/dist/ionic/svg/clipboard.svg +1 -0
- package/dist/ionic/svg/close-circle-outline.svg +1 -0
- package/dist/ionic/svg/close-circle-sharp.svg +1 -0
- package/dist/ionic/svg/close-circle.svg +1 -0
- package/dist/ionic/svg/close-outline.svg +1 -0
- package/dist/ionic/svg/close-sharp.svg +1 -0
- package/dist/ionic/svg/close.svg +1 -0
- package/dist/ionic/svg/cloud-circle-outline.svg +1 -0
- package/dist/ionic/svg/cloud-circle-sharp.svg +1 -0
- package/dist/ionic/svg/cloud-circle.svg +1 -0
- package/dist/ionic/svg/cloud-done-outline.svg +1 -0
- package/dist/ionic/svg/cloud-done-sharp.svg +1 -0
- package/dist/ionic/svg/cloud-done.svg +1 -0
- package/dist/ionic/svg/cloud-download-outline.svg +1 -0
- package/dist/ionic/svg/cloud-download-sharp.svg +1 -0
- package/dist/ionic/svg/cloud-download.svg +1 -0
- package/dist/ionic/svg/cloud-offline-outline.svg +1 -0
- package/dist/ionic/svg/cloud-offline-sharp.svg +1 -0
- package/dist/ionic/svg/cloud-offline.svg +1 -0
- package/dist/ionic/svg/cloud-outline.svg +1 -0
- package/dist/ionic/svg/cloud-sharp.svg +1 -0
- package/dist/ionic/svg/cloud-upload-outline.svg +1 -0
- package/dist/ionic/svg/cloud-upload-sharp.svg +1 -0
- package/dist/ionic/svg/cloud-upload.svg +1 -0
- package/dist/ionic/svg/cloud.svg +1 -0
- package/dist/ionic/svg/cloudy-night-outline.svg +1 -0
- package/dist/ionic/svg/cloudy-night-sharp.svg +1 -0
- package/dist/ionic/svg/cloudy-night.svg +1 -0
- package/dist/ionic/svg/cloudy-outline.svg +1 -0
- package/dist/ionic/svg/cloudy-sharp.svg +1 -0
- package/dist/ionic/svg/cloudy.svg +1 -0
- package/dist/ionic/svg/code-download-outline.svg +1 -0
- package/dist/ionic/svg/code-download-sharp.svg +1 -0
- package/dist/ionic/svg/code-download.svg +1 -0
- package/dist/ionic/svg/code-outline.svg +1 -0
- package/dist/ionic/svg/code-sharp.svg +1 -0
- package/dist/ionic/svg/code-slash-outline.svg +1 -0
- package/dist/ionic/svg/code-slash-sharp.svg +1 -0
- package/dist/ionic/svg/code-slash.svg +1 -0
- package/dist/ionic/svg/code-working-outline.svg +1 -0
- package/dist/ionic/svg/code-working-sharp.svg +1 -0
- package/dist/ionic/svg/code-working.svg +1 -0
- package/dist/ionic/svg/code.svg +1 -0
- package/dist/ionic/svg/cog-outline.svg +1 -0
- package/dist/ionic/svg/cog-sharp.svg +1 -0
- package/dist/ionic/svg/cog.svg +1 -0
- package/dist/ionic/svg/color-fill-outline.svg +1 -0
- package/dist/ionic/svg/color-fill-sharp.svg +1 -0
- package/dist/ionic/svg/color-fill.svg +1 -0
- package/dist/ionic/svg/color-filter-outline.svg +1 -0
- package/dist/ionic/svg/color-filter-sharp.svg +1 -0
- package/dist/ionic/svg/color-filter.svg +1 -0
- package/dist/ionic/svg/color-palette-outline.svg +1 -0
- package/dist/ionic/svg/color-palette-sharp.svg +1 -0
- package/dist/ionic/svg/color-palette.svg +1 -0
- package/dist/ionic/svg/color-wand-outline.svg +1 -0
- package/dist/ionic/svg/color-wand-sharp.svg +1 -0
- package/dist/ionic/svg/color-wand.svg +1 -0
- package/dist/ionic/svg/compass-outline.svg +1 -0
- package/dist/ionic/svg/compass-sharp.svg +1 -0
- package/dist/ionic/svg/compass.svg +1 -0
- package/dist/ionic/svg/construct-outline.svg +1 -0
- package/dist/ionic/svg/construct-sharp.svg +1 -0
- package/dist/ionic/svg/construct.svg +1 -0
- package/dist/ionic/svg/contract-outline.svg +1 -0
- package/dist/ionic/svg/contract-sharp.svg +1 -0
- package/dist/ionic/svg/contract.svg +1 -0
- package/dist/ionic/svg/contrast-outline.svg +1 -0
- package/dist/ionic/svg/contrast-sharp.svg +1 -0
- package/dist/ionic/svg/contrast.svg +1 -0
- package/dist/ionic/svg/copy-outline.svg +1 -0
- package/dist/ionic/svg/copy-sharp.svg +1 -0
- package/dist/ionic/svg/copy.svg +1 -0
- package/dist/ionic/svg/create-outline.svg +1 -0
- package/dist/ionic/svg/create-sharp.svg +1 -0
- package/dist/ionic/svg/create.svg +1 -0
- package/dist/ionic/svg/crop-outline.svg +1 -0
- package/dist/ionic/svg/crop-sharp.svg +1 -0
- package/dist/ionic/svg/crop.svg +1 -0
- package/dist/ionic/svg/cube-outline.svg +1 -0
- package/dist/ionic/svg/cube-sharp.svg +1 -0
- package/dist/ionic/svg/cube.svg +1 -0
- package/dist/ionic/svg/cut-outline.svg +1 -0
- package/dist/ionic/svg/cut-sharp.svg +1 -0
- package/dist/ionic/svg/cut.svg +1 -0
- package/dist/ionic/svg/desktop-outline.svg +1 -0
- package/dist/ionic/svg/desktop-sharp.svg +1 -0
- package/dist/ionic/svg/desktop.svg +1 -0
- package/dist/ionic/svg/diamond-outline.svg +1 -0
- package/dist/ionic/svg/diamond-sharp.svg +1 -0
- package/dist/ionic/svg/diamond.svg +1 -0
- package/dist/ionic/svg/dice-outline.svg +1 -0
- package/dist/ionic/svg/dice-sharp.svg +1 -0
- package/dist/ionic/svg/dice.svg +1 -0
- package/dist/ionic/svg/disc-outline.svg +1 -0
- package/dist/ionic/svg/disc-sharp.svg +1 -0
- package/dist/ionic/svg/disc.svg +1 -0
- package/dist/ionic/svg/document-attach-outline.svg +1 -0
- package/dist/ionic/svg/document-attach-sharp.svg +1 -0
- package/dist/ionic/svg/document-attach.svg +1 -0
- package/dist/ionic/svg/document-lock-outline.svg +1 -0
- package/dist/ionic/svg/document-lock-sharp.svg +1 -0
- package/dist/ionic/svg/document-lock.svg +1 -0
- package/dist/ionic/svg/document-outline.svg +1 -0
- package/dist/types/components/accordion/accordion.d.ts +18 -1
- package/dist/types/components/checkbox/checkbox.d.ts +9 -2
- package/dist/types/components/datetime/datetime.d.ts +10 -0
- package/dist/types/components/header/header.utils.d.ts +10 -0
- package/dist/types/components/input/input.d.ts +0 -4
- package/dist/types/components/radio-group/radio-group.d.ts +9 -1
- package/dist/types/components/select/select.d.ts +7 -1
- package/dist/types/components/textarea/textarea.d.ts +0 -4
- package/dist/types/components/toggle/toggle.d.ts +7 -2
- package/dist/types/utils/forms/index.d.ts +1 -0
- package/dist/types/utils/forms/validity.d.ts +10 -0
- package/dist/types/utils/transition/index.d.ts +9 -0
- package/hydrate/index.js +687 -413
- package/hydrate/index.mjs +687 -413
- package/package.json +4 -4
- package/dist/ionic/p-1c8a476d.entry.js +0 -4
- package/dist/ionic/p-3355a2ff.entry.js +0 -4
- package/dist/ionic/p-4efea47a.entry.js +0 -4
- package/dist/ionic/p-62e50f80.entry.js +0 -4
- package/dist/ionic/p-785026d7.entry.js +0 -4
- package/dist/ionic/p-78c74a3e.entry.js +0 -4
- package/dist/ionic/p-7bcfc421.entry.js +0 -4
- package/dist/ionic/p-83fc84e7.entry.js +0 -4
- package/dist/ionic/p-913a7c1e.entry.js +0 -4
- package/dist/ionic/p-CMhMiYSX.js +0 -4
- package/dist/ionic/p-c17c0a01.entry.js +0 -4
package/components/button.js
CHANGED
|
@@ -219,11 +219,7 @@ const Button = /*@__PURE__*/ proxyCustomElement(class Button extends HTMLElement
|
|
|
219
219
|
target,
|
|
220
220
|
};
|
|
221
221
|
let fill = this.fill;
|
|
222
|
-
|
|
223
|
-
* We check both undefined and null to
|
|
224
|
-
* work around https://github.com/ionic-team/stencil/issues/3586.
|
|
225
|
-
*/
|
|
226
|
-
if (fill == null) {
|
|
222
|
+
if (fill === undefined) {
|
|
227
223
|
fill = this.inToolbar || this.inListHeader ? 'clear' : 'solid';
|
|
228
224
|
}
|
|
229
225
|
/**
|
|
@@ -236,7 +232,7 @@ const Button = /*@__PURE__*/ proxyCustomElement(class Button extends HTMLElement
|
|
|
236
232
|
{
|
|
237
233
|
type !== 'button' && this.renderHiddenButton();
|
|
238
234
|
}
|
|
239
|
-
return (h(Host, { key: '
|
|
235
|
+
return (h(Host, { key: 'ed82ea53705523f9afc5f1a9addff44cc6424f27', onClick: this.handleClick, "aria-disabled": disabled ? 'true' : null, class: createColorClasses(color, {
|
|
240
236
|
[mode]: true,
|
|
241
237
|
[buttonType]: true,
|
|
242
238
|
[`${buttonType}-${expand}`]: expand !== undefined,
|
|
@@ -251,7 +247,7 @@ const Button = /*@__PURE__*/ proxyCustomElement(class Button extends HTMLElement
|
|
|
251
247
|
'button-disabled': disabled,
|
|
252
248
|
'ion-activatable': true,
|
|
253
249
|
'ion-focusable': true,
|
|
254
|
-
}) }, h(TagType, Object.assign({ key: '
|
|
250
|
+
}) }, h(TagType, Object.assign({ key: 'fadec13053469dd0405bbbc61b70ced568aa4826' }, attrs, { class: "button-native", part: "native", disabled: disabled, onFocus: this.onFocus, onBlur: this.onBlur }, inheritedAttributes), h("span", { key: '6bf0e5144fb1148002e88038522402b789689d2c', class: "button-inner" }, h("slot", { key: '25da0ca155cfa9e2754842c34f4fd09f576ac2d2', name: "icon-only", onSlotchange: this.slotChanged }), h("slot", { key: '51414065bb11953ec9d818f8d9353589bc9072c5', name: "start" }), h("slot", { key: 'c9b5f8842aeabd20628df2f4600f1257ea913d8d' }), h("slot", { key: '478dd3671c7be1909fc84e672f0fa8dfe6082263', name: "end" })), mode === 'md' && h("ion-ripple-effect", { key: 'e1d55f85a55144d743f58a5914cd116cb065fa8c', type: this.rippleType }))));
|
|
255
251
|
}
|
|
256
252
|
get el() { return this; }
|
|
257
253
|
static get watchers() { return {
|
package/components/checkbox.js
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
/*!
|
|
2
2
|
* (C) Ionic http://ionicframework.com - MIT License
|
|
3
3
|
*/
|
|
4
|
-
import { proxyCustomElement, HTMLElement, createEvent, h, Host } from '@stencil/core/internal/client';
|
|
4
|
+
import { proxyCustomElement, HTMLElement, createEvent, Build, h, Host } from '@stencil/core/internal/client';
|
|
5
5
|
import { i as inheritAriaAttributes, e as renderHiddenInput } from './helpers.js';
|
|
6
|
+
import { c as checkInvalidState } from './validity.js';
|
|
6
7
|
import { c as createColorClasses, h as hostContext } from './theme.js';
|
|
7
8
|
import { b as getIonMode } from './ionic-global.js';
|
|
8
9
|
|
|
@@ -63,6 +64,10 @@ const Checkbox = /*@__PURE__*/ proxyCustomElement(class Checkbox extends HTMLEle
|
|
|
63
64
|
* submitting if the value is invalid.
|
|
64
65
|
*/
|
|
65
66
|
this.required = false;
|
|
67
|
+
/**
|
|
68
|
+
* Track validation state for proper aria-live announcements.
|
|
69
|
+
*/
|
|
70
|
+
this.isInvalid = false;
|
|
66
71
|
/**
|
|
67
72
|
* Sets the checked property and emits
|
|
68
73
|
* the ionChange event. Use this to update the
|
|
@@ -78,7 +83,6 @@ const Checkbox = /*@__PURE__*/ proxyCustomElement(class Checkbox extends HTMLEle
|
|
|
78
83
|
};
|
|
79
84
|
this.toggleChecked = (ev) => {
|
|
80
85
|
ev.preventDefault();
|
|
81
|
-
this.setFocus();
|
|
82
86
|
this.setChecked(!this.checked);
|
|
83
87
|
this.indeterminate = false;
|
|
84
88
|
};
|
|
@@ -110,18 +114,63 @@ const Checkbox = /*@__PURE__*/ proxyCustomElement(class Checkbox extends HTMLEle
|
|
|
110
114
|
ev.stopPropagation();
|
|
111
115
|
};
|
|
112
116
|
}
|
|
117
|
+
connectedCallback() {
|
|
118
|
+
const { el } = this;
|
|
119
|
+
// Watch for class changes to update validation state.
|
|
120
|
+
if (Build.isBrowser && typeof MutationObserver !== 'undefined') {
|
|
121
|
+
this.validationObserver = new MutationObserver(() => {
|
|
122
|
+
const newIsInvalid = checkInvalidState(el);
|
|
123
|
+
if (this.isInvalid !== newIsInvalid) {
|
|
124
|
+
this.isInvalid = newIsInvalid;
|
|
125
|
+
/**
|
|
126
|
+
* Screen readers tend to announce changes
|
|
127
|
+
* to `aria-describedby` when the attribute
|
|
128
|
+
* is changed during a blur event for a
|
|
129
|
+
* native form control.
|
|
130
|
+
* However, the announcement can be spotty
|
|
131
|
+
* when using a non-native form control
|
|
132
|
+
* and `forceUpdate()`.
|
|
133
|
+
* This is due to `forceUpdate()` internally
|
|
134
|
+
* rescheduling the DOM update to a lower
|
|
135
|
+
* priority queue regardless if it's called
|
|
136
|
+
* inside a Promise or not, thus causing
|
|
137
|
+
* the screen reader to potentially miss the
|
|
138
|
+
* change.
|
|
139
|
+
* By using a State variable inside a Promise,
|
|
140
|
+
* it guarantees a re-render immediately at
|
|
141
|
+
* a higher priority.
|
|
142
|
+
*/
|
|
143
|
+
Promise.resolve().then(() => {
|
|
144
|
+
this.hintTextId = this.getHintTextId();
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
});
|
|
148
|
+
this.validationObserver.observe(el, {
|
|
149
|
+
attributes: true,
|
|
150
|
+
attributeFilter: ['class'],
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
// Always set initial state
|
|
154
|
+
this.isInvalid = checkInvalidState(el);
|
|
155
|
+
}
|
|
113
156
|
componentWillLoad() {
|
|
114
157
|
this.inheritedAttributes = Object.assign({}, inheritAriaAttributes(this.el));
|
|
158
|
+
this.hintTextId = this.getHintTextId();
|
|
159
|
+
}
|
|
160
|
+
disconnectedCallback() {
|
|
161
|
+
// Clean up validation observer to prevent memory leaks.
|
|
162
|
+
if (this.validationObserver) {
|
|
163
|
+
this.validationObserver.disconnect();
|
|
164
|
+
this.validationObserver = undefined;
|
|
165
|
+
}
|
|
115
166
|
}
|
|
116
167
|
/** @internal */
|
|
117
168
|
async setFocus() {
|
|
118
|
-
|
|
119
|
-
this.focusEl.focus();
|
|
120
|
-
}
|
|
169
|
+
this.el.focus();
|
|
121
170
|
}
|
|
122
|
-
|
|
123
|
-
const {
|
|
124
|
-
if (
|
|
171
|
+
getHintTextId() {
|
|
172
|
+
const { helperText, errorText, helperTextId, errorTextId, isInvalid } = this;
|
|
173
|
+
if (isInvalid && errorText) {
|
|
125
174
|
return errorTextId;
|
|
126
175
|
}
|
|
127
176
|
if (helperText) {
|
|
@@ -134,7 +183,7 @@ const Checkbox = /*@__PURE__*/ proxyCustomElement(class Checkbox extends HTMLEle
|
|
|
134
183
|
* This element should only be rendered if hint text is set.
|
|
135
184
|
*/
|
|
136
185
|
renderHintText() {
|
|
137
|
-
const { helperText, errorText, helperTextId, errorTextId } = this;
|
|
186
|
+
const { helperText, errorText, helperTextId, errorTextId, isInvalid } = this;
|
|
138
187
|
/**
|
|
139
188
|
* undefined and empty string values should
|
|
140
189
|
* be treated as not having helper/error text.
|
|
@@ -143,7 +192,7 @@ const Checkbox = /*@__PURE__*/ proxyCustomElement(class Checkbox extends HTMLEle
|
|
|
143
192
|
if (!hasHintText) {
|
|
144
193
|
return;
|
|
145
194
|
}
|
|
146
|
-
return (h("div", { class: "checkbox-bottom" }, h("div", { id: helperTextId, class: "helper-text", part: "supporting-text helper-text" }, helperText), h("div", { id: errorTextId, class: "error-text", part: "supporting-text error-text" }, errorText)));
|
|
195
|
+
return (h("div", { class: "checkbox-bottom" }, h("div", { id: helperTextId, class: "helper-text", part: "supporting-text helper-text", "aria-live": "polite" }, !isInvalid ? helperText : null), h("div", { id: errorTextId, class: "error-text", part: "supporting-text error-text", role: "alert" }, isInvalid ? errorText : null)));
|
|
147
196
|
}
|
|
148
197
|
render() {
|
|
149
198
|
const { color, checked, disabled, el, getSVGPath, indeterminate, inheritedAttributes, inputId, justify, labelPlacement, name, value, alignment, required, } = this;
|
|
@@ -153,7 +202,7 @@ const Checkbox = /*@__PURE__*/ proxyCustomElement(class Checkbox extends HTMLEle
|
|
|
153
202
|
renderHiddenInput(true, el, name, checked ? value : '', disabled);
|
|
154
203
|
// The host element must have a checkbox role to ensure proper VoiceOver
|
|
155
204
|
// support in Safari for accessibility.
|
|
156
|
-
return (h(Host, { key: '
|
|
205
|
+
return (h(Host, { key: 'ae0fbd4b21accbac132e6b85c513512ad9179394', role: "checkbox", "aria-checked": indeterminate ? 'mixed' : `${checked}`, "aria-describedby": this.hintTextId, "aria-invalid": this.isInvalid ? 'true' : undefined, "aria-labelledby": hasLabelContent ? this.inputLabelId : null, "aria-label": inheritedAttributes['aria-label'] || null, "aria-disabled": disabled ? 'true' : null, "aria-required": required ? 'true' : undefined, tabindex: disabled ? undefined : 0, onKeyDown: this.onKeyDown, onFocus: this.onFocus, onBlur: this.onBlur, onClick: this.onClick, class: createColorClasses(color, {
|
|
157
206
|
[mode]: true,
|
|
158
207
|
'in-item': hostContext('ion-item', el),
|
|
159
208
|
'checkbox-checked': checked,
|
|
@@ -163,10 +212,10 @@ const Checkbox = /*@__PURE__*/ proxyCustomElement(class Checkbox extends HTMLEle
|
|
|
163
212
|
[`checkbox-justify-${justify}`]: justify !== undefined,
|
|
164
213
|
[`checkbox-alignment-${alignment}`]: alignment !== undefined,
|
|
165
214
|
[`checkbox-label-placement-${labelPlacement}`]: true,
|
|
166
|
-
})
|
|
215
|
+
}) }, h("label", { key: '7a3d7f3c27dde514f2dbf2e34f4629fad33ec3bf', class: "checkbox-wrapper", htmlFor: inputId }, h("input", Object.assign({ key: '4130d77ddf034271fecccda14e101a5a809921b6', type: "checkbox", checked: checked ? true : undefined, disabled: disabled, id: inputId, onChange: this.toggleChecked, required: required }, inheritedAttributes)), h("div", { key: '5daa74f4e62b0947e37764762524001ee42609d9', class: {
|
|
167
216
|
'label-text-wrapper': true,
|
|
168
217
|
'label-text-wrapper-hidden': !hasLabelContent,
|
|
169
|
-
}, part: "label", id: this.inputLabelId, onClick: this.onDivLabelClick }, h("slot", { key: '
|
|
218
|
+
}, part: "label", id: this.inputLabelId, onClick: this.onDivLabelClick }, h("slot", { key: '23ff66138f8c3a2f56f39113fc842d54b2f7952a' }), this.renderHintText()), h("div", { key: 'ab914d9623c19fc46821d5e62db92f1192ebbe7e', class: "native-wrapper" }, h("svg", { key: '66e3f4f5dcaa9756fb0e9452299954f9ed3dcb7b', class: "checkbox-icon", viewBox: "0 0 24 24", part: "container", "aria-hidden": "true" }, path)))));
|
|
170
219
|
}
|
|
171
220
|
getSVGPath(mode, indeterminate) {
|
|
172
221
|
let path = indeterminate ? (h("path", { d: "M6 12L18 12", part: "mark" })) : (h("path", { d: "M5.9,12.5l3.8,3.8l8.8-8.8", part: "mark" }));
|
|
@@ -193,6 +242,8 @@ const Checkbox = /*@__PURE__*/ proxyCustomElement(class Checkbox extends HTMLEle
|
|
|
193
242
|
"justify": [1],
|
|
194
243
|
"alignment": [1],
|
|
195
244
|
"required": [4],
|
|
245
|
+
"isInvalid": [32],
|
|
246
|
+
"hintTextId": [32],
|
|
196
247
|
"setFocus": [64]
|
|
197
248
|
}]);
|
|
198
249
|
let checkboxIds = 0;
|
package/components/header.js
CHANGED
|
@@ -8,6 +8,8 @@ import { h as hostContext } from './theme.js';
|
|
|
8
8
|
import { b as getIonMode } from './ionic-global.js';
|
|
9
9
|
|
|
10
10
|
const TRANSITION = 'all 0.2s ease-in-out';
|
|
11
|
+
const ROLE_NONE = 'none';
|
|
12
|
+
const ROLE_BANNER = 'banner';
|
|
11
13
|
const cloneElement = (tagName) => {
|
|
12
14
|
const getCachedEl = document.querySelector(`${tagName}.ion-cloned-element`);
|
|
13
15
|
if (getCachedEl !== null) {
|
|
@@ -134,6 +136,7 @@ const setHeaderActive = (headerIndex, active = true) => {
|
|
|
134
136
|
const toolbars = headerIndex.toolbars;
|
|
135
137
|
const ionTitles = toolbars.map((toolbar) => toolbar.ionTitleEl);
|
|
136
138
|
if (active) {
|
|
139
|
+
headerEl.setAttribute('role', ROLE_BANNER);
|
|
137
140
|
headerEl.classList.remove('header-collapse-condense-inactive');
|
|
138
141
|
ionTitles.forEach((ionTitle) => {
|
|
139
142
|
if (ionTitle) {
|
|
@@ -142,6 +145,16 @@ const setHeaderActive = (headerIndex, active = true) => {
|
|
|
142
145
|
});
|
|
143
146
|
}
|
|
144
147
|
else {
|
|
148
|
+
/**
|
|
149
|
+
* There can only be one banner landmark per page.
|
|
150
|
+
* By default, all ion-headers have the banner role.
|
|
151
|
+
* This causes an accessibility issue when using a
|
|
152
|
+
* condensed header since there are two ion-headers
|
|
153
|
+
* on the page at once (active and inactive).
|
|
154
|
+
* To solve this, the role needs to be toggled
|
|
155
|
+
* based on which header is active.
|
|
156
|
+
*/
|
|
157
|
+
headerEl.setAttribute('role', ROLE_NONE);
|
|
145
158
|
headerEl.classList.add('header-collapse-condense-inactive');
|
|
146
159
|
/**
|
|
147
160
|
* The small title should only be accessed by screen readers
|
|
@@ -201,8 +214,32 @@ const handleHeaderFade = (scrollEl, baseEl, condenseHeader) => {
|
|
|
201
214
|
});
|
|
202
215
|
});
|
|
203
216
|
};
|
|
217
|
+
/**
|
|
218
|
+
* Get the role type for the ion-header.
|
|
219
|
+
*
|
|
220
|
+
* @param isInsideMenu If ion-header is inside ion-menu.
|
|
221
|
+
* @param isCondensed If ion-header has collapse="condense".
|
|
222
|
+
* @param mode The current mode.
|
|
223
|
+
* @returns 'none' if inside ion-menu or if condensed in md
|
|
224
|
+
* mode, otherwise 'banner'.
|
|
225
|
+
*/
|
|
226
|
+
const getRoleType = (isInsideMenu, isCondensed, mode) => {
|
|
227
|
+
// If the header is inside a menu, it should not have the banner role.
|
|
228
|
+
if (isInsideMenu) {
|
|
229
|
+
return ROLE_NONE;
|
|
230
|
+
}
|
|
231
|
+
/**
|
|
232
|
+
* Only apply role="none" to `md` mode condensed headers
|
|
233
|
+
* since the large header is never shown.
|
|
234
|
+
*/
|
|
235
|
+
if (isCondensed && mode === 'md') {
|
|
236
|
+
return ROLE_NONE;
|
|
237
|
+
}
|
|
238
|
+
// Default to banner role.
|
|
239
|
+
return ROLE_BANNER;
|
|
240
|
+
};
|
|
204
241
|
|
|
205
|
-
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{
|
|
242
|
+
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}";
|
|
206
243
|
|
|
207
244
|
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}";
|
|
208
245
|
|
|
@@ -345,16 +382,17 @@ const Header = /*@__PURE__*/ proxyCustomElement(class Header extends HTMLElement
|
|
|
345
382
|
const { translucent, inheritedAttributes } = this;
|
|
346
383
|
const mode = getIonMode(this);
|
|
347
384
|
const collapse = this.collapse || 'none';
|
|
385
|
+
const isCondensed = collapse === 'condense';
|
|
348
386
|
// banner role must be at top level, so remove role if inside a menu
|
|
349
|
-
const roleType = hostContext('ion-menu', this.el)
|
|
350
|
-
return (h(Host, Object.assign({ key: '
|
|
387
|
+
const roleType = getRoleType(hostContext('ion-menu', this.el), isCondensed, mode);
|
|
388
|
+
return (h(Host, Object.assign({ key: '863c4568cd7b8c0ec55109f193bbbaed68a1346e', role: roleType, class: {
|
|
351
389
|
[mode]: true,
|
|
352
390
|
// Used internally for styling
|
|
353
391
|
[`header-${mode}`]: true,
|
|
354
392
|
[`header-translucent`]: this.translucent,
|
|
355
393
|
[`header-collapse-${collapse}`]: true,
|
|
356
394
|
[`header-translucent-${mode}`]: this.translucent,
|
|
357
|
-
} }, inheritedAttributes), mode === 'ios' && translucent && h("div", { key: '
|
|
395
|
+
} }, inheritedAttributes), mode === 'ios' && translucent && h("div", { key: '25c3bdce328b0b35607d154c8b8374679313d881', class: "header-background" }), h("slot", { key: 'b44fab0a9be7920b9650da26117c783e751e1702' })));
|
|
358
396
|
}
|
|
359
397
|
get el() { return this; }
|
|
360
398
|
static get style() { return {
|
package/components/index2.js
CHANGED
|
@@ -123,11 +123,22 @@ const iosTransitionAnimation = () => import('./ios.transition.js');
|
|
|
123
123
|
const mdTransitionAnimation = () => import('./md.transition.js');
|
|
124
124
|
const focusController = createFocusController();
|
|
125
125
|
// TODO(FW-2832): types
|
|
126
|
+
/**
|
|
127
|
+
* Executes the main page transition.
|
|
128
|
+
* It also manages the lifecycle of header visibility (if any)
|
|
129
|
+
* to prevent visual flickering in iOS. The flickering only
|
|
130
|
+
* occurs for a condensed header that is placed above the content.
|
|
131
|
+
*
|
|
132
|
+
* @param opts Options for the transition.
|
|
133
|
+
* @returns A promise that resolves when the transition is complete.
|
|
134
|
+
*/
|
|
126
135
|
const transition = (opts) => {
|
|
127
136
|
return new Promise((resolve, reject) => {
|
|
128
137
|
writeTask(() => {
|
|
129
|
-
|
|
130
|
-
|
|
138
|
+
const transitioningInactiveHeader = getIosIonHeader(opts);
|
|
139
|
+
beforeTransition(opts, transitioningInactiveHeader);
|
|
140
|
+
runTransition(opts)
|
|
141
|
+
.then((result) => {
|
|
131
142
|
if (result.animation) {
|
|
132
143
|
result.animation.destroy();
|
|
133
144
|
}
|
|
@@ -136,15 +147,21 @@ const transition = (opts) => {
|
|
|
136
147
|
}, (error) => {
|
|
137
148
|
afterTransition(opts);
|
|
138
149
|
reject(error);
|
|
150
|
+
})
|
|
151
|
+
.finally(() => {
|
|
152
|
+
// Ensure that the header is restored to its original state.
|
|
153
|
+
setHeaderTransitionClass(transitioningInactiveHeader, false);
|
|
139
154
|
});
|
|
140
155
|
});
|
|
141
156
|
});
|
|
142
157
|
};
|
|
143
|
-
const beforeTransition = (opts) => {
|
|
158
|
+
const beforeTransition = (opts, transitioningInactiveHeader) => {
|
|
144
159
|
const enteringEl = opts.enteringEl;
|
|
145
160
|
const leavingEl = opts.leavingEl;
|
|
146
161
|
focusController.saveViewFocus(leavingEl);
|
|
147
162
|
setZIndex(enteringEl, leavingEl, opts.direction);
|
|
163
|
+
// Prevent flickering of the header by adding a class.
|
|
164
|
+
setHeaderTransitionClass(transitioningInactiveHeader, true);
|
|
148
165
|
if (opts.showGoBack) {
|
|
149
166
|
enteringEl.classList.add('can-go-back');
|
|
150
167
|
}
|
|
@@ -333,6 +350,39 @@ const setZIndex = (enteringEl, leavingEl, direction) => {
|
|
|
333
350
|
leavingEl.style.zIndex = '100';
|
|
334
351
|
}
|
|
335
352
|
};
|
|
353
|
+
/**
|
|
354
|
+
* Add a class to ensure that the header (if any)
|
|
355
|
+
* does not flicker during the transition. By adding the
|
|
356
|
+
* transitioning class, we ensure that the header has
|
|
357
|
+
* the necessary styles to prevent the following flickers:
|
|
358
|
+
* 1. When entering a page with a condensed header, the
|
|
359
|
+
* header should never be visible. However,
|
|
360
|
+
* it briefly renders the background color while
|
|
361
|
+
* the transition is occurring.
|
|
362
|
+
* 2. When leaving a page with a condensed header, the
|
|
363
|
+
* header has an opacity of 0 and the pages
|
|
364
|
+
* have a z-index which causes the entering page to
|
|
365
|
+
* briefly show it's content underneath the leaving page.
|
|
366
|
+
* 3. When entering a page or leaving a page with a fade
|
|
367
|
+
* header, the header should not have a background color.
|
|
368
|
+
* However, it briefly shows the background color while
|
|
369
|
+
* the transition is occurring.
|
|
370
|
+
*
|
|
371
|
+
* @param header The header element to modify.
|
|
372
|
+
* @param isTransitioning Whether the transition is occurring.
|
|
373
|
+
*/
|
|
374
|
+
const setHeaderTransitionClass = (header, isTransitioning) => {
|
|
375
|
+
if (!header) {
|
|
376
|
+
return;
|
|
377
|
+
}
|
|
378
|
+
const transitionClass = 'header-transitioning';
|
|
379
|
+
if (isTransitioning) {
|
|
380
|
+
header.classList.add(transitionClass);
|
|
381
|
+
}
|
|
382
|
+
else {
|
|
383
|
+
header.classList.remove(transitionClass);
|
|
384
|
+
}
|
|
385
|
+
};
|
|
336
386
|
const getIonPageElement = (element) => {
|
|
337
387
|
if (element.classList.contains('ion-page')) {
|
|
338
388
|
return element;
|
|
@@ -344,5 +394,26 @@ const getIonPageElement = (element) => {
|
|
|
344
394
|
// idk, return the original element so at least something animates and we don't have a null pointer
|
|
345
395
|
return element;
|
|
346
396
|
};
|
|
397
|
+
/**
|
|
398
|
+
* Retrieves the ion-header element from a page based on the
|
|
399
|
+
* direction of the transition.
|
|
400
|
+
*
|
|
401
|
+
* @param opts Options for the transition.
|
|
402
|
+
* @returns The ion-header element or null if not found or not in 'ios' mode.
|
|
403
|
+
*/
|
|
404
|
+
const getIosIonHeader = (opts) => {
|
|
405
|
+
const enteringEl = opts.enteringEl;
|
|
406
|
+
const leavingEl = opts.leavingEl;
|
|
407
|
+
const direction = opts.direction;
|
|
408
|
+
const mode = opts.mode;
|
|
409
|
+
if (mode !== 'ios') {
|
|
410
|
+
return null;
|
|
411
|
+
}
|
|
412
|
+
const element = direction === 'back' ? leavingEl : enteringEl;
|
|
413
|
+
if (!element) {
|
|
414
|
+
return null;
|
|
415
|
+
}
|
|
416
|
+
return element.querySelector('ion-header');
|
|
417
|
+
};
|
|
347
418
|
|
|
348
419
|
export { LIFECYCLE_WILL_ENTER as L, LIFECYCLE_DID_ENTER as a, LIFECYCLE_WILL_LEAVE as b, LIFECYCLE_DID_LEAVE as c, LIFECYCLE_WILL_UNLOAD as d, deepReady as e, getIonPageElement as g, lifecycle as l, setPageHidden as s, transition as t, waitForMount as w };
|
|
@@ -19,10 +19,57 @@ const Accordion = /*@__PURE__*/ proxyCustomElement(class Accordion extends HTMLE
|
|
|
19
19
|
this.__registerHost();
|
|
20
20
|
}
|
|
21
21
|
this.__attachShadow();
|
|
22
|
-
this.
|
|
22
|
+
this.accordionGroupUpdateHandler = () => {
|
|
23
|
+
/**
|
|
24
|
+
* Determine if this update will cause an actual state change.
|
|
25
|
+
* We only want to mark as "interacted" if the state is changing.
|
|
26
|
+
*/
|
|
27
|
+
const accordionGroup = this.accordionGroupEl;
|
|
28
|
+
if (accordionGroup) {
|
|
29
|
+
const value = accordionGroup.value;
|
|
30
|
+
const accordionValue = this.value;
|
|
31
|
+
const shouldExpand = Array.isArray(value) ? value.includes(accordionValue) : value === accordionValue;
|
|
32
|
+
const isExpanded = this.state === 4 /* AccordionState.Expanded */ || this.state === 8 /* AccordionState.Expanding */;
|
|
33
|
+
const stateWillChange = shouldExpand !== isExpanded;
|
|
34
|
+
/**
|
|
35
|
+
* Only mark as interacted if:
|
|
36
|
+
* 1. This is not the first update we've received with a defined value
|
|
37
|
+
* 2. The state is actually changing (prevents redundant updates from enabling animations)
|
|
38
|
+
*/
|
|
39
|
+
if (this.hasReceivedFirstUpdate && stateWillChange) {
|
|
40
|
+
this.hasInteracted = true;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Only count this as the first update if the group value is defined.
|
|
44
|
+
* This prevents the initial undefined value from the group's componentDidLoad
|
|
45
|
+
* from being treated as the first real update.
|
|
46
|
+
*/
|
|
47
|
+
if (value !== undefined) {
|
|
48
|
+
this.hasReceivedFirstUpdate = true;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
this.updateState();
|
|
52
|
+
};
|
|
23
53
|
this.state = 1 /* AccordionState.Collapsed */;
|
|
24
54
|
this.isNext = false;
|
|
25
55
|
this.isPrevious = false;
|
|
56
|
+
/**
|
|
57
|
+
* Tracks whether a user-initiated interaction has occurred.
|
|
58
|
+
* Animations are disabled until the first interaction happens.
|
|
59
|
+
* This prevents the accordion from animating when it's programmatically
|
|
60
|
+
* set to an expanded or collapsed state on initial load.
|
|
61
|
+
*/
|
|
62
|
+
this.hasInteracted = false;
|
|
63
|
+
/**
|
|
64
|
+
* Tracks if this accordion has ever been expanded.
|
|
65
|
+
* Used to prevent the first expansion from animating.
|
|
66
|
+
*/
|
|
67
|
+
this.hasEverBeenExpanded = false;
|
|
68
|
+
/**
|
|
69
|
+
* Tracks if this accordion has received its first update from the group.
|
|
70
|
+
* Used to distinguish initial programmatic sets from user interactions.
|
|
71
|
+
*/
|
|
72
|
+
this.hasReceivedFirstUpdate = false;
|
|
26
73
|
/**
|
|
27
74
|
* The value of the accordion. Defaults to an autogenerated
|
|
28
75
|
* value.
|
|
@@ -127,10 +174,15 @@ const Accordion = /*@__PURE__*/ proxyCustomElement(class Accordion extends HTMLE
|
|
|
127
174
|
iconEl.setAttribute('aria-hidden', 'true');
|
|
128
175
|
ionItem.appendChild(iconEl);
|
|
129
176
|
};
|
|
130
|
-
this.expandAccordion = (
|
|
177
|
+
this.expandAccordion = () => {
|
|
131
178
|
const { contentEl, contentElWrapper } = this;
|
|
132
|
-
|
|
179
|
+
/**
|
|
180
|
+
* If the content elements aren't available yet, just set the state.
|
|
181
|
+
* This happens on initial render before the DOM is ready.
|
|
182
|
+
*/
|
|
183
|
+
if (contentEl === undefined || contentElWrapper === undefined) {
|
|
133
184
|
this.state = 4 /* AccordionState.Expanded */;
|
|
185
|
+
this.hasEverBeenExpanded = true;
|
|
134
186
|
return;
|
|
135
187
|
}
|
|
136
188
|
if (this.state === 4 /* AccordionState.Expanded */) {
|
|
@@ -139,6 +191,11 @@ const Accordion = /*@__PURE__*/ proxyCustomElement(class Accordion extends HTMLE
|
|
|
139
191
|
if (this.currentRaf !== undefined) {
|
|
140
192
|
cancelAnimationFrame(this.currentRaf);
|
|
141
193
|
}
|
|
194
|
+
/**
|
|
195
|
+
* Mark that this accordion has been expanded at least once.
|
|
196
|
+
* This allows subsequent expansions to animate.
|
|
197
|
+
*/
|
|
198
|
+
this.hasEverBeenExpanded = true;
|
|
142
199
|
if (this.shouldAnimate()) {
|
|
143
200
|
raf(() => {
|
|
144
201
|
this.state = 8 /* AccordionState.Expanding */;
|
|
@@ -156,9 +213,13 @@ const Accordion = /*@__PURE__*/ proxyCustomElement(class Accordion extends HTMLE
|
|
|
156
213
|
this.state = 4 /* AccordionState.Expanded */;
|
|
157
214
|
}
|
|
158
215
|
};
|
|
159
|
-
this.collapseAccordion = (
|
|
216
|
+
this.collapseAccordion = () => {
|
|
160
217
|
const { contentEl } = this;
|
|
161
|
-
|
|
218
|
+
/**
|
|
219
|
+
* If the content element isn't available yet, just set the state.
|
|
220
|
+
* This happens on initial render before the DOM is ready.
|
|
221
|
+
*/
|
|
222
|
+
if (contentEl === undefined) {
|
|
162
223
|
this.state = 1 /* AccordionState.Collapsed */;
|
|
163
224
|
return;
|
|
164
225
|
}
|
|
@@ -193,6 +254,18 @@ const Accordion = /*@__PURE__*/ proxyCustomElement(class Accordion extends HTMLE
|
|
|
193
254
|
* of what is set in the config.
|
|
194
255
|
*/
|
|
195
256
|
this.shouldAnimate = () => {
|
|
257
|
+
/**
|
|
258
|
+
* Don't animate until after the first user interaction.
|
|
259
|
+
* This prevents animations on initial load when accordions
|
|
260
|
+
* start in an expanded or collapsed state programmatically.
|
|
261
|
+
*
|
|
262
|
+
* Additionally, don't animate the very first expansion even if
|
|
263
|
+
* hasInteracted is true. This handles edge cases like React StrictMode
|
|
264
|
+
* where effects run twice and might incorrectly mark as interacted.
|
|
265
|
+
*/
|
|
266
|
+
if (!this.hasInteracted || !this.hasEverBeenExpanded) {
|
|
267
|
+
return false;
|
|
268
|
+
}
|
|
196
269
|
if (typeof window === 'undefined') {
|
|
197
270
|
return false;
|
|
198
271
|
}
|
|
@@ -209,7 +282,7 @@ const Accordion = /*@__PURE__*/ proxyCustomElement(class Accordion extends HTMLE
|
|
|
209
282
|
}
|
|
210
283
|
return true;
|
|
211
284
|
};
|
|
212
|
-
this.updateState = async (
|
|
285
|
+
this.updateState = async () => {
|
|
213
286
|
const accordionGroup = this.accordionGroupEl;
|
|
214
287
|
const accordionValue = this.value;
|
|
215
288
|
if (!accordionGroup) {
|
|
@@ -218,11 +291,11 @@ const Accordion = /*@__PURE__*/ proxyCustomElement(class Accordion extends HTMLE
|
|
|
218
291
|
const value = accordionGroup.value;
|
|
219
292
|
const shouldExpand = Array.isArray(value) ? value.includes(accordionValue) : value === accordionValue;
|
|
220
293
|
if (shouldExpand) {
|
|
221
|
-
this.expandAccordion(
|
|
294
|
+
this.expandAccordion();
|
|
222
295
|
this.isNext = this.isPrevious = false;
|
|
223
296
|
}
|
|
224
297
|
else {
|
|
225
|
-
this.collapseAccordion(
|
|
298
|
+
this.collapseAccordion();
|
|
226
299
|
/**
|
|
227
300
|
* When using popout or inset,
|
|
228
301
|
* the collapsed accordion items
|
|
@@ -270,14 +343,14 @@ const Accordion = /*@__PURE__*/ proxyCustomElement(class Accordion extends HTMLE
|
|
|
270
343
|
var _a;
|
|
271
344
|
const accordionGroupEl = (this.accordionGroupEl = (_a = this.el) === null || _a === void 0 ? void 0 : _a.closest('ion-accordion-group'));
|
|
272
345
|
if (accordionGroupEl) {
|
|
273
|
-
this.updateState(
|
|
274
|
-
addEventListener(accordionGroupEl, 'ionValueChange', this.
|
|
346
|
+
this.updateState();
|
|
347
|
+
addEventListener(accordionGroupEl, 'ionValueChange', this.accordionGroupUpdateHandler);
|
|
275
348
|
}
|
|
276
349
|
}
|
|
277
350
|
disconnectedCallback() {
|
|
278
351
|
const accordionGroupEl = this.accordionGroupEl;
|
|
279
352
|
if (accordionGroupEl) {
|
|
280
|
-
removeEventListener(accordionGroupEl, 'ionValueChange', this.
|
|
353
|
+
removeEventListener(accordionGroupEl, 'ionValueChange', this.accordionGroupUpdateHandler);
|
|
281
354
|
}
|
|
282
355
|
}
|
|
283
356
|
componentDidLoad() {
|
|
@@ -301,6 +374,11 @@ const Accordion = /*@__PURE__*/ proxyCustomElement(class Accordion extends HTMLE
|
|
|
301
374
|
const { accordionGroupEl, disabled, readonly, value, state } = this;
|
|
302
375
|
if (disabled || readonly)
|
|
303
376
|
return;
|
|
377
|
+
/**
|
|
378
|
+
* Mark that the user has interacted with the accordion.
|
|
379
|
+
* This enables animations for all future state changes.
|
|
380
|
+
*/
|
|
381
|
+
this.hasInteracted = true;
|
|
304
382
|
if (accordionGroupEl) {
|
|
305
383
|
/**
|
|
306
384
|
* Because the accordion group may or may
|
|
@@ -321,7 +399,7 @@ const Accordion = /*@__PURE__*/ proxyCustomElement(class Accordion extends HTMLE
|
|
|
321
399
|
const headerPart = expanded ? 'header expanded' : 'header';
|
|
322
400
|
const contentPart = expanded ? 'content expanded' : 'content';
|
|
323
401
|
this.setAria(expanded);
|
|
324
|
-
return (h(Host, { key: '
|
|
402
|
+
return (h(Host, { key: '9c90bce01eff7e5774a19f69c872f3761d66cf3c', class: {
|
|
325
403
|
[mode]: true,
|
|
326
404
|
'accordion-expanding': this.state === 8 /* AccordionState.Expanding */,
|
|
327
405
|
'accordion-expanded': this.state === 4 /* AccordionState.Expanded */,
|
|
@@ -332,7 +410,7 @@ const Accordion = /*@__PURE__*/ proxyCustomElement(class Accordion extends HTMLE
|
|
|
332
410
|
'accordion-disabled': disabled,
|
|
333
411
|
'accordion-readonly': readonly,
|
|
334
412
|
'accordion-animated': this.shouldAnimate(),
|
|
335
|
-
} }, h("div", { key: '
|
|
413
|
+
} }, h("div", { key: 'cab40d5bcf3c93fd78e70b6d3906a541e725837d', onClick: () => this.toggleExpanded(), id: "header", part: headerPart, "aria-controls": "content", ref: (headerEl) => (this.headerEl = headerEl) }, h("slot", { key: '672bc7fb3f9e18076b41e20fc9eaeab7cafcf3a2', name: "header" })), h("div", { key: 'fd777ca5b4ab04aa4f44c339d58c8cd987c52bcb', id: "content", part: contentPart, role: "region", "aria-labelledby": "header", ref: (contentEl) => (this.contentEl = contentEl) }, h("div", { key: '0aad70a71e2cd2c16b2e98fa0bdd40421d95fe16', id: "content-wrapper", ref: (contentElWrapper) => (this.contentElWrapper = contentElWrapper) }, h("slot", { key: 'd630e10ac7c56b4dbf943b523f26759b83aead55', name: "content" })))));
|
|
336
414
|
}
|
|
337
415
|
static get delegatesFocus() { return true; }
|
|
338
416
|
get el() { return this; }
|
|
@@ -351,7 +429,8 @@ const Accordion = /*@__PURE__*/ proxyCustomElement(class Accordion extends HTMLE
|
|
|
351
429
|
"toggleIconSlot": [1, "toggle-icon-slot"],
|
|
352
430
|
"state": [32],
|
|
353
431
|
"isNext": [32],
|
|
354
|
-
"isPrevious": [32]
|
|
432
|
+
"isPrevious": [32],
|
|
433
|
+
"hasInteracted": [32]
|
|
355
434
|
}, undefined, {
|
|
356
435
|
"value": ["valueChanged"]
|
|
357
436
|
}]);
|