From f6c3fd9b3e383da408a7b0e0c04a09e5b849017a Mon Sep 17 00:00:00 2001 From: Nils Gereke Date: Mon, 28 Sep 2026 21:04:00 +0200 Subject: [PATCH 1/2] fix: import ionic utilities --- scripts/check-esm.mjs | 4 ++++ scripts/check-esm.test.mjs | 6 ++++++ src/popover/animations/ios.enter.ts | 4 ++-- src/popover/animations/ios.leave.ts | 4 ++-- src/popover/popover-interface.ts | 2 +- src/theme.ts | 2 +- src/transition/ios.transition.ts | 4 ++-- 7 files changed, 18 insertions(+), 8 deletions(-) diff --git a/scripts/check-esm.mjs b/scripts/check-esm.mjs index cbb69c5..9fae48a 100755 --- a/scripts/check-esm.mjs +++ b/scripts/check-esm.mjs @@ -37,6 +37,10 @@ try { : ts.isImportTypeNode(node) && ts.isLiteralTypeNode(node.argument) ? node.argument.literal : undefined; + // The root is Ionic lazy-loader build. Bundlers then emit every component as a chunk, and apps get a second gesture controller. + if (specifier && ts.isStringLiteral(specifier) && !declaration) { + assert.notEqual(specifier.text, '@ionic/core', `${relative}: import from @ionic/core/components instead of @ionic/core`); + } if (specifier && ts.isStringLiteral(specifier) && specifier.text.startsWith('.')) { assert.ok(specifier.text.endsWith('.js'), `${relative}: missing .js extension in ${specifier.text}`); const target = declaration ? specifier.text.replace(/\.js$/, '.d.ts') : specifier.text; diff --git a/scripts/check-esm.test.mjs b/scripts/check-esm.test.mjs index 20953b4..cae8334 100644 --- a/scripts/check-esm.test.mjs +++ b/scripts/check-esm.test.mjs @@ -88,6 +88,12 @@ test('imports subpath entry points and catches import-time DOM access', () => { assert.match(result.output, /document is not defined/); }); +test('rejects runtime imports from the @ionic/core root', () => { + const result = run(fixture('ionic-root', { native: "export { createAnimation } from '@ionic/core';" })); + assert.notEqual(result.status, 0); + assert.match(result.output, /native\.js: import from @ionic\/core\/components instead of @ionic\/core/); +}); + test('rejects extensionless references in declarations', () => { const directory = fixture('declaration'); writeFileSync(join(directory, 'dist/index.d.ts'), "export type Value = import('./detail').Value;"); diff --git a/src/popover/animations/ios.enter.ts b/src/popover/animations/ios.enter.ts index 8d68957..37ab1b6 100644 --- a/src/popover/animations/ios.enter.ts +++ b/src/popover/animations/ios.enter.ts @@ -1,5 +1,5 @@ -import { createAnimation } from '@ionic/core'; -import type { Animation } from '@ionic/core'; +import { createAnimation } from '@ionic/core/components'; +import type { Animation } from '@ionic/core/components'; import { calculateWindowAdjustment, getPopoverDimensions, getPopoverPosition, POPOVER_IOS_BODY_MARGIN } from '../utils.js'; import { createCalloutSurface } from '../callout-surface.js'; import { getElementRoot } from '../../dom.js'; diff --git a/src/popover/animations/ios.leave.ts b/src/popover/animations/ios.leave.ts index b600bb7..b018412 100644 --- a/src/popover/animations/ios.leave.ts +++ b/src/popover/animations/ios.leave.ts @@ -1,7 +1,7 @@ -import { createAnimation } from '@ionic/core'; +import { createAnimation } from '@ionic/core/components'; import { getElementRoot } from '../../dom.js'; -import type { Animation } from '@ionic/core'; +import type { Animation } from '@ionic/core/components'; /** * iOS Popover Leave Animation diff --git a/src/popover/popover-interface.ts b/src/popover/popover-interface.ts index b633da3..2047135 100644 --- a/src/popover/popover-interface.ts +++ b/src/popover/popover-interface.ts @@ -1,4 +1,4 @@ -import type { AnimationBuilder, ComponentProps, ComponentRef, FrameworkDelegate, Mode, OverlayInterface } from '@ionic/core'; +import type { AnimationBuilder, ComponentProps, ComponentRef, FrameworkDelegate, Mode, OverlayInterface } from '@ionic/core/components'; export interface PopoverInterface extends OverlayInterface { present: (event?: MouseEvent | TouchEvent | PointerEvent) => Promise; diff --git a/src/theme.ts b/src/theme.ts index 29b1fe0..15a52e1 100644 --- a/src/theme.ts +++ b/src/theme.ts @@ -1,4 +1,4 @@ -import type { IonicConfig } from '@ionic/core'; +import type { IonicConfig } from '@ionic/core/components'; import type { AnimationPosition } from './sheets-of-glass.js'; export const cloneElement = (tagName: string, useCache: boolean = true): HTMLElement => { diff --git a/src/transition/ios.transition.ts b/src/transition/ios.transition.ts index e19d903..1dd54d7 100644 --- a/src/transition/ios.transition.ts +++ b/src/transition/ios.transition.ts @@ -1,5 +1,5 @@ -import type { Animation } from '@ionic/core'; -import { createAnimation } from '@ionic/core'; +import type { Animation } from '@ionic/core/components'; +import { createAnimation } from '@ionic/core/components'; /** Options consumed by the shared iOS page transition animation. */ export interface IosTransitionAnimationOptions { From 67549dae6417b1e4203b71bfbd7b3709f7a1eed8 Mon Sep 17 00:00:00 2001 From: Nils Gereke Date: Fri, 2 Oct 2026 04:04:59 +0200 Subject: [PATCH 2/2] fix: ionic 8 support --- scripts/check-esm.mjs | 6 +++++- scripts/check-esm.test.mjs | 8 +++++++- src/popover/animations/ios.enter.ts | 2 +- src/popover/animations/ios.leave.ts | 2 +- src/transition/ios.transition.ts | 2 +- 5 files changed, 15 insertions(+), 5 deletions(-) diff --git a/scripts/check-esm.mjs b/scripts/check-esm.mjs index 9fae48a..303c8e8 100755 --- a/scripts/check-esm.mjs +++ b/scripts/check-esm.mjs @@ -38,8 +38,12 @@ try { ? node.argument.literal : undefined; // The root is Ionic lazy-loader build. Bundlers then emit every component as a chunk, and apps get a second gesture controller. + // The bare components subpath is a directory import in Node, Ionic 8 has no exports map for it. if (specifier && ts.isStringLiteral(specifier) && !declaration) { - assert.notEqual(specifier.text, '@ionic/core', `${relative}: import from @ionic/core/components instead of @ionic/core`); + assert.ok( + specifier.text !== '@ionic/core' && specifier.text !== '@ionic/core/components', + `${relative}: import from @ionic/core/components/index.js instead of ${specifier.text}`, + ); } if (specifier && ts.isStringLiteral(specifier) && specifier.text.startsWith('.')) { assert.ok(specifier.text.endsWith('.js'), `${relative}: missing .js extension in ${specifier.text}`); diff --git a/scripts/check-esm.test.mjs b/scripts/check-esm.test.mjs index cae8334..2f54030 100644 --- a/scripts/check-esm.test.mjs +++ b/scripts/check-esm.test.mjs @@ -91,7 +91,13 @@ test('imports subpath entry points and catches import-time DOM access', () => { test('rejects runtime imports from the @ionic/core root', () => { const result = run(fixture('ionic-root', { native: "export { createAnimation } from '@ionic/core';" })); assert.notEqual(result.status, 0); - assert.match(result.output, /native\.js: import from @ionic\/core\/components instead of @ionic\/core/); + assert.match(result.output, /native\.js: import from @ionic\/core\/components\/index\.js instead of @ionic\/core\n/); +}); + +test('rejects runtime imports from the bare @ionic/core/components subpath', () => { + const result = run(fixture('ionic-components-dir', { native: "export { createAnimation } from '@ionic/core/components';" })); + assert.notEqual(result.status, 0); + assert.match(result.output, /native\.js: import from @ionic\/core\/components\/index\.js instead of @ionic\/core\/components\n/); }); test('rejects extensionless references in declarations', () => { diff --git a/src/popover/animations/ios.enter.ts b/src/popover/animations/ios.enter.ts index 37ab1b6..9593c6b 100644 --- a/src/popover/animations/ios.enter.ts +++ b/src/popover/animations/ios.enter.ts @@ -1,4 +1,4 @@ -import { createAnimation } from '@ionic/core/components'; +import { createAnimation } from '@ionic/core/components/index.js'; import type { Animation } from '@ionic/core/components'; import { calculateWindowAdjustment, getPopoverDimensions, getPopoverPosition, POPOVER_IOS_BODY_MARGIN } from '../utils.js'; import { createCalloutSurface } from '../callout-surface.js'; diff --git a/src/popover/animations/ios.leave.ts b/src/popover/animations/ios.leave.ts index b018412..4469cd3 100644 --- a/src/popover/animations/ios.leave.ts +++ b/src/popover/animations/ios.leave.ts @@ -1,4 +1,4 @@ -import { createAnimation } from '@ionic/core/components'; +import { createAnimation } from '@ionic/core/components/index.js'; import { getElementRoot } from '../../dom.js'; import type { Animation } from '@ionic/core/components'; diff --git a/src/transition/ios.transition.ts b/src/transition/ios.transition.ts index 1dd54d7..3c06b1e 100644 --- a/src/transition/ios.transition.ts +++ b/src/transition/ios.transition.ts @@ -1,5 +1,5 @@ import type { Animation } from '@ionic/core/components'; -import { createAnimation } from '@ionic/core/components'; +import { createAnimation } from '@ionic/core/components/index.js'; /** Options consumed by the shared iOS page transition animation. */ export interface IosTransitionAnimationOptions {