feat(react): add custom elements bundle (#23896)

This commit is contained in:
Liam DeBeasi
2021-09-13 14:53:28 -04:00
committed by GitHub
parent d1763fc8b5
commit c50d895370
57 changed files with 321 additions and 565 deletions

View File

@ -377,28 +377,6 @@ jobs:
command: npm run test.spec
working_directory: /tmp/workspace/packages/react
test-react-router-spec:
<<: *defaults
steps:
- checkout
- attach_workspace:
at: /tmp/workspace
- run:
command: sudo npm link
working_directory: /tmp/workspace/core
- run:
command: sudo npm link @ionic/core
working_directory: /tmp/workspace/packages/react
- run:
command: sudo npm link
working_directory: /tmp/workspace/packages/react
- run:
command: sudo npm link @ionic/react
working_directory: /tmp/workspace/packages/react-router
- run:
command: npm run test.spec
working_directory: /tmp/workspace/packages/react-router
install-react-test-app:
<<: *defaults
steps:
@ -537,8 +515,6 @@ workflows:
requires: [build-react-router]
- test-react-spec:
requires: [build-react]
- test-react-router-spec:
requires: [build-react-router]
- install-react-test-app:
requires: [build-core]
- test-react-e2e:

14
core/package-lock.json generated
View File

@ -18,7 +18,7 @@
"@jest/core": "^26.6.3",
"@rollup/plugin-node-resolve": "^8.4.0",
"@rollup/plugin-virtual": "^2.0.3",
"@stencil/react-output-target": "^0.0.12",
"@stencil/react-output-target": "^0.1.0-2",
"@stencil/sass": "1.3.2",
"@stencil/vue-output-target": "^0.5.1",
"@types/jest": "^26.0.20",
@ -1369,9 +1369,9 @@
}
},
"node_modules/@stencil/react-output-target": {
"version": "0.0.12",
"resolved": "https://registry.npmjs.org/@stencil/react-output-target/-/react-output-target-0.0.12.tgz",
"integrity": "sha512-X/lWAI/FW4tg/pjwe5UWy8KbRk2vWcWR+S6tBqNzKO6pKD6qr60dfajN13EO9nnm5hGr48FP1m/M8kqFbjpZrg==",
"version": "0.1.0-2",
"resolved": "https://registry.npmjs.org/@stencil/react-output-target/-/react-output-target-0.1.0-2.tgz",
"integrity": "sha512-kIxhK+NVaBinS//s/Z4Ylz3q0ZXpu1jIHIcYi7af/tuOirCxHX2EUOja3VRxl37UGRvwv+r4eds9tgUzPLX7rA==",
"dev": true,
"peerDependencies": {
"@stencil/core": ">=1.8.0"
@ -15021,9 +15021,9 @@
"integrity": "sha512-QsxWayZyusnqSZrlCl81R71rA3KqFjVVQSH4E0rGN15F1GdQaFonKlHLyCOLKLig1zzC+DQkLLiUuocexuvdeQ=="
},
"@stencil/react-output-target": {
"version": "0.0.12",
"resolved": "https://registry.npmjs.org/@stencil/react-output-target/-/react-output-target-0.0.12.tgz",
"integrity": "sha512-X/lWAI/FW4tg/pjwe5UWy8KbRk2vWcWR+S6tBqNzKO6pKD6qr60dfajN13EO9nnm5hGr48FP1m/M8kqFbjpZrg==",
"version": "0.1.0-2",
"resolved": "https://registry.npmjs.org/@stencil/react-output-target/-/react-output-target-0.1.0-2.tgz",
"integrity": "sha512-kIxhK+NVaBinS//s/Z4Ylz3q0ZXpu1jIHIcYi7af/tuOirCxHX2EUOja3VRxl37UGRvwv+r4eds9tgUzPLX7rA==",
"dev": true
},
"@stencil/sass": {

View File

@ -40,7 +40,7 @@
"@jest/core": "^26.6.3",
"@rollup/plugin-node-resolve": "^8.4.0",
"@rollup/plugin-virtual": "^2.0.3",
"@stencil/react-output-target": "^0.0.12",
"@stencil/react-output-target": "^0.1.0-2",
"@stencil/sass": "1.3.2",
"@stencil/vue-output-target": "^0.5.1",
"@types/jest": "^26.0.20",

View File

@ -148,6 +148,12 @@ export class Menu implements ComponentInterface, MenuI {
@Event() protected ionMenuChange!: EventEmitter<MenuChangeEventDetail>;
async connectedCallback() {
// TODO: connectedCallback is fired in CE build
// before WC is defined. This needs to be fixed in Stencil.
if (typeof (customElements as any) !== 'undefined') {
await customElements.whenDefined('ion-menu');
}
if (this.type === undefined) {
this.type = config.get('menuType', 'overlay');
}

View File

@ -60,7 +60,12 @@ export class SplitPane implements ComponentInterface {
this.ionSplitPaneVisible.emit(detail);
}
connectedCallback() {
async connectedCallback() {
// TODO: connectedCallback is fired in CE build
// before WC is defined. This needs to be fixed in Stencil.
if (typeof (customElements as any) !== 'undefined') {
await customElements.whenDefined('ion-split-pane');
}
this.styleChildren();
this.updateState();
}

View File

@ -64,6 +64,7 @@ export const config: Config = {
outputTargets: [
reactOutputTarget({
componentCorePackage: '@ionic/core',
includeImportCustomElements: true,
includePolyfills: false,
includeDefineCustomElements: false,
proxiesFile: '../packages/react/src/components/proxies.ts',

View File

@ -26,8 +26,7 @@
"release": "np --any-branch --no-cleanup",
"lint": "tslint --project .",
"lint.fix": "tslint --project . --fix",
"tsc": "tsc -p .",
"test.spec": "jest --ci"
"tsc": "tsc -p ."
},
"main": "dist/index.js",
"module": "dist/index.esm.js",
@ -49,16 +48,11 @@
"@ionic/core": "6.0.0-beta.5",
"@ionic/react": "6.0.0-beta.5",
"@rollup/plugin-node-resolve": "^8.1.0",
"@testing-library/jest-dom": "^5.11.6",
"@testing-library/react": "^11.2.2",
"@testing-library/user-event": "^12.0.11",
"@types/jest": "^26.0.15",
"@types/node": "^14.0.14",
"@types/react": "16.14.0",
"@types/react-dom": "^16.9.0",
"@types/react-router": "^5.0.3",
"@types/react-router-dom": "^5.1.5",
"jest": "^26.6.3",
"np": "^6.4.0",
"prettier": "^2.2.0",
"react": "^16.9.0",
@ -68,33 +62,9 @@
"rimraf": "^3.0.2",
"rollup": "^2.26.4",
"rollup-plugin-sourcemaps": "^0.6.2",
"ts-jest": "^26.4.4",
"tslint": "^6.1.2",
"tslint-ionic-rules": "0.0.21",
"tslint-react": "^5.0.0",
"typescript": "^3.9.5"
},
"jest": {
"preset": "ts-jest",
"setupFilesAfterEnv": [
"<rootDir>/setupTests.ts"
],
"testPathIgnorePatterns": [
"node_modules",
"dist-transpiled",
"dist",
"<rootDir>/test-app"
],
"globals": {
"ts-jest": {
"diagnostics": false
}
},
"modulePaths": [
"<rootDir>"
],
"moduleNameMapper": {
"\\.(css|jpg|png|svg)$": "<rootDir>/empty-module.js"
}
}
}

View File

@ -1,11 +0,0 @@
import '@testing-library/jest-dom/extend-expect';
window.matchMedia =
window.matchMedia ||
(function () {
return {
matches: false,
addListener() {},
removeListener() {},
};
} as any);

View File

@ -1,73 +0,0 @@
import React, { useRef, useEffect } from 'react';
import { IonApp, IonRouterOutlet, IonPage } from '@ionic/react';
import { IonReactMemoryRouter } from '../ReactRouter/IonReactMemoryRouter';
import { render, waitForElement } from '@testing-library/react';
import { Route } from 'react-router';
// import {Router} from '../Router';
import { MemoryHistory, createMemoryHistory } from 'history';
describe('Router', () => {
// This test fails because the ion-router-outlet web component (from core)
// isn't supported in JSDOM, so it never registers
// TODO: figure out why they are failing on new router code when they worked before
describe('on first page render', () => {
let history: MemoryHistory;
let IonTestApp: React.ComponentType<any>;
beforeEach(() => {
history = createMemoryHistory();
IonTestApp = ({ Page }) => {
return (
<IonApp>
<IonReactMemoryRouter history={history}>
{/* <IonRouterOutlet> */}
<Route path="/" component={Page} exact />
{/* </IonRouterOutlet> */}
</IonReactMemoryRouter>
</IonApp>
);
};
});
it.skip('should be visible', () => {
const MyPage = () => {
return (
<IonPage className="ion-page-invisible">
<div>hello</div>
</IonPage>
);
};
const { container } = render(<IonTestApp Page={MyPage} />);
console.log(container.outerHTML);
const page = container.getElementsByClassName('ion-page')[0];
expect(page).not.toHaveClass('ion-page-invisible');
expect(page).toHaveStyle('z-index: 101');
});
it.skip('should fire initial lifecycle events', async () => {
const ionViewWillEnterListener = jest.fn();
const ionViewDidEnterListener = jest.fn();
const MyPage = () => {
const ref = useRef<HTMLDivElement>();
useEffect(() => {
ref.current.addEventListener('ionViewWillEnter', ionViewWillEnterListener);
ref.current.addEventListener('ionViewDidEnter', ionViewDidEnterListener);
}, []);
return (
<IonPage data-testid="mypage" ref={ref}>
<div>hello</div>
</IonPage>
);
};
render(<IonTestApp Page={MyPage} />);
expect(ionViewWillEnterListener).toHaveBeenCalledTimes(1);
expect(ionViewDidEnterListener).toHaveBeenCalledTimes(1);
});
});
});

View File

@ -14,6 +14,7 @@
"@capacitor/ios": "^2.2.0",
"@ionic/react": "5.6.3",
"@ionic/react-router": "^5.6.3",
"@stencil/core": "^2.8.0",
"@svgr/webpack": "4.3.3",
"@testing-library/jest-dom": "^4.2.4",
"@testing-library/react": "^9.4.0",
@ -77,7 +78,7 @@
"style-loader": "0.23.1",
"terser-webpack-plugin": "2.3.4",
"ts-pnp": "1.1.5",
"typescript": "^3.9.5",
"typescript": "^4.4.2",
"url-loader": "2.3.0",
"wait-on": "^5.3.0",
"webpack": "4.41.5",
@ -2027,9 +2028,9 @@
"integrity": "sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ=="
},
"node_modules/@stencil/core": {
"version": "2.5.2",
"resolved": "https://registry.npmjs.org/@stencil/core/-/core-2.5.2.tgz",
"integrity": "sha512-bgjPXkSzzg1WnTgVUm6m5ZzpKt602WmA/QljODAW1xVN40OHJdbGblzF/F6MFzqv2c5Cy30CB41arc8qADIdcQ==",
"version": "2.8.0",
"resolved": "https://registry.npmjs.org/@stencil/core/-/core-2.8.0.tgz",
"integrity": "sha512-WazFGUMnbumg8ePNvej8cIOEcxvuZ0ugKQkkE1xFbDYcl7DgJd62MiG+bIqCcQlIdLEfhjAdoixxlFdJgrgjyA==",
"bin": {
"stencil": "bin/stencil"
},
@ -19603,10 +19604,9 @@
"integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c="
},
"node_modules/typescript": {
"version": "3.9.10",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-3.9.10.tgz",
"integrity": "sha512-w6fIxVE/H1PkLKcCPsFqKE7Kv7QUwhU8qQY2MueZXWx5cPZdwFupLgKK3vntcK98BtNHZtAF4LA/yl2a7k8R6Q==",
"license": "Apache-2.0",
"version": "4.4.2",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.4.2.tgz",
"integrity": "sha512-gzP+t5W4hdy4c+68bfcv0t400HVJMMd2+H9B7gae1nQlBzCqvrXX+6GL/b3GAgyTH966pzrZ70/fRjwAtZksSQ==",
"bin": {
"tsc": "bin/tsc",
"tsserver": "bin/tsserver"
@ -22991,9 +22991,9 @@
"integrity": "sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ=="
},
"@stencil/core": {
"version": "2.5.2",
"resolved": "https://registry.npmjs.org/@stencil/core/-/core-2.5.2.tgz",
"integrity": "sha512-bgjPXkSzzg1WnTgVUm6m5ZzpKt602WmA/QljODAW1xVN40OHJdbGblzF/F6MFzqv2c5Cy30CB41arc8qADIdcQ=="
"version": "2.8.0",
"resolved": "https://registry.npmjs.org/@stencil/core/-/core-2.8.0.tgz",
"integrity": "sha512-WazFGUMnbumg8ePNvej8cIOEcxvuZ0ugKQkkE1xFbDYcl7DgJd62MiG+bIqCcQlIdLEfhjAdoixxlFdJgrgjyA=="
},
"@svgr/babel-plugin-add-jsx-attribute": {
"version": "4.2.0",
@ -37500,9 +37500,9 @@
"integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c="
},
"typescript": {
"version": "3.9.10",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-3.9.10.tgz",
"integrity": "sha512-w6fIxVE/H1PkLKcCPsFqKE7Kv7QUwhU8qQY2MueZXWx5cPZdwFupLgKK3vntcK98BtNHZtAF4LA/yl2a7k8R6Q=="
"version": "4.4.2",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.4.2.tgz",
"integrity": "sha512-gzP+t5W4hdy4c+68bfcv0t400HVJMMd2+H9B7gae1nQlBzCqvrXX+6GL/b3GAgyTH966pzrZ70/fRjwAtZksSQ=="
},
"undefsafe": {
"version": "2.0.3",

View File

@ -9,6 +9,7 @@
"@capacitor/ios": "^2.2.0",
"@ionic/react": "5.6.3",
"@ionic/react-router": "^5.6.3",
"@stencil/core": "^2.8.0",
"@svgr/webpack": "4.3.3",
"@testing-library/jest-dom": "^4.2.4",
"@testing-library/react": "^9.4.0",
@ -72,7 +73,7 @@
"style-loader": "0.23.1",
"terser-webpack-plugin": "2.3.4",
"ts-pnp": "1.1.5",
"typescript": "^3.9.5",
"typescript": "^4.4.2",
"url-loader": "2.3.0",
"wait-on": "^5.3.0",
"webpack": "4.41.5",

View File

@ -9,11 +9,11 @@ rm -rf node_modules/@ionic/react-router/dist
cp -a ../dist node_modules/@ionic/react-router/dist
cp -a ../package.json node_modules/@ionic/react-router/package.json
# Copy core dist
rm -rf node_modules/@ionic/core/dist node_modules/@ionic/core/loader
cp -a ../../../core/dist node_modules/@ionic/core/dist
cp -a ../../../core/loader node_modules/@ionic/core/loader
# Copy core dist and components
rm -rf node_modules/@ionic/core/dist node_modules/@ionic/core/components
cp -a ../../../core/package.json node_modules/@ionic/core/package.json
cp -a ../../../core/dist node_modules/@ionic/core/dist
cp -a ../../../core/components node_modules/@ionic/core/components
# Copy ionicons
rm -rf node_modules/ionicons

View File

@ -36,7 +36,6 @@ import Refs from './pages/refs/Refs';
import DynamicIonpageClassnames from './pages/dynamic-ionpage-classnames/DynamicIonpageClassnames';
import Tabs from './pages/tabs/Tabs';
import TabsSecondary from './pages/tabs/TabsSecondary';
debugger;
const App: React.FC = () => {
return (
<IonApp>

View File

@ -6,7 +6,7 @@ import {
AnimationKeyFrames,
AnimationLifecycle,
createAnimation,
} from '@ionic/core';
} from '@ionic/core/components';
import React from 'react';
interface PartialPropertyValue {

View File

@ -2,7 +2,8 @@ import {
ActionSheetButton as ActionSheetButtonCore,
ActionSheetOptions as ActionSheetOptionsCore,
actionSheetController as actionSheetControllerCore,
} from '@ionic/core';
} from '@ionic/core/components';
import { IonActionSheet as IonActionSheetCmp } from '@ionic/core/components/ion-action-sheet.js';
import { createOverlayComponent } from './createOverlayComponent';
@ -29,4 +30,4 @@ const actionSheetController = {
export const IonActionSheet = /*@__PURE__*/ createOverlayComponent<
ActionSheetOptions,
HTMLIonActionSheetElement
>('IonActionSheet', actionSheetController);
>('ion-action-sheet', actionSheetController, IonActionSheetCmp);

View File

@ -1,8 +1,10 @@
import { AlertOptions, alertController } from '@ionic/core';
import { AlertOptions, alertController } from '@ionic/core/components';
import { IonAlert as IonAlertCmp } from '@ionic/core/components/ion-alert.js';
import { createControllerComponent } from './createControllerComponent';
export const IonAlert = /*@__PURE__*/ createControllerComponent<AlertOptions, HTMLIonAlertElement>(
'IonAlert',
alertController
'ion-alert',
alertController,
IonAlertCmp
);

View File

@ -4,7 +4,6 @@ import { NavContext } from '../contexts/NavContext';
import { IonicReactProps } from './IonicReactProps';
import { IonIconInner } from './inner-proxies';
import { deprecationWarning } from './react-component-lib/utils/dev';
import { createForwardRef, isPlatform } from './utils';
interface IonIconProps {
@ -29,10 +28,7 @@ class IonIconContainer extends React.PureComponent<InternalProps> {
constructor(props: InternalProps) {
super(props);
if (this.props.name) {
deprecationWarning(
'icon-name',
'In Ionic React, you import icons from "ionicons/icons" and set the icon you imported to the "icon" property. Setting the "name" property has no effect.'
);
console.warn('In Ionic React, you import icons from "ionicons/icons" and set the icon you imported to the "icon" property. Setting the "name" property has no effect.');
}
}

View File

@ -1,8 +1,9 @@
import { LoadingOptions, loadingController } from '@ionic/core';
import { LoadingOptions, loadingController } from '@ionic/core/components';
import { IonLoading as IonLoadingCmp } from '@ionic/core/components/ion-loading.js';
import { createControllerComponent } from './createControllerComponent';
export const IonLoading = /*@__PURE__*/ createControllerComponent<
LoadingOptions,
HTMLIonLoadingElement
>('IonLoading', loadingController);
>('ion-loading', loadingController, IonLoadingCmp);

View File

@ -1,8 +1,9 @@
import { JSX } from '@ionic/core';
import { JSX } from '@ionic/core/components';
import { IonModal as IonModalCmp } from '@ionic/core/components/ion-modal.js';
import { createInlineOverlayComponent } from './createInlineOverlayComponent'
export const IonModal = /*@__PURE__*/ createInlineOverlayComponent<
JSX.IonModal,
HTMLIonModalElement
>('ion-modal');
>('ion-modal', IonModalCmp);

View File

@ -1,8 +1,9 @@
import { PickerOptions, pickerController } from '@ionic/core';
import { PickerOptions, pickerController } from '@ionic/core/components';
import { IonPicker as IonPickerCmp } from '@ionic/core/components/ion-picker.js';
import { createControllerComponent } from './createControllerComponent';
export const IonPicker = /*@__PURE__*/ createControllerComponent<
PickerOptions,
HTMLIonPickerElement
>('IonPicker', pickerController);
>('ion-picker', pickerController, IonPickerCmp);

View File

@ -1,8 +1,9 @@
import { JSX } from '@ionic/core';
import { JSX } from '@ionic/core/components';
import { IonPopover as IonPopoverCmp } from '@ionic/core/components/ion-popover.js';
import { createInlineOverlayComponent } from './createInlineOverlayComponent'
export const IonPopover = /*@__PURE__*/ createInlineOverlayComponent<
JSX.IonPopover,
HTMLIonPopoverElement
>('ion-popover');
>('ion-popover', IonPopoverCmp);

View File

@ -1,4 +1,4 @@
import { AnimationBuilder } from '@ionic/core';
import { AnimationBuilder } from '@ionic/core/components';
import React, { useContext } from 'react';
import { RouteAction, RouterDirection, RouterOptions } from '../models';

View File

@ -1,4 +1,4 @@
import { JSX as LocalJSX } from '@ionic/core';
import { JSX as LocalJSX } from '@ionic/core/components';
import React from 'react';
import { NavContext } from '../contexts/NavContext';

View File

@ -2,7 +2,8 @@ import {
ToastButton as ToastButtonCore,
ToastOptions as ToastOptionsCore,
toastController as toastControllerCore,
} from '@ionic/core';
} from '@ionic/core/components';
import { IonToast as IonToastCmp } from '@ionic/core/components/ion-toast.js';
import { createControllerComponent } from './createControllerComponent';
@ -27,6 +28,7 @@ const toastController = {
};
export const IonToast = /*@__PURE__*/ createControllerComponent<ToastOptions, HTMLIonToastElement>(
'IonToast',
toastController
'ion-toast',
toastController,
IonToastCmp
);

View File

@ -1,27 +0,0 @@
import React from 'react';
import { render, fireEvent, cleanup } from '@testing-library/react';
import { IonButton } from '../index';
import { defineCustomElements } from '@ionic/core/loader';
describe('IonButton', () => {
beforeAll(async (done) => {
await defineCustomElements(window);
done();
});
afterEach(cleanup);
it('should render a button', () => {
const { getByText } = render(<IonButton>my button</IonButton>);
const button = getByText('my button');
expect(button).toBeDefined();
});
it('when the button is clicked, it should call the click handler', () => {
const clickSpy = jest.fn();
const { getByText } = render(<IonButton onClick={clickSpy}>my button</IonButton>);
const button = getByText('my button');
fireEvent.click(button);
expect(clickSpy).toHaveBeenCalled();
});
});

View File

@ -1,87 +0,0 @@
import React from 'react';
import { IonTabs, IonTabButton, IonLabel, IonIcon, IonTabBar } from '../index';
import { render, cleanup } from '@testing-library/react';
import { IonRouterOutlet } from '../IonRouterOutlet';
afterEach(cleanup);
describe('IonTabs', () => {
test('should render happy path', () => {
const { container } = render(
<IonTabs>
<IonRouterOutlet></IonRouterOutlet>
<IonTabBar slot="bottom">
<IonTabButton tab="schedule">
<IonLabel>Schedule</IonLabel>
<IonIcon name="schedule"></IonIcon>
</IonTabButton>
<IonTabButton tab="speakers">
<IonLabel>Speakers</IonLabel>
<IonIcon name="speakers"></IonIcon>
</IonTabButton>
<IonTabButton tab="map">
<IonLabel>Map</IonLabel>
<IonIcon name="map"></IonIcon>
</IonTabButton>
<IonTabButton tab="about">
<IonLabel>About</IonLabel>
<IonIcon name="about"></IonIcon>
</IonTabButton>
</IonTabBar>
</IonTabs>
);
expect(container.children[0].children.length).toEqual(2);
expect(container.children[0].children[0].tagName).toEqual('DIV');
expect(container.children[0].children[0].className).toEqual('tabs-inner');
expect(container.children[0].children[1].tagName).toEqual('ION-TAB-BAR');
expect(container.children[0].children[1].children.length).toEqual(4);
expect(Array.from(container.children[0].children[1].children).map((c) => c.tagName)).toEqual([
'ION-TAB-BUTTON',
'ION-TAB-BUTTON',
'ION-TAB-BUTTON',
'ION-TAB-BUTTON',
]);
});
test('should allow for conditional children', () => {
const { container } = render(
<IonTabs>
<IonRouterOutlet></IonRouterOutlet>
<IonTabBar slot="bottom">
{false && (
<IonTabButton tab="schedule">
<IonLabel>Schedule</IonLabel>
<IonIcon name="schedule"></IonIcon>
</IonTabButton>
)}
<IonTabButton tab="speakers">
<IonLabel>Speakers</IonLabel>
<IonIcon name="speakers"></IonIcon>
</IonTabButton>
<IonTabButton tab="map">
<IonLabel>Map</IonLabel>
<IonIcon name="map"></IonIcon>
</IonTabButton>
<IonTabButton tab="about">
<IonLabel>About</IonLabel>
<IonIcon name="about"></IonIcon>
</IonTabButton>
</IonTabBar>
</IonTabs>
);
expect(container.children[0].children.length).toEqual(2);
expect(container.children[0].children[0].tagName).toEqual('DIV');
expect(container.children[0].children[0].className).toEqual('tabs-inner');
expect(container.children[0].children[1].tagName).toEqual('ION-TAB-BAR');
expect(container.children[0].children[1].children.length).toEqual(3);
expect(Array.from(container.children[0].children[1].children).map((c) => c.tagName)).toEqual([
'ION-TAB-BUTTON',
'ION-TAB-BUTTON',
'ION-TAB-BUTTON',
]);
});
});

View File

@ -1,128 +0,0 @@
import React from 'react';
import { JSX } from '@ionic/core';
import { createReactComponent } from '../react-component-lib';
import { render, fireEvent, cleanup, RenderResult } from '@testing-library/react';
import { IonButton } from '../index';
afterEach(cleanup);
describe('createComponent - events', () => {
test('should set events on handler', () => {
const FakeOnClick = jest.fn((e) => e);
const IonButton = createReactComponent<JSX.IonButton, HTMLIonButtonElement>('ion-button');
const { getByText } = render(<IonButton onClick={FakeOnClick}>ButtonNameA</IonButton>);
fireEvent.click(getByText('ButtonNameA'));
expect(FakeOnClick).toBeCalledTimes(1);
});
test('should add custom events', () => {
const FakeIonFocus = jest.fn((e) => e);
const IonInput = createReactComponent<JSX.IonInput, HTMLIonInputElement>('ion-input');
const { getByText } = render(<IonInput onIonFocus={FakeIonFocus}>ButtonNameA</IonInput>);
const ionInputItem = getByText('ButtonNameA');
expect(Object.keys((ionInputItem as any).__events)).toEqual(['ionFocus']);
});
});
describe('createComponent - ref', () => {
test('should pass ref on to web component instance (RefObject)', () => {
const ionButtonRef: React.RefObject<any> = React.createRef();
const IonButton = createReactComponent<JSX.IonButton, HTMLIonButtonElement>('ion-button');
const { getByText } = render(<IonButton ref={ionButtonRef}>ButtonNameA</IonButton>);
const ionButtonItem = getByText('ButtonNameA');
expect(ionButtonRef.current).toEqual(ionButtonItem);
});
test('should pass ref on to web component instance (RefCallback)', () => {
let current
const ionButtonRef: React.RefCallback<any> = value => current = value;
const IonButton = createReactComponent<JSX.IonButton, HTMLIonButtonElement>('ion-button');
const { getByText } = render(<IonButton ref={ionButtonRef}>ButtonNameA</IonButton>);
const ionButtonItem = getByText('ButtonNameA');
expect(current).toEqual(ionButtonItem);
});
});
describe('createComponent - strict mode', () => {
beforeEach(() => (console.error = (...data: any[]) => {
throw new Error(...data);
}));
test('should work without errors in strict mode', () => {
const renderResult = render(
<React.StrictMode>
<IonButton>Strict Mode Rocks</IonButton>
</React.StrictMode>
);
expect(renderResult.getByText(/Rocks/)).toBeTruthy();
});
});
describe('when working with css classes', () => {
const myClass = 'my-class';
const myClass2 = 'my-class2';
const customClass = 'custom-class';
describe('when a class is added to className', () => {
let renderResult: RenderResult;
let button: HTMLElement;
beforeEach(() => {
renderResult = render(<IonButton className={myClass}>Hello!</IonButton>);
button = renderResult.getByText(/Hello/);
});
it('then it should be in the class list', () => {
expect(button.classList.contains(myClass)).toBeTruthy();
});
it('when a class is added to class list outside of React, then that class should still be in class list when rendered again', () => {
button.classList.add(customClass);
expect(button.classList.contains(customClass)).toBeTruthy();
renderResult.rerender(<IonButton className={myClass}>Hello!</IonButton>);
expect(button.classList.contains(customClass)).toBeTruthy();
});
});
describe('when multiple classes are added to className', () => {
let renderResult: RenderResult;
let button: HTMLElement;
beforeEach(() => {
renderResult = render(<IonButton className={myClass + ' ' + myClass2}>Hello!</IonButton>);
button = renderResult.getByText(/Hello/);
});
it('then both classes should be in class list', () => {
expect(button.classList.contains(myClass)).toBeTruthy();
expect(button.classList.contains(myClass2)).toBeTruthy();
});
it('when one of the classes is removed, then only the remaining class should be in class list', () => {
expect(button.classList.contains(myClass)).toBeTruthy();
expect(button.classList.contains(myClass2)).toBeTruthy();
renderResult.rerender(<IonButton className={myClass}>Hello!</IonButton>);
expect(button.classList.contains(myClass)).toBeTruthy();
expect(button.classList.contains(myClass2)).toBeFalsy();
});
it('when a custom class is added outside of React and one of the classes is removed, then only the remaining class and the custom class should be in class list', () => {
button.classList.add(customClass);
expect(button.classList.contains(myClass)).toBeTruthy();
expect(button.classList.contains(myClass2)).toBeTruthy();
expect(button.classList.contains(customClass)).toBeTruthy();
renderResult.rerender(<IonButton className={myClass}>Hello!</IonButton>);
expect(button.classList.contains(myClass)).toBeTruthy();
expect(button.classList.contains(myClass)).toBeTruthy();
expect(button.classList.contains(myClass2)).toBeFalsy();
});
});
});

View File

@ -1,7 +1,7 @@
import { OverlayEventDetail } from '@ionic/core';
import { OverlayEventDetail } from '@ionic/core/components';
import React from 'react';
import { attachProps, setRef } from './react-component-lib/utils';
import { attachProps, dashToPascalCase, defineCustomElement, setRef } from './react-component-lib/utils';
interface OverlayBase extends HTMLElement {
present: () => Promise<void>;
@ -20,9 +20,13 @@ export const createControllerComponent = <
OptionsType extends object,
OverlayType extends OverlayBase
>(
displayName: string,
controller: { create: (options: OptionsType) => Promise<OverlayType> }
tagName: string,
controller: { create: (options: OptionsType) => Promise<OverlayType> },
customElement?: any
) => {
defineCustomElement(tagName, customElement);
const displayName = dashToPascalCase(tagName);
const didDismissEventName = `on${displayName}DidDismiss`;
const didPresentEventName = `on${displayName}DidPresent`;
const willDismissEventName = `on${displayName}WillDismiss`;

View File

@ -1,16 +1,15 @@
import { OverlayEventDetail } from '@ionic/core'
import { OverlayEventDetail } from '@ionic/core/components'
import React from 'react';
import {
attachProps,
camelToDashCase,
dashToPascalCase,
defineCustomElement,
isCoveredByReact,
mergeRefs,
} from './react-component-lib/utils';
import {
createForwardRef
} from './utils';
import { createForwardRef } from './utils';
type InlineOverlayState = {
isOpen: boolean;
@ -26,8 +25,11 @@ interface IonicReactInternalProps<ElementType> extends React.HTMLAttributes<Elem
}
export const createInlineOverlayComponent = <PropType, ElementType>(
tagName: string
tagName: string,
customElement?: any
) => {
defineCustomElement(tagName, customElement);
const displayName = dashToPascalCase(tagName);
const ReactComponent = class extends React.Component<IonicReactInternalProps<PropType>, InlineOverlayState> {
ref: React.RefObject<HTMLElement>;

View File

@ -1,8 +1,8 @@
import { OverlayEventDetail } from '@ionic/core';
import { OverlayEventDetail } from '@ionic/core/components';
import React from 'react';
import ReactDOM from 'react-dom';
import { attachProps, setRef } from './react-component-lib/utils';
import { attachProps, dashToPascalCase, defineCustomElement, setRef } from './react-component-lib/utils';
interface OverlayElement extends HTMLElement {
present: () => Promise<void>;
@ -22,9 +22,13 @@ export const createOverlayComponent = <
OverlayComponent extends object,
OverlayType extends OverlayElement
>(
displayName: string,
controller: { create: (options: any) => Promise<OverlayType> }
tagName: string,
controller: { create: (options: any) => Promise<OverlayType> },
customElement?: any
) => {
defineCustomElement(tagName, customElement);
const displayName = dashToPascalCase(tagName);
const didDismissEventName = `on${displayName}DidDismiss`;
const didPresentEventName = `on${displayName}DidPresent`;
const willDismissEventName = `on${displayName}WillDismiss`;

View File

@ -1,4 +1,4 @@
import { AnimationBuilder } from '@ionic/core';
import { AnimationBuilder } from '@ionic/core/components';
import React from 'react';
import { NavContext } from '../contexts/NavContext';
@ -9,12 +9,11 @@ import {
attachProps,
camelToDashCase,
dashToPascalCase,
defineCustomElement,
isCoveredByReact,
mergeRefs,
} from './react-component-lib/utils';
import {
createForwardRef
} from './utils';
import { createForwardRef } from './utils';
interface IonicReactInternalProps<ElementType> extends React.HTMLAttributes<ElementType> {
forwardedRef?: React.ForwardedRef<ElementType>;
@ -27,8 +26,11 @@ interface IonicReactInternalProps<ElementType> extends React.HTMLAttributes<Elem
}
export const createRoutingComponent = <PropType, ElementType>(
tagName: string
tagName: string,
customElement?: any
) => {
defineCustomElement(tagName, customElement);
const displayName = dashToPascalCase(tagName);
const ReactComponent = class extends React.Component<IonicReactInternalProps<PropType>> {
context!: React.ContextType<typeof NavContext>;

View File

@ -1,4 +1,4 @@
import { AnimationBuilder } from '@ionic/core';
import { AnimationBuilder } from '@ionic/core/components';
import { RouterOptions } from '../models';
import { RouterDirection } from '../models/RouterDirection';

View File

@ -1,4 +1,4 @@
import { defineCustomElements } from '@ionic/core/loader';
import { initialize } from '@ionic/core/components';
import { addIcons } from 'ionicons';
import {
arrowBackSharp,
@ -34,6 +34,7 @@ export {
mdTransitionAnimation,
NavComponentWithProps,
setupConfig,
initialize,
IonicSwiper,
SpinnerTypes,
@ -60,7 +61,7 @@ export {
ToastOptions,
ToastButton
} from '@ionic/core';
} from '@ionic/core/components';
export * from './proxies';
export * from './routing-proxies';
@ -122,8 +123,13 @@ addIcons({
'search-sharp': searchSharp,
});
// TODO: defineCustomElements() is asyncronous
// We need to use the promise
if (typeof window !== 'undefined') {
defineCustomElements(window);
}
/**
* By default Ionic Framework hides elements that
* are not hydrated, but in the CE build there is no
* hydration.
* TODO: Remove when all integrations have been
* migrated to CE build.
*/
document.documentElement.classList.add('ion-ce');
initialize();

View File

@ -1,30 +1,35 @@
import { JSX } from '@ionic/core';
import { JSX } from '@ionic/core/components';
import { IonBackButton as IonBackButtonCmp } from '@ionic/core/components/ion-back-button.js';
import { IonRouterOutlet as IonRouterOutletCmp } from '@ionic/core/components/ion-router-outlet.js';
import { IonTabBar as IonTabBarCmp } from '@ionic/core/components/ion-tab-bar.js';
import { IonTabButton as IonTabButtonCmp } from '@ionic/core/components/ion-tab-button.js';
import { JSX as IoniconsJSX } from 'ionicons';
import { IonIcon as IonIconCmp } from 'ionicons/components/ion-icon.js';
import { /*@__PURE__*/ createReactComponent } from './react-component-lib';
export const IonTabButtonInner = /*@__PURE__*/ createReactComponent<
JSX.IonTabButton & { onIonTabButtonClick?: (e: CustomEvent) => void },
HTMLIonTabButtonElement
>('ion-tab-button');
>('ion-tab-button', IonTabButtonCmp);
export const IonTabBarInner = /*@__PURE__*/ createReactComponent<
JSX.IonTabBar,
HTMLIonTabBarElement
>('ion-tab-bar');
>('ion-tab-bar', IonTabBarCmp);
export const IonBackButtonInner = /*@__PURE__*/ createReactComponent<
Omit<JSX.IonBackButton, 'icon'>,
HTMLIonBackButtonElement
>('ion-back-button');
>('ion-back-button', IonBackButtonCmp);
export const IonRouterOutletInner = /*@__PURE__*/ createReactComponent<
JSX.IonRouterOutlet & {
setRef?: (val: HTMLIonRouterOutletElement) => void;
forwardedRef?: React.ForwardedRef<HTMLIonRouterOutletElement>;
},
HTMLIonRouterOutletElement
>('ion-router-outlet');
>('ion-router-outlet', IonRouterOutletCmp);
// ionicons
export const IonIconInner = /*@__PURE__*/ createReactComponent<
IoniconsJSX.IonIcon,
HTMLIonIconElement
>('ion-icon');
>('ion-icon', IonIconCmp);

View File

@ -1,4 +1,4 @@
import { JSX as LocalJSX } from '@ionic/core';
import { JSX as LocalJSX } from '@ionic/core/components';
import React from 'react';
import { NavContext } from '../../contexts/NavContext';

View File

@ -1,4 +1,4 @@
import { JSX as LocalJSX } from '@ionic/core';
import { JSX as LocalJSX } from '@ionic/core/components';
import React, { useContext } from 'react';
import { NavContext } from '../../contexts/NavContext';

View File

@ -1,4 +1,4 @@
import { JSX as LocalJSX } from '@ionic/core';
import { JSX as LocalJSX } from '@ionic/core/components';
import React from 'react';
import { RouterOptions } from '../../models';

View File

@ -1,4 +1,4 @@
import { JSX as LocalJSX } from '@ionic/core';
import { JSX as LocalJSX } from '@ionic/core/components';
import React, { Fragment } from 'react';
import { NavContext } from '../../contexts/NavContext';

View File

@ -3,75 +3,142 @@
/* auto-generated react proxies */
import { createReactComponent } from './react-component-lib';
import type { JSX } from '@ionic/core';
import type { JSX } from '@ionic/core/components';
import { IonAccordion as IonAccordionCmp } from '@ionic/core/components/ion-accordion.js';
import { IonAccordionGroup as IonAccordionGroupCmp } from '@ionic/core/components/ion-accordion-group.js';
import { IonApp as IonAppCmp } from '@ionic/core/components/ion-app.js';
import { IonAvatar as IonAvatarCmp } from '@ionic/core/components/ion-avatar.js';
import { IonBackdrop as IonBackdropCmp } from '@ionic/core/components/ion-backdrop.js';
import { IonBadge as IonBadgeCmp } from '@ionic/core/components/ion-badge.js';
import { IonBreadcrumb as IonBreadcrumbCmp } from '@ionic/core/components/ion-breadcrumb.js';
import { IonBreadcrumbs as IonBreadcrumbsCmp } from '@ionic/core/components/ion-breadcrumbs.js';
import { IonButtons as IonButtonsCmp } from '@ionic/core/components/ion-buttons.js';
import { IonCardContent as IonCardContentCmp } from '@ionic/core/components/ion-card-content.js';
import { IonCardHeader as IonCardHeaderCmp } from '@ionic/core/components/ion-card-header.js';
import { IonCardSubtitle as IonCardSubtitleCmp } from '@ionic/core/components/ion-card-subtitle.js';
import { IonCardTitle as IonCardTitleCmp } from '@ionic/core/components/ion-card-title.js';
import { IonCheckbox as IonCheckboxCmp } from '@ionic/core/components/ion-checkbox.js';
import { IonChip as IonChipCmp } from '@ionic/core/components/ion-chip.js';
import { IonCol as IonColCmp } from '@ionic/core/components/ion-col.js';
import { IonContent as IonContentCmp } from '@ionic/core/components/ion-content.js';
import { IonDatetime as IonDatetimeCmp } from '@ionic/core/components/ion-datetime.js';
import { IonFab as IonFabCmp } from '@ionic/core/components/ion-fab.js';
import { IonFabList as IonFabListCmp } from '@ionic/core/components/ion-fab-list.js';
import { IonFooter as IonFooterCmp } from '@ionic/core/components/ion-footer.js';
import { IonGrid as IonGridCmp } from '@ionic/core/components/ion-grid.js';
import { IonHeader as IonHeaderCmp } from '@ionic/core/components/ion-header.js';
import { IonImg as IonImgCmp } from '@ionic/core/components/ion-img.js';
import { IonInfiniteScroll as IonInfiniteScrollCmp } from '@ionic/core/components/ion-infinite-scroll.js';
import { IonInfiniteScrollContent as IonInfiniteScrollContentCmp } from '@ionic/core/components/ion-infinite-scroll-content.js';
import { IonInput as IonInputCmp } from '@ionic/core/components/ion-input.js';
import { IonItemDivider as IonItemDividerCmp } from '@ionic/core/components/ion-item-divider.js';
import { IonItemGroup as IonItemGroupCmp } from '@ionic/core/components/ion-item-group.js';
import { IonItemOptions as IonItemOptionsCmp } from '@ionic/core/components/ion-item-options.js';
import { IonItemSliding as IonItemSlidingCmp } from '@ionic/core/components/ion-item-sliding.js';
import { IonLabel as IonLabelCmp } from '@ionic/core/components/ion-label.js';
import { IonList as IonListCmp } from '@ionic/core/components/ion-list.js';
import { IonListHeader as IonListHeaderCmp } from '@ionic/core/components/ion-list-header.js';
import { IonMenu as IonMenuCmp } from '@ionic/core/components/ion-menu.js';
import { IonMenuButton as IonMenuButtonCmp } from '@ionic/core/components/ion-menu-button.js';
import { IonMenuToggle as IonMenuToggleCmp } from '@ionic/core/components/ion-menu-toggle.js';
import { IonNav as IonNavCmp } from '@ionic/core/components/ion-nav.js';
import { IonNavLink as IonNavLinkCmp } from '@ionic/core/components/ion-nav-link.js';
import { IonNote as IonNoteCmp } from '@ionic/core/components/ion-note.js';
import { IonProgressBar as IonProgressBarCmp } from '@ionic/core/components/ion-progress-bar.js';
import { IonRadio as IonRadioCmp } from '@ionic/core/components/ion-radio.js';
import { IonRadioGroup as IonRadioGroupCmp } from '@ionic/core/components/ion-radio-group.js';
import { IonRange as IonRangeCmp } from '@ionic/core/components/ion-range.js';
import { IonRefresher as IonRefresherCmp } from '@ionic/core/components/ion-refresher.js';
import { IonRefresherContent as IonRefresherContentCmp } from '@ionic/core/components/ion-refresher-content.js';
import { IonReorder as IonReorderCmp } from '@ionic/core/components/ion-reorder.js';
import { IonReorderGroup as IonReorderGroupCmp } from '@ionic/core/components/ion-reorder-group.js';
import { IonRippleEffect as IonRippleEffectCmp } from '@ionic/core/components/ion-ripple-effect.js';
import { IonRow as IonRowCmp } from '@ionic/core/components/ion-row.js';
import { IonSearchbar as IonSearchbarCmp } from '@ionic/core/components/ion-searchbar.js';
import { IonSegment as IonSegmentCmp } from '@ionic/core/components/ion-segment.js';
import { IonSegmentButton as IonSegmentButtonCmp } from '@ionic/core/components/ion-segment-button.js';
import { IonSelect as IonSelectCmp } from '@ionic/core/components/ion-select.js';
import { IonSelectOption as IonSelectOptionCmp } from '@ionic/core/components/ion-select-option.js';
import { IonSkeletonText as IonSkeletonTextCmp } from '@ionic/core/components/ion-skeleton-text.js';
import { IonSlide as IonSlideCmp } from '@ionic/core/components/ion-slide.js';
import { IonSlides as IonSlidesCmp } from '@ionic/core/components/ion-slides.js';
import { IonSpinner as IonSpinnerCmp } from '@ionic/core/components/ion-spinner.js';
import { IonSplitPane as IonSplitPaneCmp } from '@ionic/core/components/ion-split-pane.js';
import { IonTab as IonTabCmp } from '@ionic/core/components/ion-tab.js';
import { IonText as IonTextCmp } from '@ionic/core/components/ion-text.js';
import { IonTextarea as IonTextareaCmp } from '@ionic/core/components/ion-textarea.js';
import { IonThumbnail as IonThumbnailCmp } from '@ionic/core/components/ion-thumbnail.js';
import { IonTitle as IonTitleCmp } from '@ionic/core/components/ion-title.js';
import { IonToggle as IonToggleCmp } from '@ionic/core/components/ion-toggle.js';
import { IonToolbar as IonToolbarCmp } from '@ionic/core/components/ion-toolbar.js';
import { IonVirtualScroll as IonVirtualScrollCmp } from '@ionic/core/components/ion-virtual-scroll.js';
export const IonAccordion = /*@__PURE__*/createReactComponent<JSX.IonAccordion, HTMLIonAccordionElement>('ion-accordion');
export const IonAccordionGroup = /*@__PURE__*/createReactComponent<JSX.IonAccordionGroup, HTMLIonAccordionGroupElement>('ion-accordion-group');
export const IonApp = /*@__PURE__*/createReactComponent<JSX.IonApp, HTMLIonAppElement>('ion-app');
export const IonAvatar = /*@__PURE__*/createReactComponent<JSX.IonAvatar, HTMLIonAvatarElement>('ion-avatar');
export const IonBackdrop = /*@__PURE__*/createReactComponent<JSX.IonBackdrop, HTMLIonBackdropElement>('ion-backdrop');
export const IonBadge = /*@__PURE__*/createReactComponent<JSX.IonBadge, HTMLIonBadgeElement>('ion-badge');
export const IonBreadcrumb = /*@__PURE__*/createReactComponent<JSX.IonBreadcrumb, HTMLIonBreadcrumbElement>('ion-breadcrumb');
export const IonBreadcrumbs = /*@__PURE__*/createReactComponent<JSX.IonBreadcrumbs, HTMLIonBreadcrumbsElement>('ion-breadcrumbs');
export const IonButtons = /*@__PURE__*/createReactComponent<JSX.IonButtons, HTMLIonButtonsElement>('ion-buttons');
export const IonCardContent = /*@__PURE__*/createReactComponent<JSX.IonCardContent, HTMLIonCardContentElement>('ion-card-content');
export const IonCardHeader = /*@__PURE__*/createReactComponent<JSX.IonCardHeader, HTMLIonCardHeaderElement>('ion-card-header');
export const IonCardSubtitle = /*@__PURE__*/createReactComponent<JSX.IonCardSubtitle, HTMLIonCardSubtitleElement>('ion-card-subtitle');
export const IonCardTitle = /*@__PURE__*/createReactComponent<JSX.IonCardTitle, HTMLIonCardTitleElement>('ion-card-title');
export const IonCheckbox = /*@__PURE__*/createReactComponent<JSX.IonCheckbox, HTMLIonCheckboxElement>('ion-checkbox');
export const IonChip = /*@__PURE__*/createReactComponent<JSX.IonChip, HTMLIonChipElement>('ion-chip');
export const IonCol = /*@__PURE__*/createReactComponent<JSX.IonCol, HTMLIonColElement>('ion-col');
export const IonContent = /*@__PURE__*/createReactComponent<JSX.IonContent, HTMLIonContentElement>('ion-content');
export const IonDatetime = /*@__PURE__*/createReactComponent<JSX.IonDatetime, HTMLIonDatetimeElement>('ion-datetime');
export const IonFab = /*@__PURE__*/createReactComponent<JSX.IonFab, HTMLIonFabElement>('ion-fab');
export const IonFabList = /*@__PURE__*/createReactComponent<JSX.IonFabList, HTMLIonFabListElement>('ion-fab-list');
export const IonFooter = /*@__PURE__*/createReactComponent<JSX.IonFooter, HTMLIonFooterElement>('ion-footer');
export const IonGrid = /*@__PURE__*/createReactComponent<JSX.IonGrid, HTMLIonGridElement>('ion-grid');
export const IonHeader = /*@__PURE__*/createReactComponent<JSX.IonHeader, HTMLIonHeaderElement>('ion-header');
export const IonImg = /*@__PURE__*/createReactComponent<JSX.IonImg, HTMLIonImgElement>('ion-img');
export const IonInfiniteScroll = /*@__PURE__*/createReactComponent<JSX.IonInfiniteScroll, HTMLIonInfiniteScrollElement>('ion-infinite-scroll');
export const IonInfiniteScrollContent = /*@__PURE__*/createReactComponent<JSX.IonInfiniteScrollContent, HTMLIonInfiniteScrollContentElement>('ion-infinite-scroll-content');
export const IonInput = /*@__PURE__*/createReactComponent<JSX.IonInput, HTMLIonInputElement>('ion-input');
export const IonItemDivider = /*@__PURE__*/createReactComponent<JSX.IonItemDivider, HTMLIonItemDividerElement>('ion-item-divider');
export const IonItemGroup = /*@__PURE__*/createReactComponent<JSX.IonItemGroup, HTMLIonItemGroupElement>('ion-item-group');
export const IonItemOptions = /*@__PURE__*/createReactComponent<JSX.IonItemOptions, HTMLIonItemOptionsElement>('ion-item-options');
export const IonItemSliding = /*@__PURE__*/createReactComponent<JSX.IonItemSliding, HTMLIonItemSlidingElement>('ion-item-sliding');
export const IonLabel = /*@__PURE__*/createReactComponent<JSX.IonLabel, HTMLIonLabelElement>('ion-label');
export const IonList = /*@__PURE__*/createReactComponent<JSX.IonList, HTMLIonListElement>('ion-list');
export const IonListHeader = /*@__PURE__*/createReactComponent<JSX.IonListHeader, HTMLIonListHeaderElement>('ion-list-header');
export const IonMenu = /*@__PURE__*/createReactComponent<JSX.IonMenu, HTMLIonMenuElement>('ion-menu');
export const IonMenuButton = /*@__PURE__*/createReactComponent<JSX.IonMenuButton, HTMLIonMenuButtonElement>('ion-menu-button');
export const IonMenuToggle = /*@__PURE__*/createReactComponent<JSX.IonMenuToggle, HTMLIonMenuToggleElement>('ion-menu-toggle');
export const IonNav = /*@__PURE__*/createReactComponent<JSX.IonNav, HTMLIonNavElement>('ion-nav');
export const IonNavLink = /*@__PURE__*/createReactComponent<JSX.IonNavLink, HTMLIonNavLinkElement>('ion-nav-link');
export const IonNote = /*@__PURE__*/createReactComponent<JSX.IonNote, HTMLIonNoteElement>('ion-note');
export const IonProgressBar = /*@__PURE__*/createReactComponent<JSX.IonProgressBar, HTMLIonProgressBarElement>('ion-progress-bar');
export const IonRadio = /*@__PURE__*/createReactComponent<JSX.IonRadio, HTMLIonRadioElement>('ion-radio');
export const IonRadioGroup = /*@__PURE__*/createReactComponent<JSX.IonRadioGroup, HTMLIonRadioGroupElement>('ion-radio-group');
export const IonRange = /*@__PURE__*/createReactComponent<JSX.IonRange, HTMLIonRangeElement>('ion-range');
export const IonRefresher = /*@__PURE__*/createReactComponent<JSX.IonRefresher, HTMLIonRefresherElement>('ion-refresher');
export const IonRefresherContent = /*@__PURE__*/createReactComponent<JSX.IonRefresherContent, HTMLIonRefresherContentElement>('ion-refresher-content');
export const IonReorder = /*@__PURE__*/createReactComponent<JSX.IonReorder, HTMLIonReorderElement>('ion-reorder');
export const IonReorderGroup = /*@__PURE__*/createReactComponent<JSX.IonReorderGroup, HTMLIonReorderGroupElement>('ion-reorder-group');
export const IonRippleEffect = /*@__PURE__*/createReactComponent<JSX.IonRippleEffect, HTMLIonRippleEffectElement>('ion-ripple-effect');
export const IonRow = /*@__PURE__*/createReactComponent<JSX.IonRow, HTMLIonRowElement>('ion-row');
export const IonSearchbar = /*@__PURE__*/createReactComponent<JSX.IonSearchbar, HTMLIonSearchbarElement>('ion-searchbar');
export const IonSegment = /*@__PURE__*/createReactComponent<JSX.IonSegment, HTMLIonSegmentElement>('ion-segment');
export const IonSegmentButton = /*@__PURE__*/createReactComponent<JSX.IonSegmentButton, HTMLIonSegmentButtonElement>('ion-segment-button');
export const IonSelect = /*@__PURE__*/createReactComponent<JSX.IonSelect, HTMLIonSelectElement>('ion-select');
export const IonSelectOption = /*@__PURE__*/createReactComponent<JSX.IonSelectOption, HTMLIonSelectOptionElement>('ion-select-option');
export const IonSkeletonText = /*@__PURE__*/createReactComponent<JSX.IonSkeletonText, HTMLIonSkeletonTextElement>('ion-skeleton-text');
export const IonSlide = /*@__PURE__*/createReactComponent<JSX.IonSlide, HTMLIonSlideElement>('ion-slide');
export const IonSlides = /*@__PURE__*/createReactComponent<JSX.IonSlides, HTMLIonSlidesElement>('ion-slides');
export const IonSpinner = /*@__PURE__*/createReactComponent<JSX.IonSpinner, HTMLIonSpinnerElement>('ion-spinner');
export const IonSplitPane = /*@__PURE__*/createReactComponent<JSX.IonSplitPane, HTMLIonSplitPaneElement>('ion-split-pane');
export const IonTab = /*@__PURE__*/createReactComponent<JSX.IonTab, HTMLIonTabElement>('ion-tab');
export const IonText = /*@__PURE__*/createReactComponent<JSX.IonText, HTMLIonTextElement>('ion-text');
export const IonTextarea = /*@__PURE__*/createReactComponent<JSX.IonTextarea, HTMLIonTextareaElement>('ion-textarea');
export const IonThumbnail = /*@__PURE__*/createReactComponent<JSX.IonThumbnail, HTMLIonThumbnailElement>('ion-thumbnail');
export const IonTitle = /*@__PURE__*/createReactComponent<JSX.IonTitle, HTMLIonTitleElement>('ion-title');
export const IonToggle = /*@__PURE__*/createReactComponent<JSX.IonToggle, HTMLIonToggleElement>('ion-toggle');
export const IonToolbar = /*@__PURE__*/createReactComponent<JSX.IonToolbar, HTMLIonToolbarElement>('ion-toolbar');
export const IonVirtualScroll = /*@__PURE__*/createReactComponent<JSX.IonVirtualScroll, HTMLIonVirtualScrollElement>('ion-virtual-scroll');
export const IonAccordion = /*@__PURE__*/createReactComponent<JSX.IonAccordion, HTMLIonAccordionElement>('ion-accordion', IonAccordionCmp);
export const IonAccordionGroup = /*@__PURE__*/createReactComponent<JSX.IonAccordionGroup, HTMLIonAccordionGroupElement>('ion-accordion-group', IonAccordionGroupCmp);
export const IonApp = /*@__PURE__*/createReactComponent<JSX.IonApp, HTMLIonAppElement>('ion-app', IonAppCmp);
export const IonAvatar = /*@__PURE__*/createReactComponent<JSX.IonAvatar, HTMLIonAvatarElement>('ion-avatar', IonAvatarCmp);
export const IonBackdrop = /*@__PURE__*/createReactComponent<JSX.IonBackdrop, HTMLIonBackdropElement>('ion-backdrop', IonBackdropCmp);
export const IonBadge = /*@__PURE__*/createReactComponent<JSX.IonBadge, HTMLIonBadgeElement>('ion-badge', IonBadgeCmp);
export const IonBreadcrumb = /*@__PURE__*/createReactComponent<JSX.IonBreadcrumb, HTMLIonBreadcrumbElement>('ion-breadcrumb', IonBreadcrumbCmp);
export const IonBreadcrumbs = /*@__PURE__*/createReactComponent<JSX.IonBreadcrumbs, HTMLIonBreadcrumbsElement>('ion-breadcrumbs', IonBreadcrumbsCmp);
export const IonButtons = /*@__PURE__*/createReactComponent<JSX.IonButtons, HTMLIonButtonsElement>('ion-buttons', IonButtonsCmp);
export const IonCardContent = /*@__PURE__*/createReactComponent<JSX.IonCardContent, HTMLIonCardContentElement>('ion-card-content', IonCardContentCmp);
export const IonCardHeader = /*@__PURE__*/createReactComponent<JSX.IonCardHeader, HTMLIonCardHeaderElement>('ion-card-header', IonCardHeaderCmp);
export const IonCardSubtitle = /*@__PURE__*/createReactComponent<JSX.IonCardSubtitle, HTMLIonCardSubtitleElement>('ion-card-subtitle', IonCardSubtitleCmp);
export const IonCardTitle = /*@__PURE__*/createReactComponent<JSX.IonCardTitle, HTMLIonCardTitleElement>('ion-card-title', IonCardTitleCmp);
export const IonCheckbox = /*@__PURE__*/createReactComponent<JSX.IonCheckbox, HTMLIonCheckboxElement>('ion-checkbox', IonCheckboxCmp);
export const IonChip = /*@__PURE__*/createReactComponent<JSX.IonChip, HTMLIonChipElement>('ion-chip', IonChipCmp);
export const IonCol = /*@__PURE__*/createReactComponent<JSX.IonCol, HTMLIonColElement>('ion-col', IonColCmp);
export const IonContent = /*@__PURE__*/createReactComponent<JSX.IonContent, HTMLIonContentElement>('ion-content', IonContentCmp);
export const IonDatetime = /*@__PURE__*/createReactComponent<JSX.IonDatetime, HTMLIonDatetimeElement>('ion-datetime', IonDatetimeCmp);
export const IonFab = /*@__PURE__*/createReactComponent<JSX.IonFab, HTMLIonFabElement>('ion-fab', IonFabCmp);
export const IonFabList = /*@__PURE__*/createReactComponent<JSX.IonFabList, HTMLIonFabListElement>('ion-fab-list', IonFabListCmp);
export const IonFooter = /*@__PURE__*/createReactComponent<JSX.IonFooter, HTMLIonFooterElement>('ion-footer', IonFooterCmp);
export const IonGrid = /*@__PURE__*/createReactComponent<JSX.IonGrid, HTMLIonGridElement>('ion-grid', IonGridCmp);
export const IonHeader = /*@__PURE__*/createReactComponent<JSX.IonHeader, HTMLIonHeaderElement>('ion-header', IonHeaderCmp);
export const IonImg = /*@__PURE__*/createReactComponent<JSX.IonImg, HTMLIonImgElement>('ion-img', IonImgCmp);
export const IonInfiniteScroll = /*@__PURE__*/createReactComponent<JSX.IonInfiniteScroll, HTMLIonInfiniteScrollElement>('ion-infinite-scroll', IonInfiniteScrollCmp);
export const IonInfiniteScrollContent = /*@__PURE__*/createReactComponent<JSX.IonInfiniteScrollContent, HTMLIonInfiniteScrollContentElement>('ion-infinite-scroll-content', IonInfiniteScrollContentCmp);
export const IonInput = /*@__PURE__*/createReactComponent<JSX.IonInput, HTMLIonInputElement>('ion-input', IonInputCmp);
export const IonItemDivider = /*@__PURE__*/createReactComponent<JSX.IonItemDivider, HTMLIonItemDividerElement>('ion-item-divider', IonItemDividerCmp);
export const IonItemGroup = /*@__PURE__*/createReactComponent<JSX.IonItemGroup, HTMLIonItemGroupElement>('ion-item-group', IonItemGroupCmp);
export const IonItemOptions = /*@__PURE__*/createReactComponent<JSX.IonItemOptions, HTMLIonItemOptionsElement>('ion-item-options', IonItemOptionsCmp);
export const IonItemSliding = /*@__PURE__*/createReactComponent<JSX.IonItemSliding, HTMLIonItemSlidingElement>('ion-item-sliding', IonItemSlidingCmp);
export const IonLabel = /*@__PURE__*/createReactComponent<JSX.IonLabel, HTMLIonLabelElement>('ion-label', IonLabelCmp);
export const IonList = /*@__PURE__*/createReactComponent<JSX.IonList, HTMLIonListElement>('ion-list', IonListCmp);
export const IonListHeader = /*@__PURE__*/createReactComponent<JSX.IonListHeader, HTMLIonListHeaderElement>('ion-list-header', IonListHeaderCmp);
export const IonMenu = /*@__PURE__*/createReactComponent<JSX.IonMenu, HTMLIonMenuElement>('ion-menu', IonMenuCmp);
export const IonMenuButton = /*@__PURE__*/createReactComponent<JSX.IonMenuButton, HTMLIonMenuButtonElement>('ion-menu-button', IonMenuButtonCmp);
export const IonMenuToggle = /*@__PURE__*/createReactComponent<JSX.IonMenuToggle, HTMLIonMenuToggleElement>('ion-menu-toggle', IonMenuToggleCmp);
export const IonNav = /*@__PURE__*/createReactComponent<JSX.IonNav, HTMLIonNavElement>('ion-nav', IonNavCmp);
export const IonNavLink = /*@__PURE__*/createReactComponent<JSX.IonNavLink, HTMLIonNavLinkElement>('ion-nav-link', IonNavLinkCmp);
export const IonNote = /*@__PURE__*/createReactComponent<JSX.IonNote, HTMLIonNoteElement>('ion-note', IonNoteCmp);
export const IonProgressBar = /*@__PURE__*/createReactComponent<JSX.IonProgressBar, HTMLIonProgressBarElement>('ion-progress-bar', IonProgressBarCmp);
export const IonRadio = /*@__PURE__*/createReactComponent<JSX.IonRadio, HTMLIonRadioElement>('ion-radio', IonRadioCmp);
export const IonRadioGroup = /*@__PURE__*/createReactComponent<JSX.IonRadioGroup, HTMLIonRadioGroupElement>('ion-radio-group', IonRadioGroupCmp);
export const IonRange = /*@__PURE__*/createReactComponent<JSX.IonRange, HTMLIonRangeElement>('ion-range', IonRangeCmp);
export const IonRefresher = /*@__PURE__*/createReactComponent<JSX.IonRefresher, HTMLIonRefresherElement>('ion-refresher', IonRefresherCmp);
export const IonRefresherContent = /*@__PURE__*/createReactComponent<JSX.IonRefresherContent, HTMLIonRefresherContentElement>('ion-refresher-content', IonRefresherContentCmp);
export const IonReorder = /*@__PURE__*/createReactComponent<JSX.IonReorder, HTMLIonReorderElement>('ion-reorder', IonReorderCmp);
export const IonReorderGroup = /*@__PURE__*/createReactComponent<JSX.IonReorderGroup, HTMLIonReorderGroupElement>('ion-reorder-group', IonReorderGroupCmp);
export const IonRippleEffect = /*@__PURE__*/createReactComponent<JSX.IonRippleEffect, HTMLIonRippleEffectElement>('ion-ripple-effect', IonRippleEffectCmp);
export const IonRow = /*@__PURE__*/createReactComponent<JSX.IonRow, HTMLIonRowElement>('ion-row', IonRowCmp);
export const IonSearchbar = /*@__PURE__*/createReactComponent<JSX.IonSearchbar, HTMLIonSearchbarElement>('ion-searchbar', IonSearchbarCmp);
export const IonSegment = /*@__PURE__*/createReactComponent<JSX.IonSegment, HTMLIonSegmentElement>('ion-segment', IonSegmentCmp);
export const IonSegmentButton = /*@__PURE__*/createReactComponent<JSX.IonSegmentButton, HTMLIonSegmentButtonElement>('ion-segment-button', IonSegmentButtonCmp);
export const IonSelect = /*@__PURE__*/createReactComponent<JSX.IonSelect, HTMLIonSelectElement>('ion-select', IonSelectCmp);
export const IonSelectOption = /*@__PURE__*/createReactComponent<JSX.IonSelectOption, HTMLIonSelectOptionElement>('ion-select-option', IonSelectOptionCmp);
export const IonSkeletonText = /*@__PURE__*/createReactComponent<JSX.IonSkeletonText, HTMLIonSkeletonTextElement>('ion-skeleton-text', IonSkeletonTextCmp);
export const IonSlide = /*@__PURE__*/createReactComponent<JSX.IonSlide, HTMLIonSlideElement>('ion-slide', IonSlideCmp);
export const IonSlides = /*@__PURE__*/createReactComponent<JSX.IonSlides, HTMLIonSlidesElement>('ion-slides', IonSlidesCmp);
export const IonSpinner = /*@__PURE__*/createReactComponent<JSX.IonSpinner, HTMLIonSpinnerElement>('ion-spinner', IonSpinnerCmp);
export const IonSplitPane = /*@__PURE__*/createReactComponent<JSX.IonSplitPane, HTMLIonSplitPaneElement>('ion-split-pane', IonSplitPaneCmp);
export const IonTab = /*@__PURE__*/createReactComponent<JSX.IonTab, HTMLIonTabElement>('ion-tab', IonTabCmp);
export const IonText = /*@__PURE__*/createReactComponent<JSX.IonText, HTMLIonTextElement>('ion-text', IonTextCmp);
export const IonTextarea = /*@__PURE__*/createReactComponent<JSX.IonTextarea, HTMLIonTextareaElement>('ion-textarea', IonTextareaCmp);
export const IonThumbnail = /*@__PURE__*/createReactComponent<JSX.IonThumbnail, HTMLIonThumbnailElement>('ion-thumbnail', IonThumbnailCmp);
export const IonTitle = /*@__PURE__*/createReactComponent<JSX.IonTitle, HTMLIonTitleElement>('ion-title', IonTitleCmp);
export const IonToggle = /*@__PURE__*/createReactComponent<JSX.IonToggle, HTMLIonToggleElement>('ion-toggle', IonToggleCmp);
export const IonToolbar = /*@__PURE__*/createReactComponent<JSX.IonToolbar, HTMLIonToolbarElement>('ion-toolbar', IonToolbarCmp);
export const IonVirtualScroll = /*@__PURE__*/createReactComponent<JSX.IonVirtualScroll, HTMLIonVirtualScrollElement>('ion-virtual-scroll', IonVirtualScrollCmp);

View File

@ -4,6 +4,7 @@ import {
attachProps,
createForwardRef,
dashToPascalCase,
defineCustomElement,
isCoveredByReact,
mergeRefs,
} from './utils';
@ -24,14 +25,16 @@ export const createReactComponent = <
ExpandedPropsTypes = {}
>(
tagName: string,
customElement?: any,
ReactComponentContext?: React.Context<ContextStateType>,
manipulatePropsFunction?: (
originalProps: StencilReactInternalProps<ElementType>,
propsToPass: any,
) => ExpandedPropsTypes,
) => {
const displayName = dashToPascalCase(tagName);
defineCustomElement(tagName, customElement);
const displayName = dashToPascalCase(tagName);
const ReactComponent = class extends React.Component<StencilReactInternalProps<ElementType>> {
componentEl!: ElementType;

View File

@ -2,7 +2,13 @@ import React from 'react';
import ReactDOM from 'react-dom';
import { OverlayEventDetail } from './interfaces';
import { StencilReactForwardedRef, attachProps, setRef } from './utils';
import {
StencilReactForwardedRef,
attachProps,
dashToPascalCase,
defineCustomElement,
setRef,
} from './utils';
interface OverlayElement extends HTMLElement {
present: () => Promise<void>;
@ -22,9 +28,13 @@ export const createOverlayComponent = <
OverlayComponent extends object,
OverlayType extends OverlayElement
>(
displayName: string,
controller: { create: (options: any) => Promise<OverlayType> }
tagName: string,
controller: { create: (options: any) => Promise<OverlayType> },
customElement?: any
) => {
defineCustomElement(tagName, customElement);
const displayName = dashToPascalCase(tagName);
const didDismissEventName = `on${displayName}DidDismiss`;
const didPresentEventName = `on${displayName}DidPresent`;
const willDismissEventName = `on${displayName}WillDismiss`;

View File

@ -43,5 +43,15 @@ export const createForwardRef = <PropType, ElementType>(
return React.forwardRef(forwardRef);
};
export const defineCustomElement = (tagName: string, customElement: any) => {
if (
customElement !== undefined &&
typeof customElements !== 'undefined' &&
!customElements.get(tagName)
) {
customElements.define(tagName, customElement);
}
}
export * from './attachProps';
export * from './case';

View File

@ -1,4 +1,10 @@
import type { JSX } from '@ionic/core';
import type { JSX } from '@ionic/core/components';
import { IonButton as IonButtonCmp } from '@ionic/core/components/ion-button.js';
import { IonCard as IonCardCmp } from '@ionic/core/components/ion-card.js';
import { IonFabButton as IonFabButtonCmp } from '@ionic/core/components/ion-fab-button.js';
import { IonItemOption as IonItemOptionCmp } from '@ionic/core/components/ion-item-option.js';
import { IonItem as IonItemCmp } from '@ionic/core/components/ion-item.js';
import { IonRouterLink as IonRouterLinkCmp } from '@ionic/core/components/ion-router-link.js';
import { createRoutingComponent } from './createRoutingComponent';
import { HrefProps } from './hrefprops';
@ -6,29 +12,29 @@ import { HrefProps } from './hrefprops';
export const IonRouterLink = /*@__PURE__*/ createRoutingComponent<
HrefProps<JSX.IonRouterLink>,
HTMLIonRouterLinkElement
>('ion-router-link');
>('ion-router-link', IonRouterLinkCmp);
export const IonButton = /*@__PURE__*/ createRoutingComponent<
HrefProps<JSX.IonButton>,
HTMLIonButtonElement
>('ion-button');
>('ion-button', IonButtonCmp);
export const IonCard = /*@__PURE__*/ createRoutingComponent<
HrefProps<JSX.IonCard>,
HTMLIonCardElement
>('ion-card');
>('ion-card', IonCardCmp);
export const IonFabButton = /*@__PURE__*/ createRoutingComponent<
HrefProps<JSX.IonFabButton>,
HTMLIonFabButtonElement
>('ion-fab-button');
>('ion-fab-button', IonFabButtonCmp);
export const IonItem = /*@__PURE__*/ createRoutingComponent<
HrefProps<JSX.IonItem>,
HTMLIonItemElement
>('ion-item');
>('ion-item', IonItemCmp);
export const IonItemOption = /*@__PURE__*/ createRoutingComponent<
HrefProps<JSX.IonItemOption>,
HTMLIonItemOptionElement
>('ion-item-option');
>('ion-item-option', IonItemOptionCmp);

View File

@ -3,7 +3,7 @@ import {
Platforms,
getPlatforms as getPlatformsCore,
isPlatform as isPlatformCore,
} from '@ionic/core';
} from '@ionic/core/components';
import React from 'react';
import { IonicReactProps } from '../IonicReactProps';

View File

@ -1,4 +1,4 @@
import { AnimationBuilder, RouterDirection } from '@ionic/core';
import { AnimationBuilder, RouterDirection } from '@ionic/core/components';
import React from 'react';
import { RouteInfo } from '../models';

View File

@ -1,4 +1,4 @@
import { OverlayEventDetail } from '@ionic/core';
import { OverlayEventDetail } from '@ionic/core/components';
export interface HookOverlayOptions {
onDidDismiss?: (event: CustomEvent<OverlayEventDetail>) => void;

View File

@ -1,4 +1,4 @@
import { OverlayEventDetail } from '@ionic/core';
import { OverlayEventDetail } from '@ionic/core/components';
import { useMemo, useRef } from 'react';
import { attachProps } from '../components/react-component-lib/utils';

View File

@ -1,4 +1,4 @@
import { ActionSheetButton, ActionSheetOptions, actionSheetController } from '@ionic/core';
import { ActionSheetButton, ActionSheetOptions, actionSheetController } from '@ionic/core/components';
import { HookOverlayOptions } from './HookOverlayOptions';
import { useController } from './useController';

View File

@ -1,4 +1,4 @@
import { AlertButton, AlertOptions, alertController } from '@ionic/core';
import { AlertButton, AlertOptions, alertController } from '@ionic/core/components';
import { HookOverlayOptions } from './HookOverlayOptions';
import { useController } from './useController';

View File

@ -1,4 +1,4 @@
import { LoadingOptions, SpinnerTypes, loadingController } from '@ionic/core';
import { LoadingOptions, SpinnerTypes, loadingController } from '@ionic/core/components';
import { HookOverlayOptions } from './HookOverlayOptions';
import { useController } from './useController';

View File

@ -1,4 +1,4 @@
import { ModalOptions, modalController } from '@ionic/core';
import { ModalOptions, modalController } from '@ionic/core/components';
import { HookOverlayOptions } from './HookOverlayOptions';
import { ReactComponentOrElement, useOverlay } from './useOverlay';

View File

@ -3,7 +3,7 @@ import {
PickerColumn,
PickerOptions,
pickerController,
} from '@ionic/core';
} from '@ionic/core/components';
import { HookOverlayOptions } from './HookOverlayOptions';
import { useController } from './useController';

View File

@ -1,4 +1,4 @@
import { PopoverOptions, popoverController } from '@ionic/core';
import { PopoverOptions, popoverController } from '@ionic/core/components';
import { HookOverlayOptions } from './HookOverlayOptions';
import { ReactComponentOrElement, useOverlay } from './useOverlay';

View File

@ -1,4 +1,4 @@
import { ToastOptions, toastController } from '@ionic/core';
import { ToastOptions, toastController } from '@ionic/core/components';
import { HookOverlayOptions } from './HookOverlayOptions';
import { useController } from './useController';

View File

@ -1,4 +1,4 @@
import { OverlayEventDetail } from '@ionic/core';
import { OverlayEventDetail } from '@ionic/core/components';
import React, { useEffect, useMemo, useRef, useState } from 'react';
import ReactDOM from 'react-dom';

View File

@ -1,4 +1,4 @@
import { AnimationBuilder } from '@ionic/core';
import { AnimationBuilder } from '@ionic/core/components';
import { RouteAction } from './RouteAction';
import { RouterDirection } from './RouterDirection';

View File

@ -1,4 +1,4 @@
import { AnimationBuilder } from '@ionic/core';
import { AnimationBuilder } from '@ionic/core/components';
import React from 'react';
import { IonRouterContext, IonRouterContextState } from '../components/IonRouterContext';