Merge branch 'main' into chore-update-next-from-main

This commit is contained in:
Brandy Carney
2024-10-30 12:58:29 -04:00
39 changed files with 447 additions and 119 deletions

View File

@ -3,6 +3,23 @@
All notable changes to this project will be documented in this file. All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [8.3.4](https://github.com/ionic-team/ionic-framework/compare/v8.3.3...v8.3.4) (2024-10-30)
### Bug Fixes
* **angular:** add missing 'compareWith' input to standalone ion-radio-group ([#29870](https://github.com/ionic-team/ionic-framework/issues/29870)) ([47ba703](https://github.com/ionic-team/ionic-framework/commit/47ba703a57d1ca506f943f6b790d0bf7583d79cb)), closes [#29826](https://github.com/ionic-team/ionic-framework/issues/29826)
* **backdrop:** remove tabindex for improved accessibility ([#29956](https://github.com/ionic-team/ionic-framework/issues/29956)) ([7294e96](https://github.com/ionic-team/ionic-framework/commit/7294e969bb913692eaf28e54860614f445132713)), closes [#29773](https://github.com/ionic-team/ionic-framework/issues/29773)
* **input, textarea:** ensure screen readers announce helper and error text when focused ([#29958](https://github.com/ionic-team/ionic-framework/issues/29958)) ([5a73145](https://github.com/ionic-team/ionic-framework/commit/5a7314553a8def87bd19275640c92dd72a6ef1a4))
* **overlay:** hide from screen readers while animating ([#29951](https://github.com/ionic-team/ionic-framework/issues/29951)) ([cb60073](https://github.com/ionic-team/ionic-framework/commit/cb6007363a8d42b5f126945427c2bfc3d7209c21)), closes [#29857](https://github.com/ionic-team/ionic-framework/issues/29857)
* **overlays:** do not hide root when toast appears ([#29962](https://github.com/ionic-team/ionic-framework/issues/29962)) ([322d7c9](https://github.com/ionic-team/ionic-framework/commit/322d7c98cf6613df0b0db3f119e3f892e6a17e7b)), closes [#29773](https://github.com/ionic-team/ionic-framework/issues/29773)
* **overlays:** hide the focus trap div from screen readers ([#29970](https://github.com/ionic-team/ionic-framework/issues/29970)) ([c3b58f1](https://github.com/ionic-team/ionic-framework/commit/c3b58f1620bcb74db43e3983ef570b7b982abd83)), closes [#29858](https://github.com/ionic-team/ionic-framework/issues/29858)
* **vue:** incorrect view rendered when using router.go(-n) ([#29877](https://github.com/ionic-team/ionic-framework/issues/29877)) ([e32fbe0](https://github.com/ionic-team/ionic-framework/commit/e32fbe02102fe80db29f73c26496a40852032354)), closes [#28201](https://github.com/ionic-team/ionic-framework/issues/28201) [#28201](https://github.com/ionic-team/ionic-framework/issues/28201) [#29847](https://github.com/ionic-team/ionic-framework/issues/29847)
## [8.3.3](https://github.com/ionic-team/ionic-framework/compare/v8.3.2...v8.3.3) (2024-10-16) ## [8.3.3](https://github.com/ionic-team/ionic-framework/compare/v8.3.2...v8.3.3) (2024-10-16)

View File

@ -3,6 +3,21 @@
All notable changes to this project will be documented in this file. All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [8.3.4](https://github.com/ionic-team/ionic-framework/compare/v8.3.3...v8.3.4) (2024-10-30)
### Bug Fixes
* **backdrop:** remove tabindex for improved accessibility ([#29956](https://github.com/ionic-team/ionic-framework/issues/29956)) ([7294e96](https://github.com/ionic-team/ionic-framework/commit/7294e969bb913692eaf28e54860614f445132713)), closes [#29773](https://github.com/ionic-team/ionic-framework/issues/29773)
* **input, textarea:** ensure screen readers announce helper and error text when focused ([#29958](https://github.com/ionic-team/ionic-framework/issues/29958)) ([5a73145](https://github.com/ionic-team/ionic-framework/commit/5a7314553a8def87bd19275640c92dd72a6ef1a4))
* **overlay:** hide from screen readers while animating ([#29951](https://github.com/ionic-team/ionic-framework/issues/29951)) ([cb60073](https://github.com/ionic-team/ionic-framework/commit/cb6007363a8d42b5f126945427c2bfc3d7209c21)), closes [#29857](https://github.com/ionic-team/ionic-framework/issues/29857)
* **overlays:** do not hide root when toast appears ([#29962](https://github.com/ionic-team/ionic-framework/issues/29962)) ([322d7c9](https://github.com/ionic-team/ionic-framework/commit/322d7c98cf6613df0b0db3f119e3f892e6a17e7b)), closes [#29773](https://github.com/ionic-team/ionic-framework/issues/29773)
* **overlays:** hide the focus trap div from screen readers ([#29970](https://github.com/ionic-team/ionic-framework/issues/29970)) ([c3b58f1](https://github.com/ionic-team/ionic-framework/commit/c3b58f1620bcb74db43e3983ef570b7b982abd83)), closes [#29858](https://github.com/ionic-team/ionic-framework/issues/29858)
## [8.3.3](https://github.com/ionic-team/ionic-framework/compare/v8.3.2...v8.3.3) (2024-10-16) ## [8.3.3](https://github.com/ionic-team/ionic-framework/compare/v8.3.2...v8.3.3) (2024-10-16)
**Note:** Version bump only for package @ionic/core **Note:** Version bump only for package @ionic/core

View File

@ -1,12 +1,12 @@
{ {
"name": "@ionic/core", "name": "@ionic/core",
"version": "8.3.3", "version": "8.3.4",
"lockfileVersion": 2, "lockfileVersion": 2,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "@ionic/core", "name": "@ionic/core",
"version": "8.3.3", "version": "8.3.4",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@phosphor-icons/core": "^2.1.1", "@phosphor-icons/core": "^2.1.1",

View File

@ -1,6 +1,6 @@
{ {
"name": "@ionic/core", "name": "@ionic/core",
"version": "8.3.3", "version": "8.3.4",
"description": "Base components for Ionic", "description": "Base components for Ionic",
"keywords": [ "keywords": [
"ionic", "ionic",

View File

@ -388,7 +388,7 @@ export class ActionSheet implements ComponentInterface, OverlayInterface {
> >
<ion-backdrop tappable={this.backdropDismiss} /> <ion-backdrop tappable={this.backdropDismiss} />
<div tabindex="0"></div> <div tabindex="0" aria-hidden="true"></div>
<div class="action-sheet-wrapper ion-overlay-wrapper" ref={(el) => (this.wrapperEl = el)}> <div class="action-sheet-wrapper ion-overlay-wrapper" ref={(el) => (this.wrapperEl = el)}>
<div class="action-sheet-container"> <div class="action-sheet-container">
@ -449,7 +449,7 @@ export class ActionSheet implements ComponentInterface, OverlayInterface {
</div> </div>
</div> </div>
<div tabindex="0"></div> <div tabindex="0" aria-hidden="true"></div>
</Host> </Host>
); );
} }

View File

@ -759,7 +759,7 @@ export class Alert implements ComponentInterface, OverlayInterface {
> >
<ion-backdrop tappable={this.backdropDismiss} /> <ion-backdrop tappable={this.backdropDismiss} />
<div tabindex="0"></div> <div tabindex="0" aria-hidden="true"></div>
<div class="alert-wrapper ion-overlay-wrapper" ref={(el) => (this.wrapperEl = el)}> <div class="alert-wrapper ion-overlay-wrapper" ref={(el) => (this.wrapperEl = el)}>
<div class="alert-head"> <div class="alert-head">
@ -781,7 +781,7 @@ export class Alert implements ComponentInterface, OverlayInterface {
{this.renderAlertButtons()} {this.renderAlertButtons()}
</div> </div>
<div tabindex="0"></div> <div tabindex="0" aria-hidden="true"></div>
</Host> </Host>
); );
} }

View File

@ -56,7 +56,6 @@ export class Backdrop implements ComponentInterface {
const theme = getIonTheme(this); const theme = getIonTheme(this);
return ( return (
<Host <Host
tabindex="-1"
aria-hidden="true" aria-hidden="true"
class={{ class={{
[theme]: true, [theme]: true,

View File

@ -38,6 +38,8 @@ import { getCounterText } from './input.utils';
export class Input implements ComponentInterface { export class Input implements ComponentInterface {
private nativeInput?: HTMLInputElement; private nativeInput?: HTMLInputElement;
private inputId = `ion-input-${inputIds++}`; private inputId = `ion-input-${inputIds++}`;
private helperTextId = `${this.inputId}-helper-text`;
private errorTextId = `${this.inputId}-error-text`;
private inheritedAttributes: Attributes = {}; private inheritedAttributes: Attributes = {};
private isComposing = false; private isComposing = false;
private slotMutationController?: SlotMutationController; private slotMutationController?: SlotMutationController;
@ -655,9 +657,30 @@ export class Input implements ComponentInterface {
* Renders the helper text or error text values * Renders the helper text or error text values
*/ */
private renderHintText() { private renderHintText() {
const { helperText, errorText } = this; const { helperText, errorText, helperTextId, errorTextId } = this;
return [<div class="helper-text">{helperText}</div>, <div class="error-text">{errorText}</div>]; return [
<div id={helperTextId} class="helper-text">
{helperText}
</div>,
<div id={errorTextId} class="error-text">
{errorText}
</div>,
];
}
private getHintTextID(): string | undefined {
const { el, helperText, errorText, helperTextId, errorTextId } = this;
if (el.classList.contains('ion-touched') && el.classList.contains('ion-invalid') && errorText) {
return errorTextId;
}
if (helperText) {
return helperTextId;
}
return undefined;
} }
private renderCounter() { private renderCounter() {
@ -905,6 +928,8 @@ export class Input implements ComponentInterface {
onKeyDown={this.onKeydown} onKeyDown={this.onKeydown}
onCompositionstart={this.onCompositionStart} onCompositionstart={this.onCompositionStart}
onCompositionend={this.onCompositionEnd} onCompositionend={this.onCompositionEnd}
aria-describedby={this.getHintTextID()}
aria-invalid={this.getHintTextID() === this.errorTextId}
{...this.inheritedAttributes} {...this.inheritedAttributes}
/> />
{clearInput && !readonly && !disabled && ( {clearInput && !readonly && !disabled && (

View File

@ -93,6 +93,19 @@ configs({ modes: ['md', 'ionic-md'], directions: ['ltr'] }).forEach(({ title, sc
await expect(helperText).toHaveText('my helper'); await expect(helperText).toHaveText('my helper');
await expect(errorText).toBeHidden(); await expect(errorText).toBeHidden();
}); });
test('input should have an aria-describedby attribute when helper text is present', async ({ page }) => {
await page.setContent(
`<ion-input helper-text="my helper" error-text="my error" label="my input"></ion-input>`,
config
);
const input = page.locator('ion-input input');
const helperText = page.locator('ion-input .helper-text');
const helperTextId = await helperText.getAttribute('id');
const ariaDescribedBy = await input.getAttribute('aria-describedby');
expect(ariaDescribedBy).toBe(helperTextId);
});
test('error text should be visible when input is invalid', async ({ page }) => { test('error text should be visible when input is invalid', async ({ page }) => {
await page.setContent( await page.setContent(
`<ion-input class="ion-invalid ion-touched" helper-text="my helper" error-text="my error" label="my input"></ion-input>`, `<ion-input class="ion-invalid ion-touched" helper-text="my helper" error-text="my error" label="my input"></ion-input>`,
@ -122,6 +135,48 @@ configs({ modes: ['md', 'ionic-md'], directions: ['ltr'] }).forEach(({ title, sc
const bottomEl = page.locator('ion-input .input-bottom'); const bottomEl = page.locator('ion-input .input-bottom');
await expect(bottomEl).toHaveScreenshot(screenshot(`input-error-custom-color`)); await expect(bottomEl).toHaveScreenshot(screenshot(`input-error-custom-color`));
}); });
test('input should have an aria-describedby attribute when error text is present', async ({ page }) => {
await page.setContent(
`<ion-input class="ion-invalid ion-touched" helper-text="my helper" error-text="my error" label="my input"></ion-input>`,
config
);
const input = page.locator('ion-input input');
const errorText = page.locator('ion-input .error-text');
const errorTextId = await errorText.getAttribute('id');
const ariaDescribedBy = await input.getAttribute('aria-describedby');
expect(ariaDescribedBy).toBe(errorTextId);
});
test('input should have aria-invalid attribute when input is invalid', async ({ page }) => {
await page.setContent(
`<ion-input class="ion-invalid ion-touched" helper-text="my helper" error-text="my error" label="my input"></ion-input>`,
config
);
const input = page.locator('ion-input input');
await expect(input).toHaveAttribute('aria-invalid');
});
test('input should not have aria-invalid attribute when input is valid', async ({ page }) => {
await page.setContent(
`<ion-input helper-text="my helper" error-text="my error" label="my input"></ion-input>`,
config
);
const input = page.locator('ion-input input');
await expect(input).not.toHaveAttribute('aria-invalid');
});
test('input should not have aria-describedby attribute when no hint or error text is present', async ({
page,
}) => {
await page.setContent(`<ion-input label="my input"></ion-input>`, config);
const input = page.locator('ion-input input');
await expect(input).not.toHaveAttribute('aria-describedby');
});
}); });
test.describe('input: hint text rendering', () => { test.describe('input: hint text rendering', () => {
test.describe('regular inputs', () => { test.describe('regular inputs', () => {

View File

@ -358,7 +358,7 @@ export class Loading implements ComponentInterface, OverlayInterface {
> >
<ion-backdrop visible={this.showBackdrop} tappable={this.backdropDismiss} /> <ion-backdrop visible={this.showBackdrop} tappable={this.backdropDismiss} />
<div tabindex="0"></div> <div tabindex="0" aria-hidden="true"></div>
<div class="loading-wrapper ion-overlay-wrapper"> <div class="loading-wrapper ion-overlay-wrapper">
{spinner && ( {spinner && (
@ -370,7 +370,7 @@ export class Loading implements ComponentInterface, OverlayInterface {
{message !== undefined && this.renderLoadingMessage(msgId)} {message !== undefined && this.renderLoadingMessage(msgId)}
</div> </div>
<div tabindex="0"></div> <div tabindex="0" aria-hidden="true"></div>
</Host> </Host>
); );
} }

View File

@ -376,7 +376,7 @@ export class Picker implements ComponentInterface, OverlayInterface {
> >
<ion-backdrop visible={this.showBackdrop} tappable={this.backdropDismiss}></ion-backdrop> <ion-backdrop visible={this.showBackdrop} tappable={this.backdropDismiss}></ion-backdrop>
<div tabindex="0"></div> <div tabindex="0" aria-hidden="true"></div>
<div class="picker-wrapper ion-overlay-wrapper" role="dialog"> <div class="picker-wrapper ion-overlay-wrapper" role="dialog">
<div class="picker-toolbar"> <div class="picker-toolbar">
@ -396,7 +396,7 @@ export class Picker implements ComponentInterface, OverlayInterface {
</div> </div>
</div> </div>
<div tabindex="0"></div> <div tabindex="0" aria-hidden="true"></div>
</Host> </Host>
); );
} }

View File

@ -27,6 +27,19 @@ configs({ modes: ['md'], directions: ['ltr'] }).forEach(({ title, screenshot, co
await expect(helperText).toHaveText('my helper'); await expect(helperText).toHaveText('my helper');
await expect(errorText).toBeHidden(); await expect(errorText).toBeHidden();
}); });
test('textarea should have an aria-describedby attribute when helper text is present', async ({ page }) => {
await page.setContent(
`<ion-textarea helper-text="my helper" error-text="my error" label="my textarea"></ion-textarea>`,
config
);
const textarea = page.locator('ion-textarea textarea');
const helperText = page.locator('ion-textarea .helper-text');
const helperTextId = await helperText.getAttribute('id');
const ariaDescribedBy = await textarea.getAttribute('aria-describedby');
expect(ariaDescribedBy).toBe(helperTextId);
});
test('error text should be visible when textarea is invalid', async ({ page }) => { test('error text should be visible when textarea is invalid', async ({ page }) => {
await page.setContent( await page.setContent(
`<ion-textarea class="ion-invalid ion-touched" helper-text="my helper" error-text="my error" label="my textarea"></ion-textarea>`, `<ion-textarea class="ion-invalid ion-touched" helper-text="my helper" error-text="my error" label="my textarea"></ion-textarea>`,
@ -55,6 +68,48 @@ configs({ modes: ['md'], directions: ['ltr'] }).forEach(({ title, screenshot, co
const errorText = page.locator('ion-textarea .error-text'); const errorText = page.locator('ion-textarea .error-text');
await expect(errorText).toHaveScreenshot(screenshot(`textarea-error-custom-color`)); await expect(errorText).toHaveScreenshot(screenshot(`textarea-error-custom-color`));
}); });
test('textarea should have an aria-describedby attribute when error text is present', async ({ page }) => {
await page.setContent(
`<ion-textarea class="ion-invalid ion-touched" helper-text="my helper" error-text="my error" label="my textarea"></ion-textarea>`,
config
);
const textarea = page.locator('ion-textarea textarea');
const errorText = page.locator('ion-textarea .error-text');
const errorTextId = await errorText.getAttribute('id');
const ariaDescribedBy = await textarea.getAttribute('aria-describedby');
expect(ariaDescribedBy).toBe(errorTextId);
});
test('textarea should have aria-invalid attribute when input is invalid', async ({ page }) => {
await page.setContent(
`<ion-textarea class="ion-invalid ion-touched" helper-text="my helper" error-text="my error" label="my textarea"></ion-textarea>`,
config
);
const textarea = page.locator('ion-textarea textarea');
await expect(textarea).toHaveAttribute('aria-invalid');
});
test('textarea should not have aria-invalid attribute when input is valid', async ({ page }) => {
await page.setContent(
`<ion-textarea helper-text="my helper" error-text="my error" label="my textarea"></ion-textarea>`,
config
);
const textarea = page.locator('ion-textarea textarea');
await expect(textarea).not.toHaveAttribute('aria-invalid');
});
test('textarea should not have aria-describedby attribute when no hint or error text is present', async ({
page,
}) => {
await page.setContent(`<ion-textarea label="my textarea"></ion-textarea>`, config);
const textarea = page.locator('ion-textarea textarea');
await expect(textarea).not.toHaveAttribute('aria-describedby');
});
}); });
test.describe('textarea: hint text rendering', () => { test.describe('textarea: hint text rendering', () => {
test.describe('regular textareas', () => { test.describe('regular textareas', () => {

View File

@ -47,6 +47,8 @@ import type { TextareaChangeEventDetail, TextareaInputEventDetail } from './text
export class Textarea implements ComponentInterface { export class Textarea implements ComponentInterface {
private nativeInput?: HTMLTextAreaElement; private nativeInput?: HTMLTextAreaElement;
private inputId = `ion-textarea-${textareaIds++}`; private inputId = `ion-textarea-${textareaIds++}`;
private helperTextId = `${this.inputId}-helper-text`;
private errorTextId = `${this.inputId}-error-text`;
/** /**
* `true` if the textarea was cleared as a result of the user typing * `true` if the textarea was cleared as a result of the user typing
* with `clearOnEdit` enabled. * with `clearOnEdit` enabled.
@ -601,9 +603,30 @@ export class Textarea implements ComponentInterface {
* Renders the helper text or error text values * Renders the helper text or error text values
*/ */
private renderHintText() { private renderHintText() {
const { helperText, errorText } = this; const { helperText, errorText, helperTextId, errorTextId } = this;
return [<div class="helper-text">{helperText}</div>, <div class="error-text">{errorText}</div>]; return [
<div id={helperTextId} class="helper-text">
{helperText}
</div>,
<div id={errorTextId} class="error-text">
{errorText}
</div>,
];
}
private getHintTextID(): string | undefined {
const { el, helperText, errorText, helperTextId, errorTextId } = this;
if (el.classList.contains('ion-touched') && el.classList.contains('ion-invalid') && errorText) {
return errorTextId;
}
if (helperText) {
return helperTextId;
}
return undefined;
} }
private renderCounter() { private renderCounter() {
@ -742,6 +765,8 @@ export class Textarea implements ComponentInterface {
onBlur={this.onBlur} onBlur={this.onBlur}
onFocus={this.onFocus} onFocus={this.onFocus}
onKeyDown={this.onKeyDown} onKeyDown={this.onKeyDown}
aria-describedby={this.getHintTextID()}
aria-invalid={this.getHintTextID() === this.errorTextId}
{...this.inheritedAttributes} {...this.inheritedAttributes}
> >
{value} {value}

View File

@ -510,11 +510,21 @@ export const present = async <OverlayPresentOptions>(
return; return;
} }
/**
* Due to accessibility guidelines, toasts do not have
* focus traps.
*
* All other overlays should have focus traps to prevent
* the keyboard focus from leaving the overlay.
*/
if (overlay.el.tagName !== 'ION-TOAST') {
setRootAriaHidden(true); setRootAriaHidden(true);
}
document.body.classList.add(BACKDROP_NO_SCROLL); document.body.classList.add(BACKDROP_NO_SCROLL);
hideOverlaysFromScreenReaders(overlay.el); hideUnderlyingOverlaysFromScreenReaders(overlay.el);
hideAnimatingOverlayFromScreenReaders(overlay.el);
overlay.presented = true; overlay.presented = true;
overlay.willPresent.emit(); overlay.willPresent.emit();
@ -560,6 +570,11 @@ export const present = async <OverlayPresentOptions>(
* it would still have aria-hidden on being presented again. * it would still have aria-hidden on being presented again.
* Removing it here ensures the overlay is visible to screen * Removing it here ensures the overlay is visible to screen
* readers. * readers.
*
* If this overlay was being presented, then it was hidden
* from screen readers during the animation. Now that the
* animation is complete, we can reveal the overlay to
* screen readers.
*/ */
overlay.el.removeAttribute('aria-hidden'); overlay.el.removeAttribute('aria-hidden');
}; };
@ -630,13 +645,26 @@ export const dismiss = async <OverlayDismissOptions>(
return false; return false;
} }
const lastOverlay = doc !== undefined && getPresentedOverlays(doc).length === 1; /**
* For accessibility, toasts lack focus traps and dont receive
* `aria-hidden` on the root element when presented.
*
* All other overlays use focus traps to keep keyboard focus
* within the overlay, setting `aria-hidden` on the root element
* to enhance accessibility.
*
* Therefore, we must remove `aria-hidden` from the root element
* when the last non-toast overlay is dismissed.
*/
const overlaysNotToast = doc !== undefined ? getPresentedOverlays(doc).filter((o) => o.tagName !== 'ION-TOAST') : [];
const lastOverlayNotToast = overlaysNotToast.length === 1 && overlaysNotToast[0].id === overlay.el.id;
/** /**
* If this is the last visible overlay then * If this is the last visible overlay that is not a toast
* we want to re-add the root to the accessibility tree. * then we want to re-add the root to the accessibility tree.
*/ */
if (lastOverlay) { if (lastOverlayNotToast) {
setRootAriaHidden(false); setRootAriaHidden(false);
document.body.classList.remove(BACKDROP_NO_SCROLL); document.body.classList.remove(BACKDROP_NO_SCROLL);
} }
@ -644,6 +672,13 @@ export const dismiss = async <OverlayDismissOptions>(
overlay.presented = false; overlay.presented = false;
try { try {
/**
* There is no need to show the overlay to screen readers during
* the dismiss animation. This is because the overlay will be removed
* from the DOM after the animation is complete.
*/
hideAnimatingOverlayFromScreenReaders(overlay.el);
// Overlay contents should not be clickable during dismiss // Overlay contents should not be clickable during dismiss
overlay.el.style.setProperty('pointer-events', 'none'); overlay.el.style.setProperty('pointer-events', 'none');
overlay.willDismiss.emit({ data, role }); overlay.willDismiss.emit({ data, role });
@ -930,6 +965,29 @@ export const createTriggerController = () => {
}; };
}; };
/**
* The overlay that is being animated also needs to hide from screen
* readers during its animation. This ensures that assistive technologies
* like TalkBack do not announce or interact with the content until the
* animation is complete, avoiding confusion for users.
*
* If the overlay is being presented, it prevents focus rings from appearing
* in incorrect positions due to the transition (specifically `transform`
* styles), ensuring that when aria-hidden is removed, the focus rings are
* correctly displayed in the final location of the elements.
*
* @param overlay - The overlay that is being animated.
*/
const hideAnimatingOverlayFromScreenReaders = (overlay: HTMLIonOverlayElement) => {
if (doc === undefined) return;
/**
* Once the animation is complete, this attribute will be removed.
* This is done at the end of the `present` method.
*/
overlay.setAttribute('aria-hidden', 'true');
};
/** /**
* Ensure that underlying overlays have aria-hidden if necessary so that screen readers * Ensure that underlying overlays have aria-hidden if necessary so that screen readers
* cannot move focus to these elements. Note that we cannot rely on focus/focusin/focusout * cannot move focus to these elements. Note that we cannot rely on focus/focusin/focusout
@ -940,7 +998,7 @@ export const createTriggerController = () => {
* @param newTopMostOverlay - The overlay that is being presented. Since the overlay has not been * @param newTopMostOverlay - The overlay that is being presented. Since the overlay has not been
* fully presented yet at the time this function is called it will not be included in the getPresentedOverlays result. * fully presented yet at the time this function is called it will not be included in the getPresentedOverlays result.
*/ */
const hideOverlaysFromScreenReaders = (newTopMostOverlay: HTMLIonOverlayElement) => { const hideUnderlyingOverlaysFromScreenReaders = (newTopMostOverlay: HTMLIonOverlayElement) => {
if (doc === undefined) return; if (doc === undefined) return;
const overlays = getPresentedOverlays(doc); const overlays = getPresentedOverlays(doc);

View File

@ -3,5 +3,5 @@
"core", "core",
"packages/*" "packages/*"
], ],
"version": "8.3.3" "version": "8.3.4"
} }

View File

@ -3,6 +3,14 @@
All notable changes to this project will be documented in this file. All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [8.3.4](https://github.com/ionic-team/ionic-framework/compare/v8.3.3...v8.3.4) (2024-10-30)
**Note:** Version bump only for package @ionic/angular-server
## [8.3.3](https://github.com/ionic-team/ionic-framework/compare/v8.3.2...v8.3.3) (2024-10-16) ## [8.3.3](https://github.com/ionic-team/ionic-framework/compare/v8.3.2...v8.3.3) (2024-10-16)
**Note:** Version bump only for package @ionic/angular-server **Note:** Version bump only for package @ionic/angular-server

View File

@ -1,15 +1,15 @@
{ {
"name": "@ionic/angular-server", "name": "@ionic/angular-server",
"version": "8.3.3", "version": "8.3.4",
"lockfileVersion": 2, "lockfileVersion": 2,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "@ionic/angular-server", "name": "@ionic/angular-server",
"version": "8.3.3", "version": "8.3.4",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@ionic/core": "^8.3.3" "@ionic/core": "^8.3.4"
}, },
"devDependencies": { "devDependencies": {
"@angular-eslint/eslint-plugin": "^16.0.0", "@angular-eslint/eslint-plugin": "^16.0.0",
@ -1031,9 +1031,9 @@
"dev": true "dev": true
}, },
"node_modules/@ionic/core": { "node_modules/@ionic/core": {
"version": "8.3.3", "version": "8.3.4",
"resolved": "https://registry.npmjs.org/@ionic/core/-/core-8.3.3.tgz", "resolved": "https://registry.npmjs.org/@ionic/core/-/core-8.3.4.tgz",
"integrity": "sha512-f2PXV0jFIFPdjP+NbmQ1mXqRQ4KWi0U0jdQd3wDYsJFWQLmWXhW7Yp/4lCDdl0ouMeZRB2phddqFct1c7H6PyA==", "integrity": "sha512-MkgaQ9+oQwj3AK/i25MkLgKUUH3/nvNjd4YlmUyFjPG7l2IBHsrLlSmuFGCyniB+doI9Hynu3T9CZP7NS4RjRQ==",
"dependencies": { "dependencies": {
"@stencil/core": "4.20.0", "@stencil/core": "4.20.0",
"ionicons": "^7.2.2", "ionicons": "^7.2.2",
@ -7188,9 +7188,9 @@
"dev": true "dev": true
}, },
"@ionic/core": { "@ionic/core": {
"version": "8.3.3", "version": "8.3.4",
"resolved": "https://registry.npmjs.org/@ionic/core/-/core-8.3.3.tgz", "resolved": "https://registry.npmjs.org/@ionic/core/-/core-8.3.4.tgz",
"integrity": "sha512-f2PXV0jFIFPdjP+NbmQ1mXqRQ4KWi0U0jdQd3wDYsJFWQLmWXhW7Yp/4lCDdl0ouMeZRB2phddqFct1c7H6PyA==", "integrity": "sha512-MkgaQ9+oQwj3AK/i25MkLgKUUH3/nvNjd4YlmUyFjPG7l2IBHsrLlSmuFGCyniB+doI9Hynu3T9CZP7NS4RjRQ==",
"requires": { "requires": {
"@stencil/core": "4.20.0", "@stencil/core": "4.20.0",
"ionicons": "^7.2.2", "ionicons": "^7.2.2",

View File

@ -1,6 +1,6 @@
{ {
"name": "@ionic/angular-server", "name": "@ionic/angular-server",
"version": "8.3.3", "version": "8.3.4",
"description": "Angular SSR Module for Ionic", "description": "Angular SSR Module for Ionic",
"keywords": [ "keywords": [
"ionic", "ionic",
@ -62,6 +62,6 @@
}, },
"prettier": "@ionic/prettier-config", "prettier": "@ionic/prettier-config",
"dependencies": { "dependencies": {
"@ionic/core": "^8.3.3" "@ionic/core": "^8.3.4"
} }
} }

View File

@ -3,6 +3,17 @@
All notable changes to this project will be documented in this file. All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [8.3.4](https://github.com/ionic-team/ionic-framework/compare/v8.3.3...v8.3.4) (2024-10-30)
### Bug Fixes
* **angular:** add missing 'compareWith' input to standalone ion-radio-group ([#29870](https://github.com/ionic-team/ionic-framework/issues/29870)) ([47ba703](https://github.com/ionic-team/ionic-framework/commit/47ba703a57d1ca506f943f6b790d0bf7583d79cb)), closes [#29826](https://github.com/ionic-team/ionic-framework/issues/29826)
## [8.3.3](https://github.com/ionic-team/ionic-framework/compare/v8.3.2...v8.3.3) (2024-10-16) ## [8.3.3](https://github.com/ionic-team/ionic-framework/compare/v8.3.2...v8.3.3) (2024-10-16)
**Note:** Version bump only for package @ionic/angular **Note:** Version bump only for package @ionic/angular

View File

@ -1,15 +1,15 @@
{ {
"name": "@ionic/angular", "name": "@ionic/angular",
"version": "8.3.3", "version": "8.3.4",
"lockfileVersion": 2, "lockfileVersion": 2,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "@ionic/angular", "name": "@ionic/angular",
"version": "8.3.3", "version": "8.3.4",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@ionic/core": "^8.3.3", "@ionic/core": "^8.3.4",
"ionicons": "^7.0.0", "ionicons": "^7.0.0",
"jsonc-parser": "^3.0.0", "jsonc-parser": "^3.0.0",
"tslib": "^2.3.0" "tslib": "^2.3.0"
@ -1398,9 +1398,9 @@
"dev": true "dev": true
}, },
"node_modules/@ionic/core": { "node_modules/@ionic/core": {
"version": "8.3.3", "version": "8.3.4",
"resolved": "https://registry.npmjs.org/@ionic/core/-/core-8.3.3.tgz", "resolved": "https://registry.npmjs.org/@ionic/core/-/core-8.3.4.tgz",
"integrity": "sha512-f2PXV0jFIFPdjP+NbmQ1mXqRQ4KWi0U0jdQd3wDYsJFWQLmWXhW7Yp/4lCDdl0ouMeZRB2phddqFct1c7H6PyA==", "integrity": "sha512-MkgaQ9+oQwj3AK/i25MkLgKUUH3/nvNjd4YlmUyFjPG7l2IBHsrLlSmuFGCyniB+doI9Hynu3T9CZP7NS4RjRQ==",
"dependencies": { "dependencies": {
"@stencil/core": "4.20.0", "@stencil/core": "4.20.0",
"ionicons": "^7.2.2", "ionicons": "^7.2.2",
@ -9820,9 +9820,9 @@
"dev": true "dev": true
}, },
"@ionic/core": { "@ionic/core": {
"version": "8.3.3", "version": "8.3.4",
"resolved": "https://registry.npmjs.org/@ionic/core/-/core-8.3.3.tgz", "resolved": "https://registry.npmjs.org/@ionic/core/-/core-8.3.4.tgz",
"integrity": "sha512-f2PXV0jFIFPdjP+NbmQ1mXqRQ4KWi0U0jdQd3wDYsJFWQLmWXhW7Yp/4lCDdl0ouMeZRB2phddqFct1c7H6PyA==", "integrity": "sha512-MkgaQ9+oQwj3AK/i25MkLgKUUH3/nvNjd4YlmUyFjPG7l2IBHsrLlSmuFGCyniB+doI9Hynu3T9CZP7NS4RjRQ==",
"requires": { "requires": {
"@stencil/core": "4.20.0", "@stencil/core": "4.20.0",
"ionicons": "^7.2.2", "ionicons": "^7.2.2",

View File

@ -1,6 +1,6 @@
{ {
"name": "@ionic/angular", "name": "@ionic/angular",
"version": "8.3.3", "version": "8.3.4",
"description": "Angular specific wrappers for @ionic/core", "description": "Angular specific wrappers for @ionic/core",
"keywords": [ "keywords": [
"ionic", "ionic",
@ -47,7 +47,7 @@
} }
}, },
"dependencies": { "dependencies": {
"@ionic/core": "^8.3.3", "@ionic/core": "^8.3.4",
"ionicons": "^7.0.0", "ionicons": "^7.0.0",
"jsonc-parser": "^3.0.0", "jsonc-parser": "^3.0.0",
"tslib": "^2.3.0" "tslib": "^2.3.0"

View File

@ -16,7 +16,7 @@ import { defineCustomElement } from '@ionic/core/components/ion-radio-group.js';
import { ProxyCmp, proxyOutputs } from './angular-component-lib/utils'; import { ProxyCmp, proxyOutputs } from './angular-component-lib/utils';
const RADIO_GROUP_INPUTS = ['allowEmptySelection', 'name', 'value']; const RADIO_GROUP_INPUTS = ['allowEmptySelection', 'compareWith', 'name', 'value'];
/** /**
* Pulling the provider into an object and using PURE works * Pulling the provider into an object and using PURE works

View File

@ -3,6 +3,14 @@
All notable changes to this project will be documented in this file. All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [8.3.4](https://github.com/ionic-team/ionic-framework/compare/v8.3.3...v8.3.4) (2024-10-30)
**Note:** Version bump only for package @ionic/docs
## [8.3.3](https://github.com/ionic-team/ionic-framework/compare/v8.3.2...v8.3.3) (2024-10-16) ## [8.3.3](https://github.com/ionic-team/ionic-framework/compare/v8.3.2...v8.3.3) (2024-10-16)
**Note:** Version bump only for package @ionic/docs **Note:** Version bump only for package @ionic/docs

View File

@ -1,12 +1,12 @@
{ {
"name": "@ionic/docs", "name": "@ionic/docs",
"version": "8.3.3", "version": "8.3.4",
"lockfileVersion": 2, "lockfileVersion": 2,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "@ionic/docs", "name": "@ionic/docs",
"version": "8.3.3", "version": "8.3.4",
"license": "MIT" "license": "MIT"
} }
} }

View File

@ -1,6 +1,6 @@
{ {
"name": "@ionic/docs", "name": "@ionic/docs",
"version": "8.3.3", "version": "8.3.4",
"description": "Pre-packaged API documentation for the Ionic docs.", "description": "Pre-packaged API documentation for the Ionic docs.",
"main": "core.json", "main": "core.json",
"types": "core.d.ts", "types": "core.d.ts",

View File

@ -3,6 +3,14 @@
All notable changes to this project will be documented in this file. All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [8.3.4](https://github.com/ionic-team/ionic-framework/compare/v8.3.3...v8.3.4) (2024-10-30)
**Note:** Version bump only for package @ionic/react-router
## [8.3.3](https://github.com/ionic-team/ionic-framework/compare/v8.3.2...v8.3.3) (2024-10-16) ## [8.3.3](https://github.com/ionic-team/ionic-framework/compare/v8.3.2...v8.3.3) (2024-10-16)
**Note:** Version bump only for package @ionic/react-router **Note:** Version bump only for package @ionic/react-router

View File

@ -1,15 +1,15 @@
{ {
"name": "@ionic/react-router", "name": "@ionic/react-router",
"version": "8.3.3", "version": "8.3.4",
"lockfileVersion": 2, "lockfileVersion": 2,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "@ionic/react-router", "name": "@ionic/react-router",
"version": "8.3.3", "version": "8.3.4",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@ionic/react": "^8.3.3", "@ionic/react": "^8.3.4",
"tslib": "*" "tslib": "*"
}, },
"devDependencies": { "devDependencies": {
@ -238,9 +238,9 @@
"dev": true "dev": true
}, },
"node_modules/@ionic/core": { "node_modules/@ionic/core": {
"version": "8.3.3", "version": "8.3.4",
"resolved": "https://registry.npmjs.org/@ionic/core/-/core-8.3.3.tgz", "resolved": "https://registry.npmjs.org/@ionic/core/-/core-8.3.4.tgz",
"integrity": "sha512-f2PXV0jFIFPdjP+NbmQ1mXqRQ4KWi0U0jdQd3wDYsJFWQLmWXhW7Yp/4lCDdl0ouMeZRB2phddqFct1c7H6PyA==", "integrity": "sha512-MkgaQ9+oQwj3AK/i25MkLgKUUH3/nvNjd4YlmUyFjPG7l2IBHsrLlSmuFGCyniB+doI9Hynu3T9CZP7NS4RjRQ==",
"dependencies": { "dependencies": {
"@stencil/core": "4.20.0", "@stencil/core": "4.20.0",
"ionicons": "^7.2.2", "ionicons": "^7.2.2",
@ -414,11 +414,11 @@
} }
}, },
"node_modules/@ionic/react": { "node_modules/@ionic/react": {
"version": "8.3.3", "version": "8.3.4",
"resolved": "https://registry.npmjs.org/@ionic/react/-/react-8.3.3.tgz", "resolved": "https://registry.npmjs.org/@ionic/react/-/react-8.3.4.tgz",
"integrity": "sha512-BQVke+4QF1viPmwYFV/Bfseh4AhLnA0svP8UvKTP45plJ2KDXF/IbFVNn+FWtjByrqYU4PldUgF01+O4yPGiRw==", "integrity": "sha512-CIoTHg/1nJJN11IjmsUqeQB1nIP4SxQyo2nBH+MhzeVCMv8Tj00Y4rU/9RYzKfRI7Zfsi9MOwVrwpGhPWi4KWA==",
"dependencies": { "dependencies": {
"@ionic/core": "8.3.3", "@ionic/core": "8.3.4",
"ionicons": "^7.0.0", "ionicons": "^7.0.0",
"tslib": "*" "tslib": "*"
}, },
@ -4057,9 +4057,9 @@
"dev": true "dev": true
}, },
"@ionic/core": { "@ionic/core": {
"version": "8.3.3", "version": "8.3.4",
"resolved": "https://registry.npmjs.org/@ionic/core/-/core-8.3.3.tgz", "resolved": "https://registry.npmjs.org/@ionic/core/-/core-8.3.4.tgz",
"integrity": "sha512-f2PXV0jFIFPdjP+NbmQ1mXqRQ4KWi0U0jdQd3wDYsJFWQLmWXhW7Yp/4lCDdl0ouMeZRB2phddqFct1c7H6PyA==", "integrity": "sha512-MkgaQ9+oQwj3AK/i25MkLgKUUH3/nvNjd4YlmUyFjPG7l2IBHsrLlSmuFGCyniB+doI9Hynu3T9CZP7NS4RjRQ==",
"requires": { "requires": {
"@stencil/core": "4.20.0", "@stencil/core": "4.20.0",
"ionicons": "^7.2.2", "ionicons": "^7.2.2",
@ -4163,11 +4163,11 @@
"requires": {} "requires": {}
}, },
"@ionic/react": { "@ionic/react": {
"version": "8.3.3", "version": "8.3.4",
"resolved": "https://registry.npmjs.org/@ionic/react/-/react-8.3.3.tgz", "resolved": "https://registry.npmjs.org/@ionic/react/-/react-8.3.4.tgz",
"integrity": "sha512-BQVke+4QF1viPmwYFV/Bfseh4AhLnA0svP8UvKTP45plJ2KDXF/IbFVNn+FWtjByrqYU4PldUgF01+O4yPGiRw==", "integrity": "sha512-CIoTHg/1nJJN11IjmsUqeQB1nIP4SxQyo2nBH+MhzeVCMv8Tj00Y4rU/9RYzKfRI7Zfsi9MOwVrwpGhPWi4KWA==",
"requires": { "requires": {
"@ionic/core": "8.3.3", "@ionic/core": "8.3.4",
"ionicons": "^7.0.0", "ionicons": "^7.0.0",
"tslib": "*" "tslib": "*"
} }

View File

@ -1,6 +1,6 @@
{ {
"name": "@ionic/react-router", "name": "@ionic/react-router",
"version": "8.3.3", "version": "8.3.4",
"description": "React Router wrapper for @ionic/react", "description": "React Router wrapper for @ionic/react",
"keywords": [ "keywords": [
"ionic", "ionic",
@ -36,7 +36,7 @@
"dist/" "dist/"
], ],
"dependencies": { "dependencies": {
"@ionic/react": "^8.3.3", "@ionic/react": "^8.3.4",
"tslib": "*" "tslib": "*"
}, },
"peerDependencies": { "peerDependencies": {

View File

@ -3,6 +3,14 @@
All notable changes to this project will be documented in this file. All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [8.3.4](https://github.com/ionic-team/ionic-framework/compare/v8.3.3...v8.3.4) (2024-10-30)
**Note:** Version bump only for package @ionic/react
## [8.3.3](https://github.com/ionic-team/ionic-framework/compare/v8.3.2...v8.3.3) (2024-10-16) ## [8.3.3](https://github.com/ionic-team/ionic-framework/compare/v8.3.2...v8.3.3) (2024-10-16)

View File

@ -1,15 +1,15 @@
{ {
"name": "@ionic/react", "name": "@ionic/react",
"version": "8.3.3", "version": "8.3.4",
"lockfileVersion": 2, "lockfileVersion": 2,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "@ionic/react", "name": "@ionic/react",
"version": "8.3.3", "version": "8.3.4",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@ionic/core": "^8.3.3", "@ionic/core": "^8.3.4",
"ionicons": "^7.0.0", "ionicons": "^7.0.0",
"tslib": "*" "tslib": "*"
}, },
@ -736,9 +736,9 @@
"dev": true "dev": true
}, },
"node_modules/@ionic/core": { "node_modules/@ionic/core": {
"version": "8.3.3", "version": "8.3.4",
"resolved": "https://registry.npmjs.org/@ionic/core/-/core-8.3.3.tgz", "resolved": "https://registry.npmjs.org/@ionic/core/-/core-8.3.4.tgz",
"integrity": "sha512-f2PXV0jFIFPdjP+NbmQ1mXqRQ4KWi0U0jdQd3wDYsJFWQLmWXhW7Yp/4lCDdl0ouMeZRB2phddqFct1c7H6PyA==", "integrity": "sha512-MkgaQ9+oQwj3AK/i25MkLgKUUH3/nvNjd4YlmUyFjPG7l2IBHsrLlSmuFGCyniB+doI9Hynu3T9CZP7NS4RjRQ==",
"dependencies": { "dependencies": {
"@stencil/core": "4.20.0", "@stencil/core": "4.20.0",
"ionicons": "^7.2.2", "ionicons": "^7.2.2",
@ -12315,9 +12315,9 @@
"dev": true "dev": true
}, },
"@ionic/core": { "@ionic/core": {
"version": "8.3.3", "version": "8.3.4",
"resolved": "https://registry.npmjs.org/@ionic/core/-/core-8.3.3.tgz", "resolved": "https://registry.npmjs.org/@ionic/core/-/core-8.3.4.tgz",
"integrity": "sha512-f2PXV0jFIFPdjP+NbmQ1mXqRQ4KWi0U0jdQd3wDYsJFWQLmWXhW7Yp/4lCDdl0ouMeZRB2phddqFct1c7H6PyA==", "integrity": "sha512-MkgaQ9+oQwj3AK/i25MkLgKUUH3/nvNjd4YlmUyFjPG7l2IBHsrLlSmuFGCyniB+doI9Hynu3T9CZP7NS4RjRQ==",
"requires": { "requires": {
"@stencil/core": "4.20.0", "@stencil/core": "4.20.0",
"ionicons": "^7.2.2", "ionicons": "^7.2.2",

View File

@ -1,6 +1,6 @@
{ {
"name": "@ionic/react", "name": "@ionic/react",
"version": "8.3.3", "version": "8.3.4",
"description": "React specific wrapper for @ionic/core", "description": "React specific wrapper for @ionic/core",
"keywords": [ "keywords": [
"ionic", "ionic",
@ -39,7 +39,7 @@
"css/" "css/"
], ],
"dependencies": { "dependencies": {
"@ionic/core": "^8.3.3", "@ionic/core": "^8.3.4",
"ionicons": "^7.0.0", "ionicons": "^7.0.0",
"tslib": "*" "tslib": "*"
}, },

View File

@ -3,6 +3,17 @@
All notable changes to this project will be documented in this file. All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [8.3.4](https://github.com/ionic-team/ionic-framework/compare/v8.3.3...v8.3.4) (2024-10-30)
### Bug Fixes
* **vue:** incorrect view rendered when using router.go(-n) ([#29877](https://github.com/ionic-team/ionic-framework/issues/29877)) ([e32fbe0](https://github.com/ionic-team/ionic-framework/commit/e32fbe02102fe80db29f73c26496a40852032354)), closes [#28201](https://github.com/ionic-team/ionic-framework/issues/28201) [#28201](https://github.com/ionic-team/ionic-framework/issues/28201) [#29847](https://github.com/ionic-team/ionic-framework/issues/29847)
## [8.3.3](https://github.com/ionic-team/ionic-framework/compare/v8.3.2...v8.3.3) (2024-10-16) ## [8.3.3](https://github.com/ionic-team/ionic-framework/compare/v8.3.2...v8.3.3) (2024-10-16)
**Note:** Version bump only for package @ionic/vue-router **Note:** Version bump only for package @ionic/vue-router

View File

@ -84,4 +84,25 @@ describe('Location History', () => {
expect(locationHistory.canGoBack(1, 0, 1)).toEqual(true); expect(locationHistory.canGoBack(1, 0, 1)).toEqual(true);
expect(locationHistory.canGoBack(2, 0, 1)).toEqual(false); expect(locationHistory.canGoBack(2, 0, 1)).toEqual(false);
}); });
it('should correctly find the last location', () => {
const [home, pageA, pageB, pageC] = [
{ pathname: '/home' },
{ pathname: '/page-a', pushedByRoute: '/home' },
{ pathname: '/page-b', pushedByRoute: '/page-a' },
{ pathname: '/page-c', pushedByRoute: '/page-b' },
];
locationHistory.add(home);
locationHistory.add(pageA);
locationHistory.add(pageB);
locationHistory.add(pageC);
expect(locationHistory.findLastLocation(pageB)).toEqual(pageA);
expect(locationHistory.findLastLocation(pageB, -2)).toEqual(home);
expect(locationHistory.findLastLocation(pageC)).toEqual(pageB);
expect(locationHistory.findLastLocation(pageC, -2)).toEqual(pageA);
expect(locationHistory.findLastLocation(pageC, -3)).toEqual(home);
});
}); });

View File

@ -1,15 +1,15 @@
{ {
"name": "@ionic/vue-router", "name": "@ionic/vue-router",
"version": "8.3.3", "version": "8.3.4",
"lockfileVersion": 2, "lockfileVersion": 2,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "@ionic/vue-router", "name": "@ionic/vue-router",
"version": "8.3.3", "version": "8.3.4",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@ionic/vue": "^8.3.3" "@ionic/vue": "^8.3.4"
}, },
"devDependencies": { "devDependencies": {
"@ionic/eslint-config": "^0.3.0", "@ionic/eslint-config": "^0.3.0",
@ -661,9 +661,9 @@
"dev": true "dev": true
}, },
"node_modules/@ionic/core": { "node_modules/@ionic/core": {
"version": "8.3.3", "version": "8.3.4",
"resolved": "https://registry.npmjs.org/@ionic/core/-/core-8.3.3.tgz", "resolved": "https://registry.npmjs.org/@ionic/core/-/core-8.3.4.tgz",
"integrity": "sha512-f2PXV0jFIFPdjP+NbmQ1mXqRQ4KWi0U0jdQd3wDYsJFWQLmWXhW7Yp/4lCDdl0ouMeZRB2phddqFct1c7H6PyA==", "integrity": "sha512-MkgaQ9+oQwj3AK/i25MkLgKUUH3/nvNjd4YlmUyFjPG7l2IBHsrLlSmuFGCyniB+doI9Hynu3T9CZP7NS4RjRQ==",
"dependencies": { "dependencies": {
"@stencil/core": "4.20.0", "@stencil/core": "4.20.0",
"ionicons": "^7.2.2", "ionicons": "^7.2.2",
@ -852,11 +852,11 @@
} }
}, },
"node_modules/@ionic/vue": { "node_modules/@ionic/vue": {
"version": "8.3.3", "version": "8.3.4",
"resolved": "https://registry.npmjs.org/@ionic/vue/-/vue-8.3.3.tgz", "resolved": "https://registry.npmjs.org/@ionic/vue/-/vue-8.3.4.tgz",
"integrity": "sha512-6EAPWdmQDvazP4ZsCRjWlG91Kx+1vYxX1gHx02Xvcc7Dn8hRrMW58IAAQ0BqSYsrHNFTKVtwD3cJbmnut8Ghyg==", "integrity": "sha512-s7P5mTd078CbPK2dpIxxWGNirQacG3sXhJulJ1L0J6+6VI+HHHLKy4ueTRgPl5GLDmjGgdMCBuYu1n4K2nNXFg==",
"dependencies": { "dependencies": {
"@ionic/core": "8.3.3", "@ionic/core": "8.3.4",
"ionicons": "^7.0.0" "ionicons": "^7.0.0"
} }
}, },
@ -7878,9 +7878,9 @@
"dev": true "dev": true
}, },
"@ionic/core": { "@ionic/core": {
"version": "8.3.3", "version": "8.3.4",
"resolved": "https://registry.npmjs.org/@ionic/core/-/core-8.3.3.tgz", "resolved": "https://registry.npmjs.org/@ionic/core/-/core-8.3.4.tgz",
"integrity": "sha512-f2PXV0jFIFPdjP+NbmQ1mXqRQ4KWi0U0jdQd3wDYsJFWQLmWXhW7Yp/4lCDdl0ouMeZRB2phddqFct1c7H6PyA==", "integrity": "sha512-MkgaQ9+oQwj3AK/i25MkLgKUUH3/nvNjd4YlmUyFjPG7l2IBHsrLlSmuFGCyniB+doI9Hynu3T9CZP7NS4RjRQ==",
"requires": { "requires": {
"@stencil/core": "4.20.0", "@stencil/core": "4.20.0",
"ionicons": "^7.2.2", "ionicons": "^7.2.2",
@ -7993,11 +7993,11 @@
"requires": {} "requires": {}
}, },
"@ionic/vue": { "@ionic/vue": {
"version": "8.3.3", "version": "8.3.4",
"resolved": "https://registry.npmjs.org/@ionic/vue/-/vue-8.3.3.tgz", "resolved": "https://registry.npmjs.org/@ionic/vue/-/vue-8.3.4.tgz",
"integrity": "sha512-6EAPWdmQDvazP4ZsCRjWlG91Kx+1vYxX1gHx02Xvcc7Dn8hRrMW58IAAQ0BqSYsrHNFTKVtwD3cJbmnut8Ghyg==", "integrity": "sha512-s7P5mTd078CbPK2dpIxxWGNirQacG3sXhJulJ1L0J6+6VI+HHHLKy4ueTRgPl5GLDmjGgdMCBuYu1n4K2nNXFg==",
"requires": { "requires": {
"@ionic/core": "8.3.3", "@ionic/core": "8.3.4",
"ionicons": "^7.0.0" "ionicons": "^7.0.0"
} }
}, },

View File

@ -1,6 +1,6 @@
{ {
"name": "@ionic/vue-router", "name": "@ionic/vue-router",
"version": "8.3.3", "version": "8.3.4",
"description": "Vue Router integration for @ionic/vue", "description": "Vue Router integration for @ionic/vue",
"scripts": { "scripts": {
"test.spec": "jest", "test.spec": "jest",
@ -44,7 +44,7 @@
}, },
"homepage": "https://github.com/ionic-team/ionic-framework#readme", "homepage": "https://github.com/ionic-team/ionic-framework#readme",
"dependencies": { "dependencies": {
"@ionic/vue": "^8.3.3" "@ionic/vue": "^8.3.4"
}, },
"devDependencies": { "devDependencies": {
"@ionic/eslint-config": "^0.3.0", "@ionic/eslint-config": "^0.3.0",

View File

@ -239,15 +239,11 @@ export const createLocationHistory = () => {
} }
} }
} }
if (delta < -1) {
return locationHistory[locationHistory.length - 1 + delta];
} else {
for (let i = locationHistory.length - 2; i >= 0; i--) { for (let i = locationHistory.length - 2; i >= 0; i--) {
const ri = locationHistory[i]; const ri = locationHistory[i];
if (ri) { if (ri) {
if (ri.pathname === routeInfo.pushedByRoute) { if (ri.pathname === routeInfo.pushedByRoute) {
return ri; return locationHistory[i + 1 + delta]
}
} }
} }
} }

View File

@ -3,6 +3,14 @@
All notable changes to this project will be documented in this file. All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [8.3.4](https://github.com/ionic-team/ionic-framework/compare/v8.3.3...v8.3.4) (2024-10-30)
**Note:** Version bump only for package @ionic/vue
## [8.3.3](https://github.com/ionic-team/ionic-framework/compare/v8.3.2...v8.3.3) (2024-10-16) ## [8.3.3](https://github.com/ionic-team/ionic-framework/compare/v8.3.2...v8.3.3) (2024-10-16)

View File

@ -1,15 +1,15 @@
{ {
"name": "@ionic/vue", "name": "@ionic/vue",
"version": "8.3.3", "version": "8.3.4",
"lockfileVersion": 2, "lockfileVersion": 2,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "@ionic/vue", "name": "@ionic/vue",
"version": "8.3.3", "version": "8.3.4",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@ionic/core": "^8.3.3", "@ionic/core": "^8.3.4",
"ionicons": "^7.0.0" "ionicons": "^7.0.0"
}, },
"devDependencies": { "devDependencies": {
@ -208,9 +208,9 @@
"dev": true "dev": true
}, },
"node_modules/@ionic/core": { "node_modules/@ionic/core": {
"version": "8.3.3", "version": "8.3.4",
"resolved": "https://registry.npmjs.org/@ionic/core/-/core-8.3.3.tgz", "resolved": "https://registry.npmjs.org/@ionic/core/-/core-8.3.4.tgz",
"integrity": "sha512-f2PXV0jFIFPdjP+NbmQ1mXqRQ4KWi0U0jdQd3wDYsJFWQLmWXhW7Yp/4lCDdl0ouMeZRB2phddqFct1c7H6PyA==", "integrity": "sha512-MkgaQ9+oQwj3AK/i25MkLgKUUH3/nvNjd4YlmUyFjPG7l2IBHsrLlSmuFGCyniB+doI9Hynu3T9CZP7NS4RjRQ==",
"dependencies": { "dependencies": {
"@stencil/core": "4.20.0", "@stencil/core": "4.20.0",
"ionicons": "^7.2.2", "ionicons": "^7.2.2",
@ -3970,9 +3970,9 @@
"dev": true "dev": true
}, },
"@ionic/core": { "@ionic/core": {
"version": "8.3.3", "version": "8.3.4",
"resolved": "https://registry.npmjs.org/@ionic/core/-/core-8.3.3.tgz", "resolved": "https://registry.npmjs.org/@ionic/core/-/core-8.3.4.tgz",
"integrity": "sha512-f2PXV0jFIFPdjP+NbmQ1mXqRQ4KWi0U0jdQd3wDYsJFWQLmWXhW7Yp/4lCDdl0ouMeZRB2phddqFct1c7H6PyA==", "integrity": "sha512-MkgaQ9+oQwj3AK/i25MkLgKUUH3/nvNjd4YlmUyFjPG7l2IBHsrLlSmuFGCyniB+doI9Hynu3T9CZP7NS4RjRQ==",
"requires": { "requires": {
"@stencil/core": "4.20.0", "@stencil/core": "4.20.0",
"ionicons": "^7.2.2", "ionicons": "^7.2.2",

View File

@ -1,6 +1,6 @@
{ {
"name": "@ionic/vue", "name": "@ionic/vue",
"version": "8.3.3", "version": "8.3.4",
"description": "Vue specific wrapper for @ionic/core", "description": "Vue specific wrapper for @ionic/core",
"scripts": { "scripts": {
"eslint": "eslint src", "eslint": "eslint src",
@ -66,7 +66,7 @@
"vue-router": "^4.0.16" "vue-router": "^4.0.16"
}, },
"dependencies": { "dependencies": {
"@ionic/core": "^8.3.3", "@ionic/core": "^8.3.4",
"ionicons": "^7.0.0" "ionicons": "^7.0.0"
}, },
"vetur": { "vetur": {