mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2025-08-18 11:17:19 +08:00
This commit is contained in:
@ -3,21 +3,34 @@ import React from 'react';
|
||||
import { NavContext } from '../contexts/NavContext';
|
||||
|
||||
import { IonicReactProps } from './IonicReactProps';
|
||||
import { createForwardRef } from './utils';
|
||||
|
||||
export const IonPage = /*@__PURE__*/(() => class IonPageInternal extends React.Component<React.HTMLAttributes<HTMLElement> & IonicReactProps> {
|
||||
interface IonPageProps extends IonicReactProps {
|
||||
}
|
||||
|
||||
interface IonPageInternalProps extends IonPageProps {
|
||||
forwardedRef?: React.RefObject<HTMLDivElement>;
|
||||
}
|
||||
|
||||
class IonPageInternal extends React.Component<IonPageInternalProps> {
|
||||
context!: React.ContextType<typeof NavContext>;
|
||||
ref = React.createRef<HTMLDivElement>();
|
||||
ref: React.RefObject<HTMLDivElement>;// React.createRef<HTMLDivElement>();
|
||||
|
||||
constructor(props: IonPageInternalProps) {
|
||||
super(props);
|
||||
this.ref = this.props.forwardedRef || React.createRef()
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
if (this.context && this.ref.current) {
|
||||
if (this.context && this.ref && this.ref.current) {
|
||||
if (this.context.hasIonicRouter()) {
|
||||
this.context.registerIonPage(this.ref.current);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
const { className, children, ...props } = this.props;
|
||||
const { className, children, forwardedRef, ...props } = this.props;
|
||||
|
||||
return (
|
||||
<div className={className ? `ion-page ${className}` : 'ion-page'} ref={this.ref} {...props}>
|
||||
@ -33,4 +46,6 @@ export const IonPage = /*@__PURE__*/(() => class IonPageInternal extends React.C
|
||||
static get contextType() {
|
||||
return NavContext;
|
||||
}
|
||||
})();
|
||||
};
|
||||
|
||||
export const IonPage = createForwardRef(IonPageInternal, 'IonPage');
|
||||
|
@ -13,7 +13,7 @@ type Props = LocalJSX.IonRouterOutlet & {
|
||||
};
|
||||
|
||||
type InternalProps = Props & {
|
||||
forwardedRef: any;
|
||||
forwardedRef?: React.RefObject<HTMLIonRouterOutletElement>;
|
||||
};
|
||||
|
||||
const IonRouterOutletContainer = /*@__PURE__*/(() => class extends React.Component<InternalProps> {
|
||||
|
@ -1,5 +1,6 @@
|
||||
|
||||
export interface IonicReactProps {
|
||||
class?: string;
|
||||
className?: string;
|
||||
style?: {[key: string]: any };
|
||||
}
|
||||
|
@ -19,14 +19,17 @@ export const createControllerComponent = <OptionsType extends object, OverlayTyp
|
||||
) => {
|
||||
const dismissEventName = `on${displayName}DidDismiss`;
|
||||
|
||||
type Props = OptionsType & ReactControllerProps;
|
||||
type Props = OptionsType & ReactControllerProps & {
|
||||
forwardedRef?: React.RefObject<OverlayType>
|
||||
};
|
||||
|
||||
return class extends React.Component<Props> {
|
||||
class Overlay extends React.Component<Props> {
|
||||
overlay?: OverlayType;
|
||||
isUnmounted = false;
|
||||
|
||||
constructor(props: Props) {
|
||||
super(props);
|
||||
this.handleDismiss = this.handleDismiss.bind(this);
|
||||
}
|
||||
|
||||
static get displayName() {
|
||||
@ -54,18 +57,30 @@ export const createControllerComponent = <OptionsType extends object, OverlayTyp
|
||||
}
|
||||
}
|
||||
|
||||
handleDismiss(event: CustomEvent<OverlayEventDetail<any>>) {
|
||||
if (this.props.onDidDismiss) {
|
||||
this.props.onDidDismiss(event);
|
||||
}
|
||||
if (this.props.forwardedRef) {
|
||||
(this.props.forwardedRef as any).current = undefined;
|
||||
}
|
||||
}
|
||||
|
||||
async present(prevProps?: Props) {
|
||||
const { isOpen, onDidDismiss, ...cProps } = this.props;
|
||||
this.overlay = await controller.create({
|
||||
...cProps as any
|
||||
});
|
||||
attachProps(this.overlay, {
|
||||
[dismissEventName]: onDidDismiss
|
||||
[dismissEventName]: this.handleDismiss
|
||||
}, prevProps);
|
||||
// Check isOpen again since the value could have changed during the async call to controller.create
|
||||
// It's also possible for the component to have become unmounted.
|
||||
if (this.props.isOpen === true && this.isUnmounted === false) {
|
||||
await this.overlay.present();
|
||||
if (this.props.forwardedRef) {
|
||||
(this.props.forwardedRef as any).current = this.overlay;
|
||||
}
|
||||
await this.overlay.present();
|
||||
}
|
||||
}
|
||||
|
||||
@ -73,4 +88,8 @@ export const createControllerComponent = <OptionsType extends object, OverlayTyp
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
return React.forwardRef<OverlayType, Props>((props, ref) => {
|
||||
return <Overlay {...props} forwardedRef={ref} />
|
||||
})
|
||||
};
|
||||
|
@ -15,21 +15,24 @@ export interface ReactOverlayProps {
|
||||
onDidDismiss?: (event: CustomEvent<OverlayEventDetail>) => void;
|
||||
}
|
||||
|
||||
export const createOverlayComponent = <T extends object, OverlayType extends OverlayElement>(
|
||||
export const createOverlayComponent = <OverlayComponent extends object, OverlayType extends OverlayElement>(
|
||||
displayName: string,
|
||||
controller: { create: (options: any) => Promise<OverlayType> }
|
||||
) => {
|
||||
const dismissEventName = `on${displayName}DidDismiss`;
|
||||
|
||||
type Props = T & ReactOverlayProps;
|
||||
type Props = OverlayComponent & ReactOverlayProps & {
|
||||
forwardedRef?: React.RefObject<OverlayType>
|
||||
};
|
||||
|
||||
return class extends React.Component<Props> {
|
||||
class Overlay extends React.Component<Props> {
|
||||
overlay?: OverlayType;
|
||||
el: HTMLDivElement;
|
||||
|
||||
constructor(props: Props) {
|
||||
super(props);
|
||||
this.el = document.createElement('div');
|
||||
this.handleDismiss = this.handleDismiss.bind(this);
|
||||
}
|
||||
|
||||
static get displayName() {
|
||||
@ -46,6 +49,15 @@ export const createOverlayComponent = <T extends object, OverlayType extends Ove
|
||||
if (this.overlay) { this.overlay.dismiss(); }
|
||||
}
|
||||
|
||||
handleDismiss(event: CustomEvent<OverlayEventDetail<any>>) {
|
||||
if (this.props.onDidDismiss) {
|
||||
this.props.onDidDismiss(event);
|
||||
}
|
||||
if (this.props.forwardedRef) {
|
||||
(this.props.forwardedRef as any).current = undefined;
|
||||
}
|
||||
}
|
||||
|
||||
async componentDidUpdate(prevProps: Props) {
|
||||
if (prevProps.isOpen !== this.props.isOpen && this.props.isOpen === true) {
|
||||
this.present(prevProps);
|
||||
@ -56,10 +68,11 @@ export const createOverlayComponent = <T extends object, OverlayType extends Ove
|
||||
}
|
||||
|
||||
async present(prevProps?: Props) {
|
||||
const { children, isOpen, onDidDismiss = () => { return; }, ...cProps } = this.props;
|
||||
const { children, isOpen, onDidDismiss, ...cProps } = this.props;
|
||||
const elementProps = {
|
||||
...cProps,
|
||||
[dismissEventName]: onDidDismiss
|
||||
ref: this.props.forwardedRef,
|
||||
[dismissEventName]: this.handleDismiss
|
||||
};
|
||||
|
||||
const overlay = this.overlay = await controller.create({
|
||||
@ -68,6 +81,10 @@ export const createOverlayComponent = <T extends object, OverlayType extends Ove
|
||||
componentProps: {}
|
||||
});
|
||||
|
||||
if (this.props.forwardedRef) {
|
||||
(this.props.forwardedRef as any).current = overlay;
|
||||
}
|
||||
|
||||
attachProps(overlay, elementProps, prevProps);
|
||||
|
||||
await overlay.present();
|
||||
@ -76,8 +93,12 @@ export const createOverlayComponent = <T extends object, OverlayType extends Ove
|
||||
render() {
|
||||
return ReactDOM.createPortal(
|
||||
this.props.children,
|
||||
this.el,
|
||||
this.el
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
return React.forwardRef<OverlayType, Props>((props, ref) => {
|
||||
return <Overlay {...props} forwardedRef={ref} />
|
||||
})
|
||||
};
|
||||
|
Reference in New Issue
Block a user