From b9e3cf0f5aae79a1f27a07b102c77e51f24825f4 Mon Sep 17 00:00:00 2001 From: Shane Date: Wed, 10 Dec 2025 13:08:48 -0800 Subject: [PATCH 1/4] fix(modal): allow interaction with parent content through sheet modals in child routes (#30839) Issue number: resolves #30700 --------- ## What is the current behavior? When a sheet modal with showBackdrop=false is rendered in a child route (nested ion-router-outlet), the parent content becomes non-interactive. Clicks on buttons or other interactive elements in the parent component are blocked, even though showBackdrop=false should allow background interaction. Two separate issues contributed to this bug: 1. **Root locking with `backdropBreakpoint`**: The `shouldLockRoot` logic in `overlays.ts` didn't account for `backdropBreakpoint`. Modals with `backdropBreakpoint > 0` were still locking the root with `aria-hidden`, even though developers expect background interaction when the modal is below the backdrop breakpoint. 2. **Child route wrapper blocking**: When a modal is in a child route, the child route's page wrapper (`ion-page`) and its parent `ion-router-outlet` remain in the DOM with `position: absolute` covering the viewport. Even after the modal is moved to `ion-app` and has `pointer-events: none`, these wrapper elements block clicks to the parent page's content. This issue stems from [#30563](https://github.com/ionic-team/ionic-framework/pull/30563), which added root-locking behavior that didn't account for modals that allow background interaction. A partial fix in [#30689](https://github.com/ionic-team/ionic-framework/pull/30689) partially addressed `showBackdrop=false` and `focusTrap=false`, but missed `backdropBreakpoint`. ## What is the new behavior? Sheet modals with showBackdrop=false or focusTrap=false now correctly allow interaction with parent content when the modal is in a child route. Improvements: - Recalculates isSheetModal in present() to handle Angular binding timing - Sets pointer-events: none on the modal element and its original parent elements when background interaction should be allowed - Cleans up pointer-events on dismiss - Adds regression tests ## Does this introduce a breaking change? - [ ] Yes - [X] No ## Other information Dev build: ``` 8.7.12-dev.11765060985.14ad27fb ``` --- core/src/components/modal/modal.tsx | 100 +++++++++++++++++- core/src/css/core.scss | 9 ++ core/src/utils/overlays.ts | 28 +++-- .../src/standalone/modal-child-route.spec.ts | 38 +++++++ .../standalone/app-standalone/app.routes.ts | 8 ++ .../home-page/home-page.component.html | 5 + .../modal-child-route-child.component.ts | 33 ++++++ .../modal-child-route-parent.component.ts | 38 +++++++ .../ModalSheetChildRoute.tsx | 69 ++++++++++++ .../overlay-components/OverlayComponents.tsx | 6 ++ .../IonModalFocusTrap.cy.ts | 6 +- .../IonModalSheetChildRoute.cy.ts | 37 +++++++ 12 files changed, 365 insertions(+), 12 deletions(-) create mode 100644 packages/angular/test/base/e2e/src/standalone/modal-child-route.spec.ts create mode 100644 packages/angular/test/base/src/app/standalone/modal-child-route/modal-child-route-child.component.ts create mode 100644 packages/angular/test/base/src/app/standalone/modal-child-route/modal-child-route-parent.component.ts create mode 100644 packages/react/test/base/src/pages/overlay-components/ModalSheetChildRoute.tsx create mode 100644 packages/react/test/base/tests/e2e/specs/overlay-components/IonModalSheetChildRoute.cy.ts diff --git a/core/src/components/modal/modal.tsx b/core/src/components/modal/modal.tsx index b1a494430d0..dbed406ca4a 100644 --- a/core/src/components/modal/modal.tsx +++ b/core/src/components/modal/modal.tsx @@ -71,7 +71,7 @@ export class Modal implements ComponentInterface, OverlayInterface { private gesture?: Gesture; private coreDelegate: FrameworkDelegate = CoreDelegate(); private sheetTransition?: Promise; - private isSheetModal = false; + @State() private isSheetModal = false; private currentBreakpoint?: number; private wrapperEl?: HTMLElement; private backdropEl?: HTMLIonBackdropElement; @@ -100,6 +100,8 @@ export class Modal implements ComponentInterface, OverlayInterface { private parentRemovalObserver?: MutationObserver; // Cached original parent from before modal is moved to body during presentation private cachedOriginalParent?: HTMLElement; + // Cached ion-page ancestor for child route passthrough + private cachedPageParent?: HTMLElement | null; lastFocus?: HTMLElement; animation?: Animation; @@ -644,7 +646,14 @@ export class Modal implements ComponentInterface, OverlayInterface { window.addEventListener(KEYBOARD_DID_OPEN, this.keyboardOpenCallback); } - if (this.isSheetModal) { + /** + * Recalculate isSheetModal because framework bindings (e.g., Angular) + * may not have been applied when componentWillLoad ran. + */ + const isSheetModal = this.breakpoints !== undefined && this.initialBreakpoint !== undefined; + this.isSheetModal = isSheetModal; + + if (isSheetModal) { this.initSheetGesture(); } else if (hasCardModal) { this.initSwipeToClose(); @@ -753,6 +762,91 @@ export class Modal implements ComponentInterface, OverlayInterface { this.moveSheetToBreakpoint = moveSheetToBreakpoint; this.gesture.enable(true); + + /** + * When backdrop interaction is allowed, nested router outlets from child routes + * may block pointer events to parent content. Apply passthrough styles only when + * the modal was the sole content of a child route page. + * See https://github.com/ionic-team/ionic-framework/issues/30700 + */ + const backdropNotBlocking = this.showBackdrop === false || this.focusTrap === false || backdropBreakpoint > 0; + if (backdropNotBlocking) { + this.setupChildRoutePassthrough(); + } + } + + /** + * For sheet modals that allow background interaction, sets up pointer-events + * passthrough on child route page wrappers and nested router outlets. + */ + private setupChildRoutePassthrough() { + // Cache the page parent for cleanup + this.cachedPageParent = this.getOriginalPageParent(); + const pageParent = this.cachedPageParent; + + // Skip ion-app (controller modals) and pages with visible sibling content next to the modal + if (!pageParent || pageParent.tagName === 'ION-APP') { + return; + } + + const hasVisibleContent = Array.from(pageParent.children).some( + (child) => + child !== this.el && + !(child instanceof HTMLElement && window.getComputedStyle(child).display === 'none') && + child.tagName !== 'TEMPLATE' && + child.tagName !== 'SLOT' && + !(child.nodeType === Node.TEXT_NODE && !child.textContent?.trim()) + ); + + if (hasVisibleContent) { + return; + } + + // Child route case: page only contained the modal + pageParent.classList.add('ion-page-overlay-passthrough'); + + // Also make nested router outlets passthrough + const routerOutlet = pageParent.parentElement; + if (routerOutlet?.tagName === 'ION-ROUTER-OUTLET' && routerOutlet.parentElement?.tagName !== 'ION-APP') { + routerOutlet.style.setProperty('pointer-events', 'none'); + routerOutlet.setAttribute('data-overlay-passthrough', 'true'); + } + } + + /** + * Finds the ion-page ancestor of the modal's original parent location. + */ + private getOriginalPageParent(): HTMLElement | null { + if (!this.cachedOriginalParent) { + return null; + } + + let pageParent: HTMLElement | null = this.cachedOriginalParent; + while (pageParent && !pageParent.classList.contains('ion-page')) { + pageParent = pageParent.parentElement; + } + return pageParent; + } + + /** + * Removes passthrough styles added by setupChildRoutePassthrough. + */ + private cleanupChildRoutePassthrough() { + const pageParent = this.cachedPageParent; + if (!pageParent) { + return; + } + + pageParent.classList.remove('ion-page-overlay-passthrough'); + + const routerOutlet = pageParent.parentElement; + if (routerOutlet?.hasAttribute('data-overlay-passthrough')) { + routerOutlet.style.removeProperty('pointer-events'); + routerOutlet.removeAttribute('data-overlay-passthrough'); + } + + // Clear the cached reference + this.cachedPageParent = undefined; } private sheetOnDismiss() { @@ -862,6 +956,8 @@ export class Modal implements ComponentInterface, OverlayInterface { } this.cleanupViewTransitionListener(); this.cleanupParentRemovalObserver(); + + this.cleanupChildRoutePassthrough(); } this.currentBreakpoint = undefined; this.animation = undefined; diff --git a/core/src/css/core.scss b/core/src/css/core.scss index cf7560bd348..db694fc6a07 100644 --- a/core/src/css/core.scss +++ b/core/src/css/core.scss @@ -181,6 +181,15 @@ html.ios ion-modal.modal-card .ion-page { z-index: $z-index-page-container; } +/** + * Allows pointer events to pass through child route page wrappers + * when they only contain a sheet modal that permits background interaction. + * https://github.com/ionic-team/ionic-framework/issues/30700 + */ +.ion-page.ion-page-overlay-passthrough { + pointer-events: none; +} + /** * When making custom dialogs, using * ion-content is not required. As a result, diff --git a/core/src/utils/overlays.ts b/core/src/utils/overlays.ts index 5b983158aa5..472a57559d3 100644 --- a/core/src/utils/overlays.ts +++ b/core/src/utils/overlays.ts @@ -38,6 +38,20 @@ let lastId = 0; export const activeAnimations = new WeakMap(); +type OverlayWithFocusTrapProps = HTMLIonOverlayElement & { + focusTrap?: boolean; + showBackdrop?: boolean; + backdropBreakpoint?: number; +}; + +/** + * Determines if the overlay's backdrop is always blocking (no background interaction). + * Returns false if showBackdrop=false or backdropBreakpoint > 0. + */ +const isBackdropAlwaysBlocking = (el: OverlayWithFocusTrapProps): boolean => { + return el.showBackdrop !== false && !((el.backdropBreakpoint ?? 0) > 0); +}; + const createController = (tagName: string) => { return { create(options: Opts): Promise { @@ -539,11 +553,9 @@ export const present = async ( * view container subtree, skip adding aria-hidden/inert there * to avoid disabling the overlay. */ - const overlayEl = overlay.el as HTMLIonOverlayElement & { focusTrap?: boolean; showBackdrop?: boolean }; + const overlayEl = overlay.el as OverlayWithFocusTrapProps; const shouldTrapFocus = overlayEl.tagName !== 'ION-TOAST' && overlayEl.focusTrap !== false; - // Only lock out root content when backdrop is active. Developers relying on showBackdrop=false - // expect background interaction to remain enabled. - const shouldLockRoot = shouldTrapFocus && overlayEl.showBackdrop !== false; + const shouldLockRoot = shouldTrapFocus && isBackdropAlwaysBlocking(overlayEl); overlay.presented = true; overlay.willPresent.emit(); @@ -680,12 +692,12 @@ export const dismiss = async ( * is dismissed. */ const overlaysLockingRoot = presentedOverlays.filter((o) => { - const el = o as HTMLIonOverlayElement & { focusTrap?: boolean; showBackdrop?: boolean }; - return el.tagName !== 'ION-TOAST' && el.focusTrap !== false && el.showBackdrop !== false; + const el = o as OverlayWithFocusTrapProps; + return el.tagName !== 'ION-TOAST' && el.focusTrap !== false && isBackdropAlwaysBlocking(el); }); - const overlayEl = overlay.el as HTMLIonOverlayElement & { focusTrap?: boolean; showBackdrop?: boolean }; + const overlayEl = overlay.el as OverlayWithFocusTrapProps; const locksRoot = - overlayEl.tagName !== 'ION-TOAST' && overlayEl.focusTrap !== false && overlayEl.showBackdrop !== false; + overlayEl.tagName !== 'ION-TOAST' && overlayEl.focusTrap !== false && isBackdropAlwaysBlocking(overlayEl); /** * If this is the last visible overlay that is trapping focus diff --git a/packages/angular/test/base/e2e/src/standalone/modal-child-route.spec.ts b/packages/angular/test/base/e2e/src/standalone/modal-child-route.spec.ts new file mode 100644 index 00000000000..d479599bccb --- /dev/null +++ b/packages/angular/test/base/e2e/src/standalone/modal-child-route.spec.ts @@ -0,0 +1,38 @@ +import { expect, test } from '@playwright/test'; + +/** + * Tests for sheet modals in child routes with showBackdrop=false. + * Parent has buttons + nested outlet; child route contains only the modal. + * See https://github.com/ionic-team/ionic-framework/issues/30700 + */ +test.describe('Modals: Inline Sheet in Child Route (standalone)', () => { + test.beforeEach(async ({ page }) => { + await page.goto('/standalone/modal-child-route/child'); + }); + + test('should render parent content and child modal', async ({ page }) => { + await expect(page.locator('#increment-btn')).toBeVisible(); + await expect(page.locator('#decrement-btn')).toBeVisible(); + await expect(page.locator('#background-action-count')).toHaveText('0'); + await expect(page.locator('ion-modal.show-modal')).toBeVisible(); + await expect(page.locator('#modal-content-loaded')).toBeVisible(); + }); + + test('should allow interacting with parent content while modal is open in child route', async ({ page }) => { + await expect(page.locator('ion-modal.show-modal')).toBeVisible(); + + await page.locator('#increment-btn').click(); + await expect(page.locator('#background-action-count')).toHaveText('1'); + }); + + test('should allow multiple interactions with parent content while modal is open', async ({ page }) => { + await expect(page.locator('ion-modal.show-modal')).toBeVisible(); + + await page.locator('#increment-btn').click(); + await page.locator('#increment-btn').click(); + await expect(page.locator('#background-action-count')).toHaveText('2'); + + await page.locator('#decrement-btn').click(); + await expect(page.locator('#background-action-count')).toHaveText('1'); + }); +}); diff --git a/packages/angular/test/base/src/app/standalone/app-standalone/app.routes.ts b/packages/angular/test/base/src/app/standalone/app-standalone/app.routes.ts index 007743f905f..667ef672e8b 100644 --- a/packages/angular/test/base/src/app/standalone/app-standalone/app.routes.ts +++ b/packages/angular/test/base/src/app/standalone/app-standalone/app.routes.ts @@ -13,6 +13,14 @@ export const routes: Routes = [ { path: 'modal', loadComponent: () => import('../modal/modal.component').then(c => c.ModalComponent) }, { path: 'modal-sheet-inline', loadComponent: () => import('../modal-sheet-inline/modal-sheet-inline.component').then(c => c.ModalSheetInlineComponent) }, { path: 'modal-dynamic-wrapper', loadComponent: () => import('../modal-dynamic-wrapper/modal-dynamic-wrapper.component').then(c => c.ModalDynamicWrapperComponent) }, + { path: 'modal-child-route', redirectTo: '/standalone/modal-child-route/child', pathMatch: 'full' }, + { + path: 'modal-child-route', + loadComponent: () => import('../modal-child-route/modal-child-route-parent.component').then(c => c.ModalChildRouteParentComponent), + children: [ + { path: 'child', loadComponent: () => import('../modal-child-route/modal-child-route-child.component').then(c => c.ModalChildRouteChildComponent) }, + ] + }, { path: 'programmatic-modal', loadComponent: () => import('../programmatic-modal/programmatic-modal.component').then(c => c.ProgrammaticModalComponent) }, { path: 'router-outlet', loadComponent: () => import('../router-outlet/router-outlet.component').then(c => c.RouterOutletComponent) }, { path: 'back-button', loadComponent: () => import('../back-button/back-button.component').then(c => c.BackButtonComponent) }, diff --git a/packages/angular/test/base/src/app/standalone/home-page/home-page.component.html b/packages/angular/test/base/src/app/standalone/home-page/home-page.component.html index 7ac9c619180..6dbad643eb2 100644 --- a/packages/angular/test/base/src/app/standalone/home-page/home-page.component.html +++ b/packages/angular/test/base/src/app/standalone/home-page/home-page.component.html @@ -100,6 +100,11 @@ Modal Dynamic Wrapper Test + + + Modal Child Route Test + + Programmatic Modal Test diff --git a/packages/angular/test/base/src/app/standalone/modal-child-route/modal-child-route-child.component.ts b/packages/angular/test/base/src/app/standalone/modal-child-route/modal-child-route-child.component.ts new file mode 100644 index 00000000000..6fa573fa197 --- /dev/null +++ b/packages/angular/test/base/src/app/standalone/modal-child-route/modal-child-route-child.component.ts @@ -0,0 +1,33 @@ +import { CommonModule } from '@angular/common'; +import { Component } from '@angular/core'; +import { IonContent, IonHeader, IonModal, IonTitle, IonToolbar } from '@ionic/angular/standalone'; + +/** + * Child route component containing only the sheet modal with showBackdrop=false. + * Verifies issue https://github.com/ionic-team/ionic-framework/issues/30700 + */ +@Component({ + selector: 'app-modal-child-route-child', + template: ` + + + + + Modal in Child Route + + + + + + + + `, + standalone: true, + imports: [CommonModule, IonContent, IonHeader, IonModal, IonTitle, IonToolbar], +}) +export class ModalChildRouteChildComponent {} diff --git a/packages/angular/test/base/src/app/standalone/modal-child-route/modal-child-route-parent.component.ts b/packages/angular/test/base/src/app/standalone/modal-child-route/modal-child-route-parent.component.ts new file mode 100644 index 00000000000..fdd5465ad11 --- /dev/null +++ b/packages/angular/test/base/src/app/standalone/modal-child-route/modal-child-route-parent.component.ts @@ -0,0 +1,38 @@ +import { Component } from '@angular/core'; +import { IonButton, IonContent, IonHeader, IonRouterOutlet, IonTitle, IonToolbar } from '@ionic/angular/standalone'; + +/** + * Parent with interactive buttons and nested outlet for child route modal. + * See https://github.com/ionic-team/ionic-framework/issues/30700 + */ +@Component({ + selector: 'app-modal-child-route-parent', + template: ` + + + Parent Page with Nested Route + + + +
+ - +

{{ count }}

+ + +
+ +
+ `, + standalone: true, + imports: [IonButton, IonContent, IonHeader, IonRouterOutlet, IonTitle, IonToolbar], +}) +export class ModalChildRouteParentComponent { + count = 0; + + increment() { + this.count++; + } + + decrement() { + this.count--; + } +} diff --git a/packages/react/test/base/src/pages/overlay-components/ModalSheetChildRoute.tsx b/packages/react/test/base/src/pages/overlay-components/ModalSheetChildRoute.tsx new file mode 100644 index 00000000000..e686bbd00eb --- /dev/null +++ b/packages/react/test/base/src/pages/overlay-components/ModalSheetChildRoute.tsx @@ -0,0 +1,69 @@ +import React, { useState } from 'react'; +import { + IonButton, + IonContent, + IonHeader, + IonModal, + IonPage, + IonRouterOutlet, + IonTitle, + IonToolbar, +} from '@ionic/react'; +import { Route } from 'react-router'; + +/** + * Parent component with counter buttons and nested router outlet. + * This reproduces the issue from https://github.com/ionic-team/ionic-framework/issues/30700 + * where sheet modals in child routes with showBackdrop=false block interaction with parent content. + */ +const ModalSheetChildRouteParent: React.FC = () => { + const [count, setCount] = useState(0); + + return ( + + + + Parent Page with Nested Route + + + +
+ setCount((c) => c - 1)}> + - + +

{count}

+ setCount((c) => c + 1)}> + + + +
+
+ + + +
+ ); +}; + +const ModalSheetChildRouteChild: React.FC = () => { + return ( + + + + + Modal in Child Route + + + + + + + + ); +}; + +export default ModalSheetChildRouteParent; diff --git a/packages/react/test/base/src/pages/overlay-components/OverlayComponents.tsx b/packages/react/test/base/src/pages/overlay-components/OverlayComponents.tsx index 19aebc9081c..75bf98bb734 100644 --- a/packages/react/test/base/src/pages/overlay-components/OverlayComponents.tsx +++ b/packages/react/test/base/src/pages/overlay-components/OverlayComponents.tsx @@ -15,6 +15,7 @@ import AlertComponent from './AlertComponent'; import LoadingComponent from './LoadingComponent'; import ModalComponent from './ModalComponent'; import ModalFocusTrap from './ModalFocusTrap'; +import ModalSheetChildRoute from './ModalSheetChildRoute'; import ModalTeleport from './ModalTeleport'; import PickerComponent from './PickerComponent'; import PopoverComponent from './PopoverComponent'; @@ -32,6 +33,7 @@ const OverlayHooks: React.FC = () => { + @@ -62,6 +64,10 @@ const OverlayHooks: React.FC = () => { Modal Teleport + + + Sheet Child + Picker diff --git a/packages/react/test/base/tests/e2e/specs/overlay-components/IonModalFocusTrap.cy.ts b/packages/react/test/base/tests/e2e/specs/overlay-components/IonModalFocusTrap.cy.ts index 395c642dcc4..78ca7a581e3 100644 --- a/packages/react/test/base/tests/e2e/specs/overlay-components/IonModalFocusTrap.cy.ts +++ b/packages/react/test/base/tests/e2e/specs/overlay-components/IonModalFocusTrap.cy.ts @@ -5,7 +5,9 @@ describe('IonModal: focusTrap regression', () => { it('should allow interacting with background when focusTrap=false', () => { cy.get('#open-non-trapped-modal').click(); - cy.get('ion-modal').should('be.visible'); + // Use 'exist' instead of 'be.visible' because the modal has pointer-events: none + // to allow background interaction, which Cypress interprets as "covered" + cy.get('ion-modal.show-modal').should('exist'); cy.get('#background-action').click(); cy.get('#background-action-count').should('have.text', '1'); @@ -13,7 +15,7 @@ describe('IonModal: focusTrap regression', () => { it('should prevent interacting with background when focusTrap=true', () => { cy.get('#open-trapped-modal').click(); - cy.get('ion-modal').should('be.visible'); + cy.get('ion-modal.show-modal').should('be.visible'); // Ensure backdrop is active and capturing pointer events cy.get('ion-backdrop').should('exist'); diff --git a/packages/react/test/base/tests/e2e/specs/overlay-components/IonModalSheetChildRoute.cy.ts b/packages/react/test/base/tests/e2e/specs/overlay-components/IonModalSheetChildRoute.cy.ts new file mode 100644 index 00000000000..ff791f3aade --- /dev/null +++ b/packages/react/test/base/tests/e2e/specs/overlay-components/IonModalSheetChildRoute.cy.ts @@ -0,0 +1,37 @@ +/** + * Tests for sheet modals in child routes with showBackdrop=false. + * See https://github.com/ionic-team/ionic-framework/issues/30700 + */ +describe('IonModal: Sheet in Child Route with Nested Routing', () => { + beforeEach(() => { + cy.visit('/overlay-components/modal-sheet-child-route/child'); + }); + + it('should render parent content and child modal', () => { + cy.get('#increment-btn').should('exist'); + cy.get('#decrement-btn').should('exist'); + cy.get('#background-action-count').should('have.text', '0'); + cy.get('ion-modal.show-modal').should('exist'); + cy.get('#modal-content-loaded').should('exist'); + }); + + it('should allow interacting with parent content while modal is open in child route', () => { + // Wait for modal to be presented + cy.get('ion-modal.show-modal').should('exist'); + + // Click the increment button in the parent content + cy.get('#increment-btn').click(); + cy.get('#background-action-count').should('have.text', '1'); + }); + + it('should allow multiple interactions with parent content while modal is open', () => { + cy.get('ion-modal.show-modal').should('exist'); + + cy.get('#increment-btn').click(); + cy.get('#increment-btn').click(); + cy.get('#background-action-count').should('have.text', '2'); + + cy.get('#decrement-btn').click(); + cy.get('#background-action-count').should('have.text', '1'); + }); +}); From b1645168a7fb9378dc39a081c207b2de0e180089 Mon Sep 17 00:00:00 2001 From: Shane Date: Wed, 10 Dec 2025 13:11:49 -0800 Subject: [PATCH 2/4] fix(modal): prevent browser hang when using ModalController in Angular (#30845) Issue number: resolves internal --------- ## What is the current behavior? When using ModalController to present a modal in Angular applications, the browser becomes non-responsive and hangs in some circumstances. This regression was introduced in #30544 with the addition of a MutationObserver that watches document.body with subtree: true to detect when a modal's parent element is removed from the DOM. For controller-based modals, this observer fires on every DOM mutation in the document, causing severe performance issues during Angular's change detection cycles. ## What is the new behavior? The MutationObserver for parent removal detection is now skipped for controller-based modals and when the cached parent is the app root (document.body or ion-app). These parents are never removed from the DOM, so observing them is unnecessary. This prevents the performance issues while still maintaining the parent removal detection behavior for inline modals with meaningful parent elements. ## Does this introduce a breaking change? - [ ] Yes - [X] No ## Other information Current dev build: ``` 8.7.12-dev.11765231260.1def96ab ``` --------- Co-authored-by: Maria Hutt --- core/src/components/modal/modal.tsx | 14 +++++++++++ .../components/modal/test/basic/modal.e2e.ts | 24 ++++++++++++++++++- 2 files changed, 37 insertions(+), 1 deletion(-) diff --git a/core/src/components/modal/modal.tsx b/core/src/components/modal/modal.tsx index dbed406ca4a..174ac2f9d8a 100644 --- a/core/src/components/modal/modal.tsx +++ b/core/src/components/modal/modal.tsx @@ -1279,6 +1279,20 @@ export class Modal implements ComponentInterface, OverlayInterface { return; } + /** + * Don't observe for controller-based modals or when the parent is the + * app root (document.body or ion-app). These parents won't be removed, + * and observing document.body with subtree: true causes performance + * issues with frameworks like Angular during change detection. + */ + if ( + this.hasController || + this.cachedOriginalParent === document.body || + this.cachedOriginalParent.tagName === 'ION-APP' + ) { + return; + } + this.parentRemovalObserver = new MutationObserver((mutations) => { mutations.forEach((mutation) => { if (mutation.type === 'childList' && mutation.removedNodes.length > 0) { diff --git a/core/src/components/modal/test/basic/modal.e2e.ts b/core/src/components/modal/test/basic/modal.e2e.ts index 325c4b3fbb5..1c9ac92743c 100644 --- a/core/src/components/modal/test/basic/modal.e2e.ts +++ b/core/src/components/modal/test/basic/modal.e2e.ts @@ -1,6 +1,6 @@ import { expect } from '@playwright/test'; -import { configs, test, Viewports } from '@utils/test/playwright'; import type { E2EPage } from '@utils/test/playwright'; +import { configs, test, Viewports } from '@utils/test/playwright'; configs({ modes: ['ios'], directions: ['ltr'] }).forEach(({ title, config }) => { test.describe(title('modal: focus trapping'), () => { @@ -104,6 +104,28 @@ configs().forEach(({ title, screenshot, config }) => { }); configs({ modes: ['ios'], directions: ['ltr'] }).forEach(({ title, config }) => { + test.describe(title('modal: parent removal observer'), () => { + test('should not set up parentRemovalObserver for controller-created modals', async ({ page }, testInfo) => { + testInfo.annotations.push({ + type: 'issue', + description: 'FW-6766', + }); + + await page.goto('/src/components/modal/test/basic', config); + const ionModalDidPresent = await page.spyOnEvent('ionModalDidPresent'); + + await page.click('#basic-modal'); + await ionModalDidPresent.next(); + + const modal = page.locator('ion-modal'); + const hasObserver = await modal.evaluate((el: any) => { + return el.parentRemovalObserver !== undefined; + }); + + expect(hasObserver).toBe(false); + }); + }); + test.describe(title('modal: backdrop'), () => { test.beforeEach(async ({ page }) => { await page.goto('/src/components/modal/test/basic', config); From afa15d23d21f34aebb3ab33ca446efb986bc4d84 Mon Sep 17 00:00:00 2001 From: ionitron Date: Wed, 10 Dec 2025 21:33:15 +0000 Subject: [PATCH 3/4] v8.7.12 --- CHANGELOG.md | 14 ++++++++++++++ core/CHANGELOG.md | 14 ++++++++++++++ core/package-lock.json | 6 +++--- core/package.json | 2 +- lerna.json | 2 +- packages/angular-server/CHANGELOG.md | 8 ++++++++ packages/angular-server/package-lock.json | 8 ++++---- packages/angular-server/package.json | 4 ++-- packages/angular/CHANGELOG.md | 11 +++++++++++ packages/angular/package-lock.json | 8 ++++---- packages/angular/package.json | 4 ++-- packages/docs/CHANGELOG.md | 8 ++++++++ packages/docs/package-lock.json | 4 ++-- packages/docs/package.json | 2 +- packages/react-router/CHANGELOG.md | 8 ++++++++ packages/react-router/package-lock.json | 8 ++++---- packages/react-router/package.json | 4 ++-- packages/react/CHANGELOG.md | 11 +++++++++++ packages/react/package-lock.json | 8 ++++---- packages/react/package.json | 4 ++-- packages/vue-router/CHANGELOG.md | 8 ++++++++ packages/vue-router/package-lock.json | 8 ++++---- packages/vue-router/package.json | 4 ++-- packages/vue/CHANGELOG.md | 8 ++++++++ packages/vue/package-lock.json | 8 ++++---- packages/vue/package.json | 4 ++-- 26 files changed, 134 insertions(+), 44 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 59418196b5b..44039ae1102 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,20 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [8.7.12](https://github.com/ionic-team/ionic-framework/compare/v8.7.11...v8.7.12) (2025-12-10) + + +### Bug Fixes + +* **modal:** allow interaction with parent content through sheet modals in child routes ([#30839](https://github.com/ionic-team/ionic-framework/issues/30839)) ([b9e3cf0](https://github.com/ionic-team/ionic-framework/commit/b9e3cf0f5aae79a1f27a07b102c77e51f24825f4)), closes [#30700](https://github.com/ionic-team/ionic-framework/issues/30700) +* **modal:** prevent browser hang when using ModalController in Angular ([#30845](https://github.com/ionic-team/ionic-framework/issues/30845)) ([b164516](https://github.com/ionic-team/ionic-framework/commit/b1645168a7fb9378dc39a081c207b2de0e180089)) +* **popover:** recalculate the content dimensions after the header has fully loaded ([#30853](https://github.com/ionic-team/ionic-framework/issues/30853)) ([99dcf38](https://github.com/ionic-team/ionic-framework/commit/99dcf3810a0c32416996d1e992ddf63359965cfc)) +* **select, action-sheet:** use radio role for options ([#30769](https://github.com/ionic-team/ionic-framework/issues/30769)) ([1c89cf0](https://github.com/ionic-team/ionic-framework/commit/1c89cf06ac959f9c9a35a66f811227c244d3198b)) + + + + + ## [8.7.11](https://github.com/ionic-team/ionic-framework/compare/v8.7.10...v8.7.11) (2025-11-26) diff --git a/core/CHANGELOG.md b/core/CHANGELOG.md index d1a86679387..3edf5cd89c3 100644 --- a/core/CHANGELOG.md +++ b/core/CHANGELOG.md @@ -3,6 +3,20 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [8.7.12](https://github.com/ionic-team/ionic-framework/compare/v8.7.11...v8.7.12) (2025-12-10) + + +### Bug Fixes + +* **modal:** allow interaction with parent content through sheet modals in child routes ([#30839](https://github.com/ionic-team/ionic-framework/issues/30839)) ([b9e3cf0](https://github.com/ionic-team/ionic-framework/commit/b9e3cf0f5aae79a1f27a07b102c77e51f24825f4)), closes [#30700](https://github.com/ionic-team/ionic-framework/issues/30700) +* **modal:** prevent browser hang when using ModalController in Angular ([#30845](https://github.com/ionic-team/ionic-framework/issues/30845)) ([b164516](https://github.com/ionic-team/ionic-framework/commit/b1645168a7fb9378dc39a081c207b2de0e180089)) +* **popover:** recalculate the content dimensions after the header has fully loaded ([#30853](https://github.com/ionic-team/ionic-framework/issues/30853)) ([99dcf38](https://github.com/ionic-team/ionic-framework/commit/99dcf3810a0c32416996d1e992ddf63359965cfc)) +* **select, action-sheet:** use radio role for options ([#30769](https://github.com/ionic-team/ionic-framework/issues/30769)) ([1c89cf0](https://github.com/ionic-team/ionic-framework/commit/1c89cf06ac959f9c9a35a66f811227c244d3198b)) + + + + + ## [8.7.11](https://github.com/ionic-team/ionic-framework/compare/v8.7.10...v8.7.11) (2025-11-26) diff --git a/core/package-lock.json b/core/package-lock.json index b4f227b4c43..4aa5600d56d 100644 --- a/core/package-lock.json +++ b/core/package-lock.json @@ -1,12 +1,12 @@ { "name": "@ionic/core", - "version": "8.7.11", + "version": "8.7.12", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@ionic/core", - "version": "8.7.11", + "version": "8.7.12", "license": "MIT", "dependencies": { "@stencil/core": "4.38.0", @@ -9823,4 +9823,4 @@ } } } -} +} \ No newline at end of file diff --git a/core/package.json b/core/package.json index b0f0db7b189..11f78142274 100644 --- a/core/package.json +++ b/core/package.json @@ -1,6 +1,6 @@ { "name": "@ionic/core", - "version": "8.7.11", + "version": "8.7.12", "description": "Base components for Ionic", "engines": { "node": "24.x" diff --git a/lerna.json b/lerna.json index 5134a3baffe..3e932560e2a 100644 --- a/lerna.json +++ b/lerna.json @@ -3,5 +3,5 @@ "core", "packages/*" ], - "version": "8.7.11" + "version": "8.7.12" } \ No newline at end of file diff --git a/packages/angular-server/CHANGELOG.md b/packages/angular-server/CHANGELOG.md index 55109a07286..cdce885d0d8 100644 --- a/packages/angular-server/CHANGELOG.md +++ b/packages/angular-server/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [8.7.12](https://github.com/ionic-team/ionic-framework/compare/v8.7.11...v8.7.12) (2025-12-10) + +**Note:** Version bump only for package @ionic/angular-server + + + + + ## [8.7.11](https://github.com/ionic-team/ionic-framework/compare/v8.7.10...v8.7.11) (2025-11-26) **Note:** Version bump only for package @ionic/angular-server diff --git a/packages/angular-server/package-lock.json b/packages/angular-server/package-lock.json index fdddce185b1..36674a7cd44 100644 --- a/packages/angular-server/package-lock.json +++ b/packages/angular-server/package-lock.json @@ -1,15 +1,15 @@ { "name": "@ionic/angular-server", - "version": "8.7.11", + "version": "8.7.12", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@ionic/angular-server", - "version": "8.7.11", + "version": "8.7.12", "license": "MIT", "dependencies": { - "@ionic/core": "^8.7.11" + "@ionic/core": "^8.7.12" }, "devDependencies": { "@angular-eslint/eslint-plugin": "^16.0.0", @@ -11286,4 +11286,4 @@ } } } -} +} \ No newline at end of file diff --git a/packages/angular-server/package.json b/packages/angular-server/package.json index 47aafb0182f..b5c6bd7ea15 100644 --- a/packages/angular-server/package.json +++ b/packages/angular-server/package.json @@ -1,6 +1,6 @@ { "name": "@ionic/angular-server", - "version": "8.7.11", + "version": "8.7.12", "description": "Angular SSR Module for Ionic", "keywords": [ "ionic", @@ -62,6 +62,6 @@ }, "prettier": "@ionic/prettier-config", "dependencies": { - "@ionic/core": "^8.7.11" + "@ionic/core": "^8.7.12" } } diff --git a/packages/angular/CHANGELOG.md b/packages/angular/CHANGELOG.md index af9a74674e4..41c9a25bec4 100644 --- a/packages/angular/CHANGELOG.md +++ b/packages/angular/CHANGELOG.md @@ -3,6 +3,17 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [8.7.12](https://github.com/ionic-team/ionic-framework/compare/v8.7.11...v8.7.12) (2025-12-10) + + +### Bug Fixes + +* **modal:** allow interaction with parent content through sheet modals in child routes ([#30839](https://github.com/ionic-team/ionic-framework/issues/30839)) ([b9e3cf0](https://github.com/ionic-team/ionic-framework/commit/b9e3cf0f5aae79a1f27a07b102c77e51f24825f4)), closes [#30700](https://github.com/ionic-team/ionic-framework/issues/30700) + + + + + ## [8.7.11](https://github.com/ionic-team/ionic-framework/compare/v8.7.10...v8.7.11) (2025-11-26) **Note:** Version bump only for package @ionic/angular diff --git a/packages/angular/package-lock.json b/packages/angular/package-lock.json index 2f8f71c7358..9c785ef51b8 100644 --- a/packages/angular/package-lock.json +++ b/packages/angular/package-lock.json @@ -1,15 +1,15 @@ { "name": "@ionic/angular", - "version": "8.7.11", + "version": "8.7.12", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@ionic/angular", - "version": "8.7.11", + "version": "8.7.12", "license": "MIT", "dependencies": { - "@ionic/core": "^8.7.11", + "@ionic/core": "^8.7.12", "ionicons": "^8.0.13", "jsonc-parser": "^3.0.0", "tslib": "^2.3.0" @@ -9092,4 +9092,4 @@ } } } -} +} \ No newline at end of file diff --git a/packages/angular/package.json b/packages/angular/package.json index 6dc90b223c4..2c015fd9212 100644 --- a/packages/angular/package.json +++ b/packages/angular/package.json @@ -1,6 +1,6 @@ { "name": "@ionic/angular", - "version": "8.7.11", + "version": "8.7.12", "description": "Angular specific wrappers for @ionic/core", "keywords": [ "ionic", @@ -48,7 +48,7 @@ } }, "dependencies": { - "@ionic/core": "^8.7.11", + "@ionic/core": "^8.7.12", "ionicons": "^8.0.13", "jsonc-parser": "^3.0.0", "tslib": "^2.3.0" diff --git a/packages/docs/CHANGELOG.md b/packages/docs/CHANGELOG.md index 63638865fae..4cc3c8f7f8a 100644 --- a/packages/docs/CHANGELOG.md +++ b/packages/docs/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [8.7.12](https://github.com/ionic-team/ionic-framework/compare/v8.7.11...v8.7.12) (2025-12-10) + +**Note:** Version bump only for package @ionic/docs + + + + + ## [8.7.11](https://github.com/ionic-team/ionic-framework/compare/v8.7.10...v8.7.11) (2025-11-26) **Note:** Version bump only for package @ionic/docs diff --git a/packages/docs/package-lock.json b/packages/docs/package-lock.json index 3c1391b8cf3..c3e6ed1d233 100644 --- a/packages/docs/package-lock.json +++ b/packages/docs/package-lock.json @@ -1,12 +1,12 @@ { "name": "@ionic/docs", - "version": "8.7.11", + "version": "8.7.12", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@ionic/docs", - "version": "8.7.11", + "version": "8.7.12", "license": "MIT" } } diff --git a/packages/docs/package.json b/packages/docs/package.json index 018947033c8..0c0f81bbf97 100644 --- a/packages/docs/package.json +++ b/packages/docs/package.json @@ -1,6 +1,6 @@ { "name": "@ionic/docs", - "version": "8.7.11", + "version": "8.7.12", "description": "Pre-packaged API documentation for the Ionic docs.", "main": "core.json", "types": "core.d.ts", diff --git a/packages/react-router/CHANGELOG.md b/packages/react-router/CHANGELOG.md index dcc56dc20c8..5b01d669edf 100644 --- a/packages/react-router/CHANGELOG.md +++ b/packages/react-router/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [8.7.12](https://github.com/ionic-team/ionic-framework/compare/v8.7.11...v8.7.12) (2025-12-10) + +**Note:** Version bump only for package @ionic/react-router + + + + + ## [8.7.11](https://github.com/ionic-team/ionic-framework/compare/v8.7.10...v8.7.11) (2025-11-26) **Note:** Version bump only for package @ionic/react-router diff --git a/packages/react-router/package-lock.json b/packages/react-router/package-lock.json index ca60000c58b..e1366ec9467 100644 --- a/packages/react-router/package-lock.json +++ b/packages/react-router/package-lock.json @@ -1,15 +1,15 @@ { "name": "@ionic/react-router", - "version": "8.7.11", + "version": "8.7.12", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@ionic/react-router", - "version": "8.7.11", + "version": "8.7.12", "license": "MIT", "dependencies": { - "@ionic/react": "^8.7.11", + "@ionic/react": "^8.7.12", "tslib": "*" }, "devDependencies": { @@ -6844,4 +6844,4 @@ "dev": true } } -} +} \ No newline at end of file diff --git a/packages/react-router/package.json b/packages/react-router/package.json index 6caca04b3dc..7e2f11fc05b 100644 --- a/packages/react-router/package.json +++ b/packages/react-router/package.json @@ -1,6 +1,6 @@ { "name": "@ionic/react-router", - "version": "8.7.11", + "version": "8.7.12", "description": "React Router wrapper for @ionic/react", "keywords": [ "ionic", @@ -36,7 +36,7 @@ "dist/" ], "dependencies": { - "@ionic/react": "^8.7.11", + "@ionic/react": "^8.7.12", "tslib": "*" }, "peerDependencies": { diff --git a/packages/react/CHANGELOG.md b/packages/react/CHANGELOG.md index d0dfb6d60de..550acf8a07c 100644 --- a/packages/react/CHANGELOG.md +++ b/packages/react/CHANGELOG.md @@ -3,6 +3,17 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [8.7.12](https://github.com/ionic-team/ionic-framework/compare/v8.7.11...v8.7.12) (2025-12-10) + + +### Bug Fixes + +* **modal:** allow interaction with parent content through sheet modals in child routes ([#30839](https://github.com/ionic-team/ionic-framework/issues/30839)) ([b9e3cf0](https://github.com/ionic-team/ionic-framework/commit/b9e3cf0f5aae79a1f27a07b102c77e51f24825f4)), closes [#30700](https://github.com/ionic-team/ionic-framework/issues/30700) + + + + + ## [8.7.11](https://github.com/ionic-team/ionic-framework/compare/v8.7.10...v8.7.11) (2025-11-26) **Note:** Version bump only for package @ionic/react diff --git a/packages/react/package-lock.json b/packages/react/package-lock.json index 909959cda1b..0d3b0edc67f 100644 --- a/packages/react/package-lock.json +++ b/packages/react/package-lock.json @@ -1,15 +1,15 @@ { "name": "@ionic/react", - "version": "8.7.11", + "version": "8.7.12", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@ionic/react", - "version": "8.7.11", + "version": "8.7.12", "license": "MIT", "dependencies": { - "@ionic/core": "^8.7.11", + "@ionic/core": "^8.7.12", "ionicons": "^8.0.13", "tslib": "*" }, @@ -11913,4 +11913,4 @@ } } } -} +} \ No newline at end of file diff --git a/packages/react/package.json b/packages/react/package.json index f9407abde68..bb2bfa74b77 100644 --- a/packages/react/package.json +++ b/packages/react/package.json @@ -1,6 +1,6 @@ { "name": "@ionic/react", - "version": "8.7.11", + "version": "8.7.12", "description": "React specific wrapper for @ionic/core", "keywords": [ "ionic", @@ -40,7 +40,7 @@ "css/" ], "dependencies": { - "@ionic/core": "^8.7.11", + "@ionic/core": "^8.7.12", "ionicons": "^8.0.13", "tslib": "*" }, diff --git a/packages/vue-router/CHANGELOG.md b/packages/vue-router/CHANGELOG.md index 21cc70cb953..a80b6d0a24f 100644 --- a/packages/vue-router/CHANGELOG.md +++ b/packages/vue-router/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [8.7.12](https://github.com/ionic-team/ionic-framework/compare/v8.7.11...v8.7.12) (2025-12-10) + +**Note:** Version bump only for package @ionic/vue-router + + + + + ## [8.7.11](https://github.com/ionic-team/ionic-framework/compare/v8.7.10...v8.7.11) (2025-11-26) **Note:** Version bump only for package @ionic/vue-router diff --git a/packages/vue-router/package-lock.json b/packages/vue-router/package-lock.json index fa908748990..52233768392 100644 --- a/packages/vue-router/package-lock.json +++ b/packages/vue-router/package-lock.json @@ -1,15 +1,15 @@ { "name": "@ionic/vue-router", - "version": "8.7.11", + "version": "8.7.12", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@ionic/vue-router", - "version": "8.7.11", + "version": "8.7.12", "license": "MIT", "dependencies": { - "@ionic/vue": "^8.7.11" + "@ionic/vue": "^8.7.12" }, "devDependencies": { "@ionic/eslint-config": "^0.3.0", @@ -12991,4 +12991,4 @@ "dev": true } } -} +} \ No newline at end of file diff --git a/packages/vue-router/package.json b/packages/vue-router/package.json index 2d7e95b40f6..cee8f5e4e54 100644 --- a/packages/vue-router/package.json +++ b/packages/vue-router/package.json @@ -1,6 +1,6 @@ { "name": "@ionic/vue-router", - "version": "8.7.11", + "version": "8.7.12", "description": "Vue Router integration for @ionic/vue", "scripts": { "test.spec": "jest", @@ -44,7 +44,7 @@ }, "homepage": "https://github.com/ionic-team/ionic-framework#readme", "dependencies": { - "@ionic/vue": "^8.7.11" + "@ionic/vue": "^8.7.12" }, "devDependencies": { "@ionic/eslint-config": "^0.3.0", diff --git a/packages/vue/CHANGELOG.md b/packages/vue/CHANGELOG.md index 2d82d381e83..e00ea2c3773 100644 --- a/packages/vue/CHANGELOG.md +++ b/packages/vue/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [8.7.12](https://github.com/ionic-team/ionic-framework/compare/v8.7.11...v8.7.12) (2025-12-10) + +**Note:** Version bump only for package @ionic/vue + + + + + ## [8.7.11](https://github.com/ionic-team/ionic-framework/compare/v8.7.10...v8.7.11) (2025-11-26) **Note:** Version bump only for package @ionic/vue diff --git a/packages/vue/package-lock.json b/packages/vue/package-lock.json index 1c127c6af94..70c1dbfd596 100644 --- a/packages/vue/package-lock.json +++ b/packages/vue/package-lock.json @@ -1,15 +1,15 @@ { "name": "@ionic/vue", - "version": "8.7.11", + "version": "8.7.12", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@ionic/vue", - "version": "8.7.11", + "version": "8.7.12", "license": "MIT", "dependencies": { - "@ionic/core": "^8.7.11", + "@ionic/core": "^8.7.12", "@stencil/vue-output-target": "0.10.7", "ionicons": "^8.0.13" }, @@ -4019,4 +4019,4 @@ "dev": true } } -} +} \ No newline at end of file diff --git a/packages/vue/package.json b/packages/vue/package.json index b10b5b65a00..d89aa3cf61e 100644 --- a/packages/vue/package.json +++ b/packages/vue/package.json @@ -1,6 +1,6 @@ { "name": "@ionic/vue", - "version": "8.7.11", + "version": "8.7.12", "description": "Vue specific wrapper for @ionic/core", "scripts": { "eslint": "eslint src", @@ -68,7 +68,7 @@ "vue-router": "^4.0.16" }, "dependencies": { - "@ionic/core": "^8.7.11", + "@ionic/core": "^8.7.12", "@stencil/vue-output-target": "0.10.7", "ionicons": "^8.0.13" }, From 5bf6f6e8251c819af192576e40ea072d87f38471 Mon Sep 17 00:00:00 2001 From: ionitron Date: Wed, 10 Dec 2025 21:34:28 +0000 Subject: [PATCH 4/4] chore(): update package lock files --- core/package-lock.json | 42 ++++++++++++++--------- packages/angular-server/package-lock.json | 17 +++++---- packages/angular/package-lock.json | 11 +++--- packages/docs/package-lock.json | 2 +- packages/react-router/package-lock.json | 33 ++++++++++-------- packages/react/package-lock.json | 11 +++--- packages/vue-router/package-lock.json | 33 ++++++++++-------- packages/vue/package-lock.json | 11 +++--- 8 files changed, 93 insertions(+), 67 deletions(-) diff --git a/core/package-lock.json b/core/package-lock.json index 4aa5600d56d..362a93bb797 100644 --- a/core/package-lock.json +++ b/core/package-lock.json @@ -50,6 +50,9 @@ "serve": "^14.0.1", "stylelint": "^13.13.1", "stylelint-order": "^4.1.0" + }, + "engines": { + "node": "24.x" } }, "custom-rules": { @@ -91,7 +94,6 @@ "version": "7.16.12", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/code-frame": "^7.16.7", "@babel/generator": "^7.16.8", @@ -629,7 +631,6 @@ "version": "7.4.4", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "tslib": "^2.1.0" } @@ -861,7 +862,6 @@ "version": "4.33.0", "dev": true, "license": "BSD-2-Clause", - "peer": true, "dependencies": { "@typescript-eslint/scope-manager": "4.33.0", "@typescript-eslint/types": "4.33.0", @@ -1799,7 +1799,6 @@ "node_modules/@stencil/core": { "version": "4.38.0", "license": "MIT", - "peer": true, "bin": { "stencil": "bin/stencil" }, @@ -2224,7 +2223,6 @@ "version": "6.7.2", "dev": true, "license": "BSD-2-Clause", - "peer": true, "dependencies": { "@typescript-eslint/scope-manager": "6.7.2", "@typescript-eslint/types": "6.7.2", @@ -2450,6 +2448,7 @@ "integrity": "sha512-vay5/oQJdsNHmliWoZfHPoVZZRmnSWhug0BYT34njkYTPqClh3DNWLkZNJBVSjsNMrg0CCrBfoKkjZQPM/QVUw==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@babel/parser": "^7.28.5", "@vue/shared": "3.5.25", @@ -2464,6 +2463,7 @@ "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", "dev": true, "license": "BSD-2-Clause", + "peer": true, "engines": { "node": ">=0.12" }, @@ -2476,7 +2476,8 @@ "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", "dev": true, - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/@vue/compiler-dom": { "version": "3.5.25", @@ -2484,6 +2485,7 @@ "integrity": "sha512-4We0OAcMZsKgYoGlMjzYvaoErltdFI2/25wqanuTu+S4gismOTRTBPi4IASOjxWdzIwrYSjnqONfKvuqkXzE2Q==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@vue/compiler-core": "3.5.25", "@vue/shared": "3.5.25" @@ -2495,6 +2497,7 @@ "integrity": "sha512-PUgKp2rn8fFsI++lF2sO7gwO2d9Yj57Utr5yEsDf3GNaQcowCLKL7sf+LvVFvtJDXUp/03+dC6f2+LCv5aK1ag==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@babel/parser": "^7.28.5", "@vue/compiler-core": "3.5.25", @@ -2512,7 +2515,8 @@ "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", "dev": true, - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/@vue/compiler-sfc/node_modules/postcss": { "version": "8.5.6", @@ -2534,6 +2538,7 @@ } ], "license": "MIT", + "peer": true, "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", @@ -2549,6 +2554,7 @@ "integrity": "sha512-ritPSKLBcParnsKYi+GNtbdbrIE1mtuFEJ4U1sWeuOMlIziK5GtOL85t5RhsNy4uWIXPgk+OUdpnXiTdzn8o3A==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@vue/compiler-dom": "3.5.25", "@vue/shared": "3.5.25" @@ -2560,6 +2566,7 @@ "integrity": "sha512-5xfAypCQepv4Jog1U4zn8cZIcbKKFka3AgWHEFQeK65OW+Ys4XybP6z2kKgws4YB43KGpqp5D/K3go2UPPunLA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@vue/shared": "3.5.25" } @@ -2570,6 +2577,7 @@ "integrity": "sha512-Z751v203YWwYzy460bzsYQISDfPjHTl+6Zzwo/a3CsAf+0ccEjQ8c+0CdX1WsumRTHeywvyUFtW6KvNukT/smA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@vue/reactivity": "3.5.25", "@vue/shared": "3.5.25" @@ -2581,6 +2589,7 @@ "integrity": "sha512-a4WrkYFbb19i9pjkz38zJBg8wa/rboNERq3+hRRb0dHiJh13c+6kAbgqCPfMaJ2gg4weWD3APZswASOfmKwamA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@vue/reactivity": "3.5.25", "@vue/runtime-core": "3.5.25", @@ -2594,6 +2603,7 @@ "integrity": "sha512-UJaXR54vMG61i8XNIzTSf2Q7MOqZHpp8+x3XLGtE3+fL+nQd+k7O5+X3D/uWrnQXOdMw5VPih+Uremcw+u1woQ==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@vue/compiler-ssr": "3.5.25", "@vue/shared": "3.5.25" @@ -2607,7 +2617,8 @@ "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.5.25.tgz", "integrity": "sha512-AbOPdQQnAnzs58H2FrrDxYj/TJfmeS2jdfEEhgiKINy+bnOANmVizIEgq1r+C5zsbs6l1CCQxtcj71rwNQ4jWg==", "dev": true, - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/@zeit/schemas": { "version": "2.21.0", @@ -2630,7 +2641,6 @@ "version": "7.4.0", "dev": true, "license": "MIT", - "peer": true, "bin": { "acorn": "bin/acorn" }, @@ -3791,7 +3801,8 @@ "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz", "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==", "dev": true, - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/debug": { "version": "2.6.9", @@ -4085,7 +4096,6 @@ "version": "7.32.0", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/code-frame": "7.12.11", "@eslint/eslintrc": "^0.4.3", @@ -7281,6 +7291,7 @@ "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.5" } @@ -7602,6 +7613,7 @@ } ], "license": "MIT", + "peer": true, "bin": { "nanoid": "bin/nanoid.cjs" }, @@ -7956,7 +7968,6 @@ "integrity": "sha512-hutraynyn31F+Bifme+Ps9Vq59hKuUCz7H1kDOcBs+2oGguKkWTU50bBWrtz34OUWmIwpBTWDxaRPXrIXkgvmQ==", "dev": true, "license": "Apache-2.0", - "peer": true, "bin": { "playwright-core": "cli.js" }, @@ -7968,7 +7979,6 @@ "version": "7.0.35", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "chalk": "^2.4.2", "source-map": "^0.6.1", @@ -8074,7 +8084,6 @@ "version": "0.36.2", "dev": true, "license": "MIT", - "peer": true, "peerDependencies": { "postcss": ">=5.0.0" } @@ -8123,7 +8132,6 @@ "version": "2.6.1", "dev": true, "license": "MIT", - "peer": true, "bin": { "prettier": "bin-prettier.js" }, @@ -8481,7 +8489,6 @@ "version": "2.35.1", "dev": true, "license": "MIT", - "peer": true, "bin": { "rollup": "dist/bin/rollup" }, @@ -8703,6 +8710,7 @@ "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", "dev": true, "license": "BSD-3-Clause", + "peer": true, "engines": { "node": ">=0.10.0" } @@ -9823,4 +9831,4 @@ } } } -} \ No newline at end of file +} diff --git a/packages/angular-server/package-lock.json b/packages/angular-server/package-lock.json index 36674a7cd44..4eee627f8dc 100644 --- a/packages/angular-server/package-lock.json +++ b/packages/angular-server/package-lock.json @@ -1031,14 +1031,17 @@ "dev": true }, "node_modules/@ionic/core": { - "version": "8.7.11", - "resolved": "https://registry.npmjs.org/@ionic/core/-/core-8.7.11.tgz", - "integrity": "sha512-9UX9IeEztWWXymi+xCUMEBnnY+TbaR8crZLOwFnxPUEq4FFWSUCSv5XeHHQBpgZjBO2MJuDGcNv0GCQumIjVcQ==", + "version": "8.7.12", + "resolved": "https://registry.npmjs.org/@ionic/core/-/core-8.7.12.tgz", + "integrity": "sha512-+QnytOHsMMDEz45hi/t9AN8ATaWMNZ7jNdx621BGSHi0JkEl1c4NylL3cfYIPJ/78y40ZG5NzprwNiR9sXdswg==", "license": "MIT", "dependencies": { "@stencil/core": "4.38.0", "ionicons": "^8.0.13", "tslib": "^2.1.0" + }, + "engines": { + "node": "24.x" } }, "node_modules/@ionic/eslint-config": { @@ -7306,9 +7309,9 @@ "dev": true }, "@ionic/core": { - "version": "8.7.11", - "resolved": "https://registry.npmjs.org/@ionic/core/-/core-8.7.11.tgz", - "integrity": "sha512-9UX9IeEztWWXymi+xCUMEBnnY+TbaR8crZLOwFnxPUEq4FFWSUCSv5XeHHQBpgZjBO2MJuDGcNv0GCQumIjVcQ==", + "version": "8.7.12", + "resolved": "https://registry.npmjs.org/@ionic/core/-/core-8.7.12.tgz", + "integrity": "sha512-+QnytOHsMMDEz45hi/t9AN8ATaWMNZ7jNdx621BGSHi0JkEl1c4NylL3cfYIPJ/78y40ZG5NzprwNiR9sXdswg==", "requires": { "@stencil/core": "4.38.0", "ionicons": "^8.0.13", @@ -11286,4 +11289,4 @@ } } } -} \ No newline at end of file +} diff --git a/packages/angular/package-lock.json b/packages/angular/package-lock.json index 9c785ef51b8..18d9d9e5f79 100644 --- a/packages/angular/package-lock.json +++ b/packages/angular/package-lock.json @@ -1398,14 +1398,17 @@ "dev": true }, "node_modules/@ionic/core": { - "version": "8.7.11", - "resolved": "https://registry.npmjs.org/@ionic/core/-/core-8.7.11.tgz", - "integrity": "sha512-9UX9IeEztWWXymi+xCUMEBnnY+TbaR8crZLOwFnxPUEq4FFWSUCSv5XeHHQBpgZjBO2MJuDGcNv0GCQumIjVcQ==", + "version": "8.7.12", + "resolved": "https://registry.npmjs.org/@ionic/core/-/core-8.7.12.tgz", + "integrity": "sha512-+QnytOHsMMDEz45hi/t9AN8ATaWMNZ7jNdx621BGSHi0JkEl1c4NylL3cfYIPJ/78y40ZG5NzprwNiR9sXdswg==", "license": "MIT", "dependencies": { "@stencil/core": "4.38.0", "ionicons": "^8.0.13", "tslib": "^2.1.0" + }, + "engines": { + "node": "24.x" } }, "node_modules/@ionic/eslint-config": { @@ -9092,4 +9095,4 @@ } } } -} \ No newline at end of file +} diff --git a/packages/docs/package-lock.json b/packages/docs/package-lock.json index c3e6ed1d233..999970780cd 100644 --- a/packages/docs/package-lock.json +++ b/packages/docs/package-lock.json @@ -10,4 +10,4 @@ "license": "MIT" } } -} \ No newline at end of file +} diff --git a/packages/react-router/package-lock.json b/packages/react-router/package-lock.json index e1366ec9467..56b884f97c4 100644 --- a/packages/react-router/package-lock.json +++ b/packages/react-router/package-lock.json @@ -238,14 +238,17 @@ "dev": true }, "node_modules/@ionic/core": { - "version": "8.7.11", - "resolved": "https://registry.npmjs.org/@ionic/core/-/core-8.7.11.tgz", - "integrity": "sha512-9UX9IeEztWWXymi+xCUMEBnnY+TbaR8crZLOwFnxPUEq4FFWSUCSv5XeHHQBpgZjBO2MJuDGcNv0GCQumIjVcQ==", + "version": "8.7.12", + "resolved": "https://registry.npmjs.org/@ionic/core/-/core-8.7.12.tgz", + "integrity": "sha512-+QnytOHsMMDEz45hi/t9AN8ATaWMNZ7jNdx621BGSHi0JkEl1c4NylL3cfYIPJ/78y40ZG5NzprwNiR9sXdswg==", "license": "MIT", "dependencies": { "@stencil/core": "4.38.0", "ionicons": "^8.0.13", "tslib": "^2.1.0" + }, + "engines": { + "node": "24.x" } }, "node_modules/@ionic/eslint-config": { @@ -415,12 +418,12 @@ } }, "node_modules/@ionic/react": { - "version": "8.7.11", - "resolved": "https://registry.npmjs.org/@ionic/react/-/react-8.7.11.tgz", - "integrity": "sha512-h4j2SVRMgoxZBdr1bluKGrb0xNYEqEDcjHDuHsok669tKH3RnTMfD276zytfhFh3R8gIKWIqxb76NIsW/hfZcQ==", + "version": "8.7.12", + "resolved": "https://registry.npmjs.org/@ionic/react/-/react-8.7.12.tgz", + "integrity": "sha512-gNm5L++aiwkwJrUFKhcHUUgjqnj9n03gK7UcoL7Oz+271arzmwF/FNd47G85b6PovwiYQXY2CUBvNJ7Nh4qE/A==", "license": "MIT", "dependencies": { - "@ionic/core": "8.7.11", + "@ionic/core": "8.7.12", "ionicons": "^8.0.13", "tslib": "*" }, @@ -4175,9 +4178,9 @@ "dev": true }, "@ionic/core": { - "version": "8.7.11", - "resolved": "https://registry.npmjs.org/@ionic/core/-/core-8.7.11.tgz", - "integrity": "sha512-9UX9IeEztWWXymi+xCUMEBnnY+TbaR8crZLOwFnxPUEq4FFWSUCSv5XeHHQBpgZjBO2MJuDGcNv0GCQumIjVcQ==", + "version": "8.7.12", + "resolved": "https://registry.npmjs.org/@ionic/core/-/core-8.7.12.tgz", + "integrity": "sha512-+QnytOHsMMDEz45hi/t9AN8ATaWMNZ7jNdx621BGSHi0JkEl1c4NylL3cfYIPJ/78y40ZG5NzprwNiR9sXdswg==", "requires": { "@stencil/core": "4.38.0", "ionicons": "^8.0.13", @@ -4281,11 +4284,11 @@ "requires": {} }, "@ionic/react": { - "version": "8.7.11", - "resolved": "https://registry.npmjs.org/@ionic/react/-/react-8.7.11.tgz", - "integrity": "sha512-h4j2SVRMgoxZBdr1bluKGrb0xNYEqEDcjHDuHsok669tKH3RnTMfD276zytfhFh3R8gIKWIqxb76NIsW/hfZcQ==", + "version": "8.7.12", + "resolved": "https://registry.npmjs.org/@ionic/react/-/react-8.7.12.tgz", + "integrity": "sha512-gNm5L++aiwkwJrUFKhcHUUgjqnj9n03gK7UcoL7Oz+271arzmwF/FNd47G85b6PovwiYQXY2CUBvNJ7Nh4qE/A==", "requires": { - "@ionic/core": "8.7.11", + "@ionic/core": "8.7.12", "ionicons": "^8.0.13", "tslib": "*" } @@ -6844,4 +6847,4 @@ "dev": true } } -} \ No newline at end of file +} diff --git a/packages/react/package-lock.json b/packages/react/package-lock.json index 0d3b0edc67f..3f35a39caad 100644 --- a/packages/react/package-lock.json +++ b/packages/react/package-lock.json @@ -736,14 +736,17 @@ "dev": true }, "node_modules/@ionic/core": { - "version": "8.7.11", - "resolved": "https://registry.npmjs.org/@ionic/core/-/core-8.7.11.tgz", - "integrity": "sha512-9UX9IeEztWWXymi+xCUMEBnnY+TbaR8crZLOwFnxPUEq4FFWSUCSv5XeHHQBpgZjBO2MJuDGcNv0GCQumIjVcQ==", + "version": "8.7.12", + "resolved": "https://registry.npmjs.org/@ionic/core/-/core-8.7.12.tgz", + "integrity": "sha512-+QnytOHsMMDEz45hi/t9AN8ATaWMNZ7jNdx621BGSHi0JkEl1c4NylL3cfYIPJ/78y40ZG5NzprwNiR9sXdswg==", "license": "MIT", "dependencies": { "@stencil/core": "4.38.0", "ionicons": "^8.0.13", "tslib": "^2.1.0" + }, + "engines": { + "node": "24.x" } }, "node_modules/@ionic/eslint-config": { @@ -11913,4 +11916,4 @@ } } } -} \ No newline at end of file +} diff --git a/packages/vue-router/package-lock.json b/packages/vue-router/package-lock.json index 52233768392..f7e737b3747 100644 --- a/packages/vue-router/package-lock.json +++ b/packages/vue-router/package-lock.json @@ -673,14 +673,17 @@ "dev": true }, "node_modules/@ionic/core": { - "version": "8.7.11", - "resolved": "https://registry.npmjs.org/@ionic/core/-/core-8.7.11.tgz", - "integrity": "sha512-9UX9IeEztWWXymi+xCUMEBnnY+TbaR8crZLOwFnxPUEq4FFWSUCSv5XeHHQBpgZjBO2MJuDGcNv0GCQumIjVcQ==", + "version": "8.7.12", + "resolved": "https://registry.npmjs.org/@ionic/core/-/core-8.7.12.tgz", + "integrity": "sha512-+QnytOHsMMDEz45hi/t9AN8ATaWMNZ7jNdx621BGSHi0JkEl1c4NylL3cfYIPJ/78y40ZG5NzprwNiR9sXdswg==", "license": "MIT", "dependencies": { "@stencil/core": "4.38.0", "ionicons": "^8.0.13", "tslib": "^2.1.0" + }, + "engines": { + "node": "24.x" } }, "node_modules/@ionic/eslint-config": { @@ -865,12 +868,12 @@ } }, "node_modules/@ionic/vue": { - "version": "8.7.11", - "resolved": "https://registry.npmjs.org/@ionic/vue/-/vue-8.7.11.tgz", - "integrity": "sha512-HDEcjhxWfimVQxvXfghrqlAWpXnJvcUDTIVE2Mvq8ul+s7gL/OZCpXTAODJOfFCBAGJ0o9QXyC7OPjyN4UbO8Q==", + "version": "8.7.12", + "resolved": "https://registry.npmjs.org/@ionic/vue/-/vue-8.7.12.tgz", + "integrity": "sha512-fH/acQ7dYYd1XY1HFqKf0Th6klbfNNzhlnYUf9kNQpkHqUpMamSzA8TWDOV5f4PNKYq6X4oKAPPeIQA4DOayUQ==", "license": "MIT", "dependencies": { - "@ionic/core": "8.7.11", + "@ionic/core": "8.7.12", "@stencil/vue-output-target": "0.10.7", "ionicons": "^8.0.13" } @@ -8041,9 +8044,9 @@ "dev": true }, "@ionic/core": { - "version": "8.7.11", - "resolved": "https://registry.npmjs.org/@ionic/core/-/core-8.7.11.tgz", - "integrity": "sha512-9UX9IeEztWWXymi+xCUMEBnnY+TbaR8crZLOwFnxPUEq4FFWSUCSv5XeHHQBpgZjBO2MJuDGcNv0GCQumIjVcQ==", + "version": "8.7.12", + "resolved": "https://registry.npmjs.org/@ionic/core/-/core-8.7.12.tgz", + "integrity": "sha512-+QnytOHsMMDEz45hi/t9AN8ATaWMNZ7jNdx621BGSHi0JkEl1c4NylL3cfYIPJ/78y40ZG5NzprwNiR9sXdswg==", "requires": { "@stencil/core": "4.38.0", "ionicons": "^8.0.13", @@ -8156,11 +8159,11 @@ "requires": {} }, "@ionic/vue": { - "version": "8.7.11", - "resolved": "https://registry.npmjs.org/@ionic/vue/-/vue-8.7.11.tgz", - "integrity": "sha512-HDEcjhxWfimVQxvXfghrqlAWpXnJvcUDTIVE2Mvq8ul+s7gL/OZCpXTAODJOfFCBAGJ0o9QXyC7OPjyN4UbO8Q==", + "version": "8.7.12", + "resolved": "https://registry.npmjs.org/@ionic/vue/-/vue-8.7.12.tgz", + "integrity": "sha512-fH/acQ7dYYd1XY1HFqKf0Th6klbfNNzhlnYUf9kNQpkHqUpMamSzA8TWDOV5f4PNKYq6X4oKAPPeIQA4DOayUQ==", "requires": { - "@ionic/core": "8.7.11", + "@ionic/core": "8.7.12", "@stencil/vue-output-target": "0.10.7", "ionicons": "^8.0.13" } @@ -12991,4 +12994,4 @@ "dev": true } } -} \ No newline at end of file +} diff --git a/packages/vue/package-lock.json b/packages/vue/package-lock.json index 70c1dbfd596..12314e4f7a6 100644 --- a/packages/vue/package-lock.json +++ b/packages/vue/package-lock.json @@ -222,14 +222,17 @@ "dev": true }, "node_modules/@ionic/core": { - "version": "8.7.11", - "resolved": "https://registry.npmjs.org/@ionic/core/-/core-8.7.11.tgz", - "integrity": "sha512-9UX9IeEztWWXymi+xCUMEBnnY+TbaR8crZLOwFnxPUEq4FFWSUCSv5XeHHQBpgZjBO2MJuDGcNv0GCQumIjVcQ==", + "version": "8.7.12", + "resolved": "https://registry.npmjs.org/@ionic/core/-/core-8.7.12.tgz", + "integrity": "sha512-+QnytOHsMMDEz45hi/t9AN8ATaWMNZ7jNdx621BGSHi0JkEl1c4NylL3cfYIPJ/78y40ZG5NzprwNiR9sXdswg==", "license": "MIT", "dependencies": { "@stencil/core": "4.38.0", "ionicons": "^8.0.13", "tslib": "^2.1.0" + }, + "engines": { + "node": "24.x" } }, "node_modules/@ionic/core/node_modules/tslib": { @@ -4019,4 +4022,4 @@ "dev": true } } -} \ No newline at end of file +}