Skip to content

Commit

Permalink
fix(react): resolve errors with JSX and types
Browse files Browse the repository at this point in the history
  • Loading branch information
brandyscarney committed Feb 26, 2025
1 parent 30b1e7f commit 22b852e
Show file tree
Hide file tree
Showing 6 changed files with 292 additions and 288 deletions.
91 changes: 42 additions & 49 deletions packages/react/src/components/IonApp.tsx
Original file line number Diff line number Diff line change
@@ -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';
Expand All @@ -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;

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';
}
})();
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 displayName = 'IonApp';
}
84 changes: 40 additions & 44 deletions packages/react/src/components/navigation/IonBackButton.tsx
Original file line number Diff line number Diff line change
@@ -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>;
};

export const IonBackButton = /*@__PURE__*/ (() =>
class 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;
}
};

render() {
return <IonBackButtonInner onClick={this.clickButton} {...this.props}></IonBackButtonInner>;
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;
}

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;
}
}
68 changes: 36 additions & 32 deletions packages/react/src/components/navigation/IonTabButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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';
}
}
Loading

0 comments on commit 22b852e

Please sign in to comment.