mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2025-08-20 12:29:55 +08:00
This commit is contained in:
@ -87,6 +87,10 @@ export class StackManager extends React.Component<StackManagerProps, StackManage
|
|||||||
ref: this.routerOutletEl
|
ref: this.routerOutletEl
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if(ionRouterOutlet.props.forwardedRef) {
|
||||||
|
ionRouterOutlet.props.forwardedRef.current = this.routerOutletEl;
|
||||||
|
}
|
||||||
|
|
||||||
if (isDevMode()) {
|
if (isDevMode()) {
|
||||||
elementProps['data-stack-id'] = this.id;
|
elementProps['data-stack-id'] = this.id;
|
||||||
}
|
}
|
||||||
@ -99,4 +103,4 @@ export class StackManager extends React.Component<StackManagerProps, StackManage
|
|||||||
static get contextType() {
|
static get contextType() {
|
||||||
return RouteManagerContext;
|
return RouteManagerContext;
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -3,21 +3,34 @@ import React from 'react';
|
|||||||
import { NavContext } from '../contexts/NavContext';
|
import { NavContext } from '../contexts/NavContext';
|
||||||
|
|
||||||
import { IonicReactProps } from './IonicReactProps';
|
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>;
|
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() {
|
componentDidMount() {
|
||||||
if (this.context && this.ref.current) {
|
if (this.context && this.ref && this.ref.current) {
|
||||||
if (this.context.hasIonicRouter()) {
|
if (this.context.hasIonicRouter()) {
|
||||||
this.context.registerIonPage(this.ref.current);
|
this.context.registerIonPage(this.ref.current);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { className, children, ...props } = this.props;
|
const { className, children, forwardedRef, ...props } = this.props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={className ? `ion-page ${className}` : 'ion-page'} ref={this.ref} {...props}>
|
<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() {
|
static get contextType() {
|
||||||
return NavContext;
|
return NavContext;
|
||||||
}
|
}
|
||||||
})();
|
};
|
||||||
|
|
||||||
|
export const IonPage = createForwardRef(IonPageInternal, 'IonPage');
|
||||||
|
@ -13,7 +13,7 @@ type Props = LocalJSX.IonRouterOutlet & {
|
|||||||
};
|
};
|
||||||
|
|
||||||
type InternalProps = Props & {
|
type InternalProps = Props & {
|
||||||
forwardedRef: any;
|
forwardedRef?: React.RefObject<HTMLIonRouterOutletElement>;
|
||||||
};
|
};
|
||||||
|
|
||||||
const IonRouterOutletContainer = /*@__PURE__*/(() => class extends React.Component<InternalProps> {
|
const IonRouterOutletContainer = /*@__PURE__*/(() => class extends React.Component<InternalProps> {
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
|
|
||||||
export interface IonicReactProps {
|
export interface IonicReactProps {
|
||||||
class?: string;
|
class?: string;
|
||||||
|
className?: string;
|
||||||
style?: {[key: string]: any };
|
style?: {[key: string]: any };
|
||||||
}
|
}
|
||||||
|
@ -19,14 +19,17 @@ export const createControllerComponent = <OptionsType extends object, OverlayTyp
|
|||||||
) => {
|
) => {
|
||||||
const dismissEventName = `on${displayName}DidDismiss`;
|
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;
|
overlay?: OverlayType;
|
||||||
isUnmounted = false;
|
isUnmounted = false;
|
||||||
|
|
||||||
constructor(props: Props) {
|
constructor(props: Props) {
|
||||||
super(props);
|
super(props);
|
||||||
|
this.handleDismiss = this.handleDismiss.bind(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
static get displayName() {
|
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) {
|
async present(prevProps?: Props) {
|
||||||
const { isOpen, onDidDismiss, ...cProps } = this.props;
|
const { isOpen, onDidDismiss, ...cProps } = this.props;
|
||||||
this.overlay = await controller.create({
|
this.overlay = await controller.create({
|
||||||
...cProps as any
|
...cProps as any
|
||||||
});
|
});
|
||||||
attachProps(this.overlay, {
|
attachProps(this.overlay, {
|
||||||
[dismissEventName]: onDidDismiss
|
[dismissEventName]: this.handleDismiss
|
||||||
}, prevProps);
|
}, prevProps);
|
||||||
// Check isOpen again since the value could have changed during the async call to controller.create
|
// 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.
|
// It's also possible for the component to have become unmounted.
|
||||||
if (this.props.isOpen === true && this.isUnmounted === false) {
|
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 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;
|
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,
|
displayName: string,
|
||||||
controller: { create: (options: any) => Promise<OverlayType> }
|
controller: { create: (options: any) => Promise<OverlayType> }
|
||||||
) => {
|
) => {
|
||||||
const dismissEventName = `on${displayName}DidDismiss`;
|
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;
|
overlay?: OverlayType;
|
||||||
el: HTMLDivElement;
|
el: HTMLDivElement;
|
||||||
|
|
||||||
constructor(props: Props) {
|
constructor(props: Props) {
|
||||||
super(props);
|
super(props);
|
||||||
this.el = document.createElement('div');
|
this.el = document.createElement('div');
|
||||||
|
this.handleDismiss = this.handleDismiss.bind(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
static get displayName() {
|
static get displayName() {
|
||||||
@ -46,6 +49,15 @@ export const createOverlayComponent = <T extends object, OverlayType extends Ove
|
|||||||
if (this.overlay) { this.overlay.dismiss(); }
|
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) {
|
async componentDidUpdate(prevProps: Props) {
|
||||||
if (prevProps.isOpen !== this.props.isOpen && this.props.isOpen === true) {
|
if (prevProps.isOpen !== this.props.isOpen && this.props.isOpen === true) {
|
||||||
this.present(prevProps);
|
this.present(prevProps);
|
||||||
@ -56,10 +68,11 @@ export const createOverlayComponent = <T extends object, OverlayType extends Ove
|
|||||||
}
|
}
|
||||||
|
|
||||||
async present(prevProps?: Props) {
|
async present(prevProps?: Props) {
|
||||||
const { children, isOpen, onDidDismiss = () => { return; }, ...cProps } = this.props;
|
const { children, isOpen, onDidDismiss, ...cProps } = this.props;
|
||||||
const elementProps = {
|
const elementProps = {
|
||||||
...cProps,
|
...cProps,
|
||||||
[dismissEventName]: onDidDismiss
|
ref: this.props.forwardedRef,
|
||||||
|
[dismissEventName]: this.handleDismiss
|
||||||
};
|
};
|
||||||
|
|
||||||
const overlay = this.overlay = await controller.create({
|
const overlay = this.overlay = await controller.create({
|
||||||
@ -68,6 +81,10 @@ export const createOverlayComponent = <T extends object, OverlayType extends Ove
|
|||||||
componentProps: {}
|
componentProps: {}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (this.props.forwardedRef) {
|
||||||
|
(this.props.forwardedRef as any).current = overlay;
|
||||||
|
}
|
||||||
|
|
||||||
attachProps(overlay, elementProps, prevProps);
|
attachProps(overlay, elementProps, prevProps);
|
||||||
|
|
||||||
await overlay.present();
|
await overlay.present();
|
||||||
@ -76,8 +93,12 @@ export const createOverlayComponent = <T extends object, OverlayType extends Ove
|
|||||||
render() {
|
render() {
|
||||||
return ReactDOM.createPortal(
|
return ReactDOM.createPortal(
|
||||||
this.props.children,
|
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