mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2025-08-14 16:52:26 +08:00
fix(react): resolve errors with JSX and types
This commit is contained in:
@ -1,5 +1,5 @@
|
||||
import type { JSX as LocalJSX } from '@ionic/core/components';
|
||||
import React from 'react';
|
||||
import React, { type PropsWithChildren } from 'react';
|
||||
|
||||
import type { IonContextInterface } from '../contexts/IonContext';
|
||||
import { IonContext } from '../contexts/IonContext';
|
||||
@ -9,53 +9,46 @@ import { IonOverlayManager } from './IonOverlayManager';
|
||||
import type { IonicReactProps } from './IonicReactProps';
|
||||
import { IonAppInner } from './inner-proxies';
|
||||
|
||||
type Props = LocalJSX.IonApp &
|
||||
IonicReactProps & {
|
||||
ref?: React.Ref<HTMLIonAppElement>;
|
||||
type Props = PropsWithChildren<LocalJSX.IonApp & IonicReactProps & {
|
||||
ref?: React.Ref<HTMLIonAppElement>;
|
||||
}>;
|
||||
|
||||
export class IonApp extends React.Component<Props> {
|
||||
addOverlayCallback?: (id: string, overlay: ReactComponentOrElement, containerElement: HTMLDivElement) => void;
|
||||
removeOverlayCallback?: (id: string) => void;
|
||||
|
||||
constructor(props: Props) {
|
||||
super(props);
|
||||
}
|
||||
|
||||
ionContext: IonContextInterface = {
|
||||
addOverlay: (id: string, overlay: ReactComponentOrElement, containerElement: HTMLDivElement) => {
|
||||
if (this.addOverlayCallback) {
|
||||
this.addOverlayCallback(id, overlay, containerElement);
|
||||
}
|
||||
},
|
||||
removeOverlay: (id: string) => {
|
||||
if (this.removeOverlayCallback) {
|
||||
this.removeOverlayCallback(id);
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
export const IonApp = /*@__PURE__*/ (() =>
|
||||
class extends React.Component<Props> {
|
||||
addOverlayCallback?: (id: string, overlay: ReactComponentOrElement, containerElement: HTMLDivElement) => void;
|
||||
removeOverlayCallback?: (id: string) => void;
|
||||
render() {
|
||||
return (
|
||||
<IonContext.Provider value={this.ionContext}>
|
||||
<IonAppInner {...this.props}>{this.props.children}</IonAppInner>
|
||||
<IonOverlayManager
|
||||
onAddOverlay={(callback) => {
|
||||
this.addOverlayCallback = callback;
|
||||
}}
|
||||
onRemoveOverlay={(callback) => {
|
||||
this.removeOverlayCallback = callback;
|
||||
}}
|
||||
/>
|
||||
</IonContext.Provider>
|
||||
);
|
||||
}
|
||||
|
||||
constructor(props: Props) {
|
||||
super(props);
|
||||
}
|
||||
|
||||
/*
|
||||
Wire up methods to call into IonOverlayManager
|
||||
*/
|
||||
ionContext: IonContextInterface = {
|
||||
addOverlay: (id: string, overlay: ReactComponentOrElement, containerElement: HTMLDivElement) => {
|
||||
if (this.addOverlayCallback) {
|
||||
this.addOverlayCallback(id, overlay, containerElement);
|
||||
}
|
||||
},
|
||||
removeOverlay: (id: string) => {
|
||||
if (this.removeOverlayCallback) {
|
||||
this.removeOverlayCallback(id);
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
render() {
|
||||
return (
|
||||
<IonContext.Provider value={this.ionContext}>
|
||||
<IonAppInner {...this.props}>{this.props.children}</IonAppInner>
|
||||
<IonOverlayManager
|
||||
onAddOverlay={(callback) => {
|
||||
this.addOverlayCallback = callback;
|
||||
}}
|
||||
onRemoveOverlay={(callback) => {
|
||||
this.removeOverlayCallback = callback;
|
||||
}}
|
||||
/>
|
||||
</IonContext.Provider>
|
||||
);
|
||||
}
|
||||
|
||||
static get displayName() {
|
||||
return 'IonApp';
|
||||
}
|
||||
})();
|
||||
static displayName = 'IonApp';
|
||||
}
|
||||
|
@ -1,54 +1,50 @@
|
||||
import type { JSX as LocalJSX } from '@ionic/core/components';
|
||||
import React from 'react';
|
||||
import React, { type PropsWithChildren } from 'react';
|
||||
|
||||
import { NavContext } from '../../contexts/NavContext';
|
||||
import type { IonicReactProps } from '../IonicReactProps';
|
||||
import { IonBackButtonInner } from '../inner-proxies';
|
||||
|
||||
type Props = Omit<LocalJSX.IonBackButton, 'icon'> &
|
||||
IonicReactProps & {
|
||||
icon?:
|
||||
| {
|
||||
ios: string;
|
||||
md: string;
|
||||
}
|
||||
| string;
|
||||
ref?: React.Ref<HTMLIonBackButtonElement>;
|
||||
type Props = PropsWithChildren<LocalJSX.IonBackButton & IonicReactProps & {
|
||||
ref?: React.Ref<HTMLIonBackButtonElement>;
|
||||
}>;
|
||||
|
||||
export class IonBackButton extends React.Component<Props> {
|
||||
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);
|
||||
} else if (defaultHref !== undefined) {
|
||||
window.location.href = defaultHref;
|
||||
}
|
||||
};
|
||||
|
||||
export const IonBackButton = /*@__PURE__*/ (() =>
|
||||
class extends React.Component<Props> {
|
||||
context!: React.ContextType<typeof NavContext>;
|
||||
render() {
|
||||
return <IonBackButtonInner onClick={this.clickButton} {...this.props}></IonBackButtonInner>;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
static get displayName() {
|
||||
return 'IonBackButton';
|
||||
}
|
||||
|
||||
const { defaultHref, routerAnimation } = this.props;
|
||||
static get contextType() {
|
||||
return NavContext;
|
||||
}
|
||||
|
||||
if (this.context.hasIonicRouter()) {
|
||||
e.stopPropagation();
|
||||
this.context.goBack(defaultHref, routerAnimation);
|
||||
} else if (defaultHref !== undefined) {
|
||||
window.location.href = defaultHref;
|
||||
}
|
||||
};
|
||||
|
||||
render() {
|
||||
return <IonBackButtonInner onClick={this.clickButton} {...this.props}></IonBackButtonInner>;
|
||||
}
|
||||
|
||||
static get displayName() {
|
||||
return 'IonBackButton';
|
||||
}
|
||||
|
||||
static get contextType() {
|
||||
return NavContext;
|
||||
}
|
||||
})();
|
||||
shouldComponentUpdate(_nextProps: Readonly<Props>): boolean {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -13,41 +13,45 @@ type Props = LocalJSX.IonTabButton &
|
||||
onPointerDown?: React.PointerEventHandler<HTMLIonTabButtonElement>;
|
||||
onTouchEnd?: React.TouchEventHandler<HTMLIonTabButtonElement>;
|
||||
onTouchMove?: React.TouchEventHandler<HTMLIonTabButtonElement>;
|
||||
children?: React.ReactNode;
|
||||
};
|
||||
|
||||
export const IonTabButton = /*@__PURE__*/ (() =>
|
||||
class extends React.Component<Props> {
|
||||
constructor(props: Props) {
|
||||
super(props);
|
||||
this.handleIonTabButtonClick = this.handleIonTabButtonClick.bind(this);
|
||||
}
|
||||
export class IonTabButton extends React.Component<Props> {
|
||||
shouldComponentUpdate(_nextProps: Readonly<Props>, _nextState: Readonly<{}>): boolean {
|
||||
return true;
|
||||
}
|
||||
|
||||
handleIonTabButtonClick() {
|
||||
if (this.props.onClick) {
|
||||
this.props.onClick(
|
||||
new CustomEvent('ionTabButtonClick', {
|
||||
detail: {
|
||||
tab: this.props.tab,
|
||||
href: this.props.href,
|
||||
routeOptions: this.props.routerOptions,
|
||||
},
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
||||
constructor(props: Props) {
|
||||
super(props);
|
||||
this.handleIonTabButtonClick = this.handleIonTabButtonClick.bind(this);
|
||||
}
|
||||
|
||||
render() {
|
||||
/**
|
||||
* onClick is excluded from the props, since it has a custom
|
||||
* implementation within IonTabBar.tsx. Calling onClick within this
|
||||
* component would result in duplicate handler calls.
|
||||
*/
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
const { onClick, ...rest } = this.props;
|
||||
return <IonTabButtonInner onIonTabButtonClick={this.handleIonTabButtonClick} {...rest}></IonTabButtonInner>;
|
||||
handleIonTabButtonClick() {
|
||||
if (this.props.onClick) {
|
||||
this.props.onClick(
|
||||
new CustomEvent('ionTabButtonClick', {
|
||||
detail: {
|
||||
tab: this.props.tab,
|
||||
href: this.props.href,
|
||||
routeOptions: this.props.routerOptions,
|
||||
},
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
static get displayName() {
|
||||
return 'IonTabButton';
|
||||
}
|
||||
})();
|
||||
render() {
|
||||
/**
|
||||
* onClick is excluded from the props, since it has a custom
|
||||
* implementation within IonTabBar.tsx. Calling onClick within this
|
||||
* component would result in duplicate handler calls.
|
||||
*/
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
const { onClick, ...rest } = this.props;
|
||||
return <IonTabButtonInner onIonTabButtonClick={this.handleIonTabButtonClick} {...rest}></IonTabButtonInner>;
|
||||
}
|
||||
|
||||
static get displayName() {
|
||||
return 'IonTabButton';
|
||||
}
|
||||
}
|
||||
|
@ -1,3 +1,4 @@
|
||||
import type { Components } from '@ionic/core';
|
||||
import type { JSX as LocalJSX } from '@ionic/core/components';
|
||||
import React, { Fragment } from 'react';
|
||||
|
||||
@ -26,12 +27,14 @@ if (typeof (window as any) !== 'undefined' && window.customElements) {
|
||||
}
|
||||
}
|
||||
|
||||
declare global {
|
||||
// eslint-disable-next-line @typescript-eslint/no-namespace
|
||||
namespace JSX {
|
||||
interface IntrinsicElements {
|
||||
'ion-tabs': any;
|
||||
}
|
||||
export interface IonTabsProps extends React.HTMLAttributes<Components.IonTabs> {
|
||||
onIonTabsWillChange?: (event: CustomEvent<{ tab: string }>) => void;
|
||||
onIonTabsDidChange?: (event: CustomEvent<{ tab: string }>) => void;
|
||||
}
|
||||
|
||||
declare module 'react' {
|
||||
interface HTMLElements {
|
||||
'ion-tabs': IonTabsProps;
|
||||
}
|
||||
}
|
||||
|
||||
@ -40,169 +43,174 @@ type ChildFunction = (ionTabContext: IonTabsContextState) => React.ReactNode;
|
||||
interface Props extends LocalJSX.IonTabs {
|
||||
className?: string;
|
||||
children: ChildFunction | React.ReactNode;
|
||||
onIonTabsWillChange?: (event: CustomEvent<{ tab: string }>) => void;
|
||||
onIonTabsDidChange?: (event: CustomEvent<{ tab: string }>) => void;
|
||||
}
|
||||
|
||||
export const IonTabs = /*@__PURE__*/ (() =>
|
||||
class extends React.Component<Props> {
|
||||
context!: React.ContextType<typeof NavContext>;
|
||||
export class IonTabs extends React.Component<Props> {
|
||||
shouldComponentUpdate(_nextProps: Readonly<Props>, _nextState: Readonly<{}>): boolean {
|
||||
return true;
|
||||
}
|
||||
|
||||
context!: React.ContextType<typeof NavContext>;
|
||||
/**
|
||||
* `routerOutletRef` allows users to add a `ref` to `IonRouterOutlet`.
|
||||
* Without this, `ref.current` will be `undefined` in the user's app,
|
||||
* breaking their ability to access the `IonRouterOutlet` instance.
|
||||
* Do not remove this ref.
|
||||
*/
|
||||
routerOutletRef: React.Ref<Components.IonRouterOutlet> = React.createRef();
|
||||
selectTabHandler?: (tag: string) => boolean;
|
||||
tabBarRef = React.createRef<any>();
|
||||
|
||||
ionTabContextState: IonTabsContextState = {
|
||||
activeTab: undefined,
|
||||
selectTab: () => false,
|
||||
hasRouterOutlet: false,
|
||||
/**
|
||||
* `routerOutletRef` allows users to add a `ref` to `IonRouterOutlet`.
|
||||
* Without this, `ref.current` will be `undefined` in the user's app,
|
||||
* breaking their ability to access the `IonRouterOutlet` instance.
|
||||
* Do not remove this ref.
|
||||
* Tab bar can be used as a standalone component,
|
||||
* so the props can not be passed directly to the
|
||||
* tab bar component. Instead, props will be
|
||||
* passed through the context.
|
||||
*/
|
||||
routerOutletRef: React.Ref<HTMLIonRouterOutletElement> = React.createRef();
|
||||
selectTabHandler?: (tag: string) => boolean;
|
||||
tabBarRef = React.createRef<any>();
|
||||
tabBarProps: { ref: this.tabBarRef },
|
||||
};
|
||||
|
||||
ionTabContextState: IonTabsContextState = {
|
||||
activeTab: undefined,
|
||||
selectTab: () => false,
|
||||
hasRouterOutlet: false,
|
||||
/**
|
||||
* Tab bar can be used as a standalone component,
|
||||
* so the props can not be passed directly to the
|
||||
* tab bar component. Instead, props will be
|
||||
* passed through the context.
|
||||
*/
|
||||
tabBarProps: { ref: this.tabBarRef },
|
||||
};
|
||||
constructor(props: Props) {
|
||||
super(props);
|
||||
}
|
||||
|
||||
constructor(props: Props) {
|
||||
super(props);
|
||||
componentDidMount() {
|
||||
if (this.tabBarRef.current) {
|
||||
// Grab initial value
|
||||
this.ionTabContextState.activeTab = this.tabBarRef.current.state.activeTab;
|
||||
// Override method
|
||||
this.tabBarRef.current.setActiveTabOnContext = (tab: string) => {
|
||||
this.ionTabContextState.activeTab = tab;
|
||||
};
|
||||
this.ionTabContextState.selectTab = this.tabBarRef.current.selectTab;
|
||||
}
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
if (this.tabBarRef.current) {
|
||||
// Grab initial value
|
||||
this.ionTabContextState.activeTab = this.tabBarRef.current.state.activeTab;
|
||||
// Override method
|
||||
this.tabBarRef.current.setActiveTabOnContext = (tab: string) => {
|
||||
this.ionTabContextState.activeTab = tab;
|
||||
};
|
||||
this.ionTabContextState.selectTab = this.tabBarRef.current.selectTab;
|
||||
}
|
||||
}
|
||||
renderTabsInner(children: React.ReactNode, outlet: React.ReactElement<{}> | undefined) {
|
||||
return (
|
||||
<IonTabsInner {...this.props}>
|
||||
{React.Children.map(children, (child: React.ReactNode) => {
|
||||
if (React.isValidElement(child)) {
|
||||
const isRouterOutlet =
|
||||
child.type === IonRouterOutlet ||
|
||||
(child.type as any).isRouterOutlet ||
|
||||
(child.type === Fragment && child.props.children[0].type === IonRouterOutlet);
|
||||
|
||||
renderTabsInner(children: React.ReactNode, outlet: React.ReactElement<{}> | undefined) {
|
||||
return (
|
||||
<IonTabsInner {...this.props}>
|
||||
{React.Children.map(children, (child: React.ReactNode) => {
|
||||
if (React.isValidElement(child)) {
|
||||
const isRouterOutlet =
|
||||
child.type === IonRouterOutlet ||
|
||||
(child.type as any).isRouterOutlet ||
|
||||
(child.type === Fragment && child.props.children[0].type === IonRouterOutlet);
|
||||
|
||||
if (isRouterOutlet) {
|
||||
/**
|
||||
* The modified outlet needs to be returned to include
|
||||
* the ref.
|
||||
*/
|
||||
return outlet;
|
||||
}
|
||||
if (isRouterOutlet) {
|
||||
/**
|
||||
* The modified outlet needs to be returned to include
|
||||
* the ref.
|
||||
*/
|
||||
return outlet;
|
||||
}
|
||||
return child;
|
||||
})}
|
||||
</IonTabsInner>
|
||||
);
|
||||
}
|
||||
}
|
||||
return child;
|
||||
})}
|
||||
</IonTabsInner>
|
||||
);
|
||||
}
|
||||
|
||||
render() {
|
||||
let outlet: React.ReactElement<{}> | undefined;
|
||||
// Check if IonTabs has any IonTab children
|
||||
let hasTab = false;
|
||||
const { className, onIonTabsDidChange, onIonTabsWillChange, ...props } = this.props;
|
||||
render() {
|
||||
let outlet: React.ReactElement<{}> | undefined;
|
||||
// Check if IonTabs has any IonTab children
|
||||
let hasTab = false;
|
||||
const { className, onIonTabsDidChange, onIonTabsWillChange, ...props } = this.props;
|
||||
|
||||
const children =
|
||||
typeof this.props.children === 'function'
|
||||
? (this.props.children as ChildFunction)(this.ionTabContextState)
|
||||
: this.props.children;
|
||||
|
||||
React.Children.forEach(children, (child: any) => {
|
||||
// eslint-disable-next-line no-prototype-builtins
|
||||
if (child == null || typeof child !== 'object' || !child.hasOwnProperty('type')) {
|
||||
return;
|
||||
}
|
||||
if (child.type === IonRouterOutlet || child.type.isRouterOutlet) {
|
||||
outlet = React.cloneElement(child);
|
||||
} else if (child.type === Fragment && child.props.children[0].type === IonRouterOutlet) {
|
||||
outlet = React.cloneElement(child.props.children[0]);
|
||||
} else if (child.type === IonTab) {
|
||||
/**
|
||||
* This indicates that IonTabs will be using a basic tab-based navigation
|
||||
* without the history stack or URL updates associated with the router.
|
||||
*/
|
||||
hasTab = true;
|
||||
}
|
||||
|
||||
this.ionTabContextState.hasRouterOutlet = !!outlet;
|
||||
|
||||
let childProps: any = {
|
||||
...this.ionTabContextState.tabBarProps,
|
||||
};
|
||||
const children =
|
||||
typeof this.props.children === 'function'
|
||||
? (this.props.children as ChildFunction)(this.ionTabContextState)
|
||||
: this.props.children;
|
||||
|
||||
React.Children.forEach(children, (child: any) => {
|
||||
// eslint-disable-next-line no-prototype-builtins
|
||||
if (child == null || typeof child !== 'object' || !child.hasOwnProperty('type')) {
|
||||
return;
|
||||
}
|
||||
if (child.type === IonRouterOutlet || child.type.isRouterOutlet) {
|
||||
outlet = React.cloneElement(child);
|
||||
} else if (child.type === Fragment && child.props.children[0].type === IonRouterOutlet) {
|
||||
outlet = React.cloneElement(child.props.children[0]);
|
||||
} else if (child.type === IonTab) {
|
||||
/**
|
||||
* Only pass these props
|
||||
* down from IonTabs to IonTabBar
|
||||
* if they are defined, otherwise
|
||||
* if you have a handler set on
|
||||
* IonTabBar it will be overridden.
|
||||
* This indicates that IonTabs will be using a basic tab-based navigation
|
||||
* without the history stack or URL updates associated with the router.
|
||||
*/
|
||||
if (onIonTabsDidChange !== undefined) {
|
||||
childProps = {
|
||||
...childProps,
|
||||
onIonTabsDidChange,
|
||||
};
|
||||
}
|
||||
|
||||
if (onIonTabsWillChange !== undefined) {
|
||||
childProps = {
|
||||
...childProps,
|
||||
onIonTabsWillChange,
|
||||
};
|
||||
}
|
||||
|
||||
this.ionTabContextState.tabBarProps = childProps;
|
||||
});
|
||||
|
||||
if (!outlet && !hasTab) {
|
||||
throw new Error('IonTabs must contain an IonRouterOutlet or an IonTab');
|
||||
}
|
||||
if (outlet && hasTab) {
|
||||
throw new Error('IonTabs cannot contain an IonRouterOutlet and an IonTab at the same time');
|
||||
hasTab = true;
|
||||
}
|
||||
|
||||
if (hasTab) {
|
||||
return <IonTabsInner {...this.props}></IonTabsInner>;
|
||||
}
|
||||
this.ionTabContextState.hasRouterOutlet = !!outlet;
|
||||
|
||||
let childProps: any = {
|
||||
...this.ionTabContextState.tabBarProps,
|
||||
};
|
||||
|
||||
/**
|
||||
* TODO(ROU-11051)
|
||||
*
|
||||
* There is no error handling for the case where there
|
||||
* is no associated Route for the given IonTabButton.
|
||||
*
|
||||
* More investigation is needed to determine how to
|
||||
* handle this to prevent any overwriting of the
|
||||
* IonTabButton's onClick handler and how the routing
|
||||
* is handled.
|
||||
* Only pass these props
|
||||
* down from IonTabs to IonTabBar
|
||||
* if they are defined, otherwise
|
||||
* if you have a handler set on
|
||||
* IonTabBar it will be overridden.
|
||||
*/
|
||||
if (onIonTabsDidChange !== undefined) {
|
||||
childProps = {
|
||||
...childProps,
|
||||
onIonTabsDidChange,
|
||||
};
|
||||
}
|
||||
|
||||
return (
|
||||
<IonTabsContext.Provider value={this.ionTabContextState}>
|
||||
{this.context.hasIonicRouter() ? (
|
||||
<PageManager className={className ? `${className}` : ''} routeInfo={this.context.routeInfo} {...props}>
|
||||
{this.renderTabsInner(children, outlet)}
|
||||
</PageManager>
|
||||
) : (
|
||||
this.renderTabsInner(children, outlet)
|
||||
)}
|
||||
</IonTabsContext.Provider>
|
||||
);
|
||||
if (onIonTabsWillChange !== undefined) {
|
||||
childProps = {
|
||||
...childProps,
|
||||
onIonTabsWillChange,
|
||||
};
|
||||
}
|
||||
|
||||
this.ionTabContextState.tabBarProps = childProps;
|
||||
});
|
||||
|
||||
if (!outlet && !hasTab) {
|
||||
throw new Error('IonTabs must contain an IonRouterOutlet or an IonTab');
|
||||
}
|
||||
if (outlet && hasTab) {
|
||||
throw new Error('IonTabs cannot contain an IonRouterOutlet and an IonTab at the same time');
|
||||
}
|
||||
|
||||
static get contextType() {
|
||||
return NavContext;
|
||||
if (hasTab) {
|
||||
return <IonTabsInner {...this.props}></IonTabsInner>;
|
||||
}
|
||||
})();
|
||||
|
||||
/**
|
||||
* TODO(ROU-11051)
|
||||
*
|
||||
* There is no error handling for the case where there
|
||||
* is no associated Route for the given IonTabButton.
|
||||
*
|
||||
* More investigation is needed to determine how to
|
||||
* handle this to prevent any overwriting of the
|
||||
* IonTabButton's onClick handler and how the routing
|
||||
* is handled.
|
||||
*/
|
||||
|
||||
return (
|
||||
<IonTabsContext.Provider value={this.ionTabContextState}>
|
||||
{this.context.hasIonicRouter() ? (
|
||||
<PageManager className={className ? `${className}` : ''} routeInfo={this.context.routeInfo} {...props}>
|
||||
{this.renderTabsInner(children, outlet)}
|
||||
</PageManager>
|
||||
) : (
|
||||
this.renderTabsInner(children, outlet)
|
||||
)}
|
||||
</IonTabsContext.Provider>
|
||||
);
|
||||
}
|
||||
|
||||
static get contextType() {
|
||||
return NavContext;
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
import React from 'react';
|
||||
import { Route } from 'react-router-dom';
|
||||
import { IonApp, IonRouterOutlet, setupIonicReact } from '@ionic/react';
|
||||
import { IonReactRouter } from '@ionic/react-router';
|
||||
import React from 'react';
|
||||
import { Route } from 'react-router-dom';
|
||||
|
||||
/* Core CSS required for Ionic components to work properly */
|
||||
import '@ionic/react/css/core.css';
|
||||
@ -21,19 +21,19 @@ import '@ionic/react/css/display.css';
|
||||
|
||||
/* Theme variables */
|
||||
import './theme/variables.css';
|
||||
import Icons from './pages/Icons';
|
||||
import Main from './pages/Main';
|
||||
import OverlayHooks from './pages/overlay-hooks/OverlayHooks';
|
||||
import OverlayComponents from './pages/overlay-components/OverlayComponents';
|
||||
import KeepContentsMounted from './pages/overlay-components/KeepContentsMounted';
|
||||
import Tabs from './pages/Tabs';
|
||||
import TabsBasic from './pages/TabsBasic';
|
||||
import Icons from './pages/Icons';
|
||||
import NavComponent from './pages/navigation/NavComponent';
|
||||
import IonModalConditionalSibling from './pages/overlay-components/IonModalConditionalSibling';
|
||||
import IonModalConditional from './pages/overlay-components/IonModalConditional';
|
||||
import IonModalConditionalSibling from './pages/overlay-components/IonModalConditionalSibling';
|
||||
import IonModalDatetimeButton from './pages/overlay-components/IonModalDatetimeButton';
|
||||
import IonPopoverNested from './pages/overlay-components/IonPopoverNested';
|
||||
import IonModalMultipleChildren from './pages/overlay-components/IonModalMultipleChildren';
|
||||
import IonPopoverNested from './pages/overlay-components/IonPopoverNested';
|
||||
import KeepContentsMounted from './pages/overlay-components/KeepContentsMounted';
|
||||
import OverlayComponents from './pages/overlay-components/OverlayComponents';
|
||||
import OverlayHooks from './pages/overlay-hooks/OverlayHooks';
|
||||
|
||||
setupIonicReact();
|
||||
|
||||
|
@ -7,12 +7,14 @@
|
||||
"declaration": true,
|
||||
"experimentalDecorators": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"importHelpers": true,
|
||||
"lib": [
|
||||
"dom",
|
||||
"es2017"
|
||||
"es2020",
|
||||
"dom.iterable"
|
||||
],
|
||||
"module": "es2015",
|
||||
"moduleResolution": "node",
|
||||
"module": "esnext",
|
||||
"moduleResolution": "bundler",
|
||||
"noImplicitAny": true,
|
||||
"noImplicitReturns": true,
|
||||
"noUnusedLocals": true,
|
||||
@ -20,7 +22,8 @@
|
||||
"pretty": true,
|
||||
"removeComments": false,
|
||||
"strictPropertyInitialization": false,
|
||||
"target": "es2017",
|
||||
"target": "es2020",
|
||||
"jsx": "react-jsx",
|
||||
"baseUrl": ".",
|
||||
"paths": {
|
||||
"@ionic/core/hydrate": [
|
||||
|
Reference in New Issue
Block a user