mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2025-08-19 19:57:22 +08:00
merge release-6.1.14
Release 6.1.14
This commit is contained in:
@ -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.
|
||||
|
||||
## [6.1.14](https://github.com/ionic-team/ionic/compare/v6.1.13...v6.1.14) (2022-07-13)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **react:** IonNav works with react ([#25565](https://github.com/ionic-team/ionic/issues/25565)) ([420f9bb](https://github.com/ionic-team/ionic/commit/420f9bbebd41f3eab6def795bcdd1933d5c5a47a)), closes [#24002](https://github.com/ionic-team/ionic/issues/24002)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [6.1.13](https://github.com/ionic-team/ionic/compare/v6.1.12...v6.1.13) (2022-07-06)
|
||||
|
||||
**Note:** Version bump only for package @ionic/react
|
||||
|
18
packages/react/package-lock.json
generated
18
packages/react/package-lock.json
generated
@ -1,15 +1,15 @@
|
||||
{
|
||||
"name": "@ionic/react",
|
||||
"version": "6.1.13",
|
||||
"version": "6.1.14",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "@ionic/react",
|
||||
"version": "6.1.13",
|
||||
"version": "6.1.14",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@ionic/core": "^6.1.13",
|
||||
"@ionic/core": "^6.1.14",
|
||||
"ionicons": "^6.0.2",
|
||||
"tslib": "*"
|
||||
},
|
||||
@ -607,9 +607,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@ionic/core": {
|
||||
"version": "6.1.13",
|
||||
"resolved": "https://registry.npmjs.org/@ionic/core/-/core-6.1.13.tgz",
|
||||
"integrity": "sha512-CZ5P1El/bk6ZDKqey/67/ZgpUhVQTr+WyhGxFTnPCsIWg+VfOogQ7rHCkEqWfXJqdzNPsvtH5/Lck4qoD0nCkg==",
|
||||
"version": "6.1.14",
|
||||
"resolved": "https://registry.npmjs.org/@ionic/core/-/core-6.1.14.tgz",
|
||||
"integrity": "sha512-tmhumOD7VM7QV3boh8rwMNYOgqBskOtGJPSEaySEmCUy+Y0nXwb0gBqxZ/M6c0JcGwT17gIB2KiQDvZ4O/J8iA==",
|
||||
"dependencies": {
|
||||
"@stencil/core": "^2.16.0",
|
||||
"ionicons": "^6.0.2",
|
||||
@ -9522,9 +9522,9 @@
|
||||
}
|
||||
},
|
||||
"@ionic/core": {
|
||||
"version": "6.1.13",
|
||||
"resolved": "https://registry.npmjs.org/@ionic/core/-/core-6.1.13.tgz",
|
||||
"integrity": "sha512-CZ5P1El/bk6ZDKqey/67/ZgpUhVQTr+WyhGxFTnPCsIWg+VfOogQ7rHCkEqWfXJqdzNPsvtH5/Lck4qoD0nCkg==",
|
||||
"version": "6.1.14",
|
||||
"resolved": "https://registry.npmjs.org/@ionic/core/-/core-6.1.14.tgz",
|
||||
"integrity": "sha512-tmhumOD7VM7QV3boh8rwMNYOgqBskOtGJPSEaySEmCUy+Y0nXwb0gBqxZ/M6c0JcGwT17gIB2KiQDvZ4O/J8iA==",
|
||||
"requires": {
|
||||
"@stencil/core": "^2.16.0",
|
||||
"ionicons": "^6.0.2",
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@ionic/react",
|
||||
"version": "6.1.13",
|
||||
"version": "6.1.14",
|
||||
"description": "React specific wrapper for @ionic/core",
|
||||
"keywords": [
|
||||
"ionic",
|
||||
@ -41,7 +41,7 @@
|
||||
"css/"
|
||||
],
|
||||
"dependencies": {
|
||||
"@ionic/core": "^6.1.13",
|
||||
"@ionic/core": "^6.1.14",
|
||||
"ionicons": "^6.0.2",
|
||||
"tslib": "*"
|
||||
},
|
||||
|
@ -132,6 +132,7 @@ export { IonPopover } from './IonPopover';
|
||||
// Custom Components
|
||||
export { IonApp } from './IonApp';
|
||||
export { IonPage } from './IonPage';
|
||||
export { IonNav } from './navigation/IonNav';
|
||||
export { IonTabsContext, IonTabsContextState } from './navigation/IonTabsContext';
|
||||
export { IonTabs } from './navigation/IonTabs';
|
||||
export { IonTabBar } from './navigation/IonTabBar';
|
||||
|
@ -21,7 +21,15 @@ export const IonBackButton = /*@__PURE__*/ (() =>
|
||||
context!: React.ContextType<typeof NavContext>;
|
||||
|
||||
clickButton = (e: React.MouseEvent) => {
|
||||
/**
|
||||
* If ion-back-button is being used inside
|
||||
* of ion-nav then we should not interact with
|
||||
* the router.
|
||||
*/
|
||||
if (e.target && (e.target as HTMLElement).closest('ion-nav') !== null) { return; }
|
||||
|
||||
const { defaultHref, routerAnimation } = this.props;
|
||||
|
||||
if (this.context.hasIonicRouter()) {
|
||||
e.stopPropagation();
|
||||
this.context.goBack(defaultHref, routerAnimation);
|
||||
|
30
packages/react/src/components/navigation/IonNav.tsx
Normal file
30
packages/react/src/components/navigation/IonNav.tsx
Normal file
@ -0,0 +1,30 @@
|
||||
import type { FrameworkDelegate, JSX } from '@ionic/core/components';
|
||||
import { defineCustomElement } from '@ionic/core/components/ion-nav.js';
|
||||
import React, { useState } from 'react';
|
||||
|
||||
import { ReactDelegate } from '../../framework-delegate';
|
||||
import { createReactComponent } from '../react-component-lib';
|
||||
|
||||
const IonNavInner = createReactComponent<
|
||||
JSX.IonNav & { delegate: FrameworkDelegate },
|
||||
HTMLIonNavElement
|
||||
>('ion-nav', undefined, undefined, defineCustomElement);
|
||||
|
||||
export const IonNav: React.FC<JSX.IonNav> = ({ children, ...restOfProps }) => {
|
||||
const [views, setViews] = useState<React.ReactPortal[]>([]);
|
||||
|
||||
/**
|
||||
* Allows us to create React components that are rendered within
|
||||
* the context of the IonNav component.
|
||||
*/
|
||||
const addView = (view: React.ReactPortal) => setViews([...views, view]);
|
||||
const removeView = (view: React.ReactPortal) => setViews(views.filter((v) => v !== view));
|
||||
|
||||
const delegate = ReactDelegate(addView, removeView);
|
||||
|
||||
return (
|
||||
<IonNavInner delegate={delegate} {...restOfProps}>
|
||||
{views}
|
||||
</IonNavInner>
|
||||
);
|
||||
};
|
38
packages/react/src/framework-delegate.tsx
Normal file
38
packages/react/src/framework-delegate.tsx
Normal file
@ -0,0 +1,38 @@
|
||||
import { FrameworkDelegate } from '@ionic/core/components';
|
||||
import { createPortal } from 'react-dom';
|
||||
|
||||
export const ReactDelegate = (
|
||||
addView: (view: React.ReactPortal) => void,
|
||||
removeView: (view: React.ReactPortal) => void
|
||||
): FrameworkDelegate => {
|
||||
let Component: React.ReactPortal;
|
||||
|
||||
const attachViewToDom = async (
|
||||
parentElement: HTMLElement,
|
||||
component: () => JSX.Element,
|
||||
propsOrDataObj?: any,
|
||||
cssClasses?: string[]
|
||||
): Promise<any> => {
|
||||
const div = document.createElement('div');
|
||||
cssClasses && div.classList.add(...cssClasses);
|
||||
parentElement.appendChild(div);
|
||||
|
||||
Component = createPortal(component(), div);
|
||||
|
||||
Component.props = propsOrDataObj;
|
||||
|
||||
addView(Component);
|
||||
|
||||
return Promise.resolve(div);
|
||||
};
|
||||
|
||||
const removeViewFromDom = (): Promise<void> => {
|
||||
Component && removeView(Component);
|
||||
return Promise.resolve();
|
||||
};
|
||||
|
||||
return {
|
||||
attachViewToDom,
|
||||
removeViewFromDom,
|
||||
};
|
||||
};
|
@ -0,0 +1,28 @@
|
||||
describe('IonNav', () => {
|
||||
beforeEach(() => {
|
||||
cy.visit('/navigation');
|
||||
});
|
||||
|
||||
it('should render the root page', () => {
|
||||
cy.get('ion-nav').contains('Page one content');
|
||||
});
|
||||
|
||||
it('should push a page', () => {
|
||||
cy.get('ion-button').contains('Go to Page Two').click();
|
||||
cy.get('#pageTwoContent').should('be.visible');
|
||||
cy.get('ion-nav').contains('Page two content');
|
||||
});
|
||||
|
||||
it('should pop a page', () => {
|
||||
cy.get('ion-button').contains('Go to Page Two').click();
|
||||
|
||||
cy.get('#pageTwoContent').should('be.visible');
|
||||
cy.get('ion-nav').contains('Page two content');
|
||||
|
||||
cy.get('.ion-page.can-go-back ion-back-button').click();
|
||||
|
||||
cy.get('#pageOneContent').should('be.visible');
|
||||
cy.get('ion-nav').contains('Page one content');
|
||||
});
|
||||
|
||||
});
|
@ -25,6 +25,7 @@ import Main from './pages/Main';
|
||||
import OverlayHooks from './pages/overlay-hooks/OverlayHooks';
|
||||
import OverlayComponents from './pages/overlay-components/OverlayComponents';
|
||||
import Tabs from './pages/Tabs';
|
||||
import NavComponent from './pages/navigation/NavComponent';
|
||||
|
||||
setupIonicReact();
|
||||
|
||||
@ -35,6 +36,7 @@ const App: React.FC = () => (
|
||||
<Route path="/" component={Main} />
|
||||
<Route path="/overlay-hooks" component={OverlayHooks} />
|
||||
<Route path="/overlay-components" component={OverlayComponents} />
|
||||
<Route path="/navigation" component={NavComponent} />
|
||||
<Route path="/tabs" component={Tabs} />
|
||||
</IonRouterOutlet>
|
||||
</IonReactRouter>
|
||||
|
@ -31,6 +31,11 @@ const Main: React.FC<MainProps> = () => {
|
||||
<IonLabel>Overlay Components</IonLabel>
|
||||
</IonItem>
|
||||
</IonList>
|
||||
<IonList>
|
||||
<IonItem routerLink="/navigation">
|
||||
<IonLabel>Navigation</IonLabel>
|
||||
</IonItem>
|
||||
</IonList>
|
||||
<IonList>
|
||||
<IonItem routerLink="/tabs">
|
||||
<IonLabel>Tabs</IonLabel>
|
||||
|
@ -0,0 +1,84 @@
|
||||
import {
|
||||
IonButton,
|
||||
IonContent,
|
||||
IonHeader,
|
||||
IonLabel,
|
||||
IonNav,
|
||||
IonNavLink,
|
||||
IonTitle,
|
||||
IonToolbar,
|
||||
IonButtons,
|
||||
IonBackButton,
|
||||
IonPage,
|
||||
} from '@ionic/react';
|
||||
import React from 'react';
|
||||
|
||||
const NavComponent: React.FC = () => {
|
||||
return (
|
||||
<IonPage>
|
||||
<IonNav
|
||||
root={() => {
|
||||
return (
|
||||
<>
|
||||
<IonHeader>
|
||||
<IonToolbar>
|
||||
<IonTitle>Page One</IonTitle>
|
||||
<IonButtons>
|
||||
<IonBackButton />
|
||||
</IonButtons>
|
||||
</IonToolbar>
|
||||
</IonHeader>
|
||||
<IonContent id="pageOneContent">
|
||||
<IonLabel>Page one content</IonLabel>
|
||||
<IonNavLink
|
||||
routerDirection="forward"
|
||||
component={() => {
|
||||
return (
|
||||
<>
|
||||
<IonHeader>
|
||||
<IonToolbar>
|
||||
<IonTitle>Page Two</IonTitle>
|
||||
<IonButtons>
|
||||
<IonBackButton />
|
||||
</IonButtons>
|
||||
</IonToolbar>
|
||||
</IonHeader>
|
||||
<IonContent id="pageTwoContent">
|
||||
<IonLabel>Page two content</IonLabel>
|
||||
<IonNavLink
|
||||
routerDirection="forward"
|
||||
component={() => (
|
||||
<>
|
||||
<IonHeader>
|
||||
<IonToolbar>
|
||||
<IonTitle>Page Three</IonTitle>
|
||||
<IonButtons>
|
||||
<IonBackButton />
|
||||
</IonButtons>
|
||||
</IonToolbar>
|
||||
</IonHeader>
|
||||
<IonContent>
|
||||
<IonLabel>Page three content</IonLabel>
|
||||
</IonContent>
|
||||
</>
|
||||
)}
|
||||
>
|
||||
<IonButton>Go to Page Three</IonButton>
|
||||
</IonNavLink>
|
||||
</IonContent>
|
||||
</>
|
||||
);
|
||||
}}
|
||||
>
|
||||
<IonButton>Go to Page Two</IonButton>
|
||||
</IonNavLink>
|
||||
</IonContent>
|
||||
</>
|
||||
);
|
||||
}}
|
||||
></IonNav>
|
||||
</IonPage>
|
||||
);
|
||||
};
|
||||
|
||||
export default NavComponent;
|
@ -49,7 +49,7 @@ const ModalHook: React.FC = () => {
|
||||
setCount(count + 1);
|
||||
}, [count, setCount]);
|
||||
|
||||
const handleDismissWithComponent = useCallback((data, role) => {
|
||||
const handleDismissWithComponent = useCallback((data: any, role: string) => {
|
||||
dismissWithComponent(data, role);
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, []);
|
||||
|
Reference in New Issue
Block a user