mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2026-03-13 10:22:08 +08:00
68 lines
1.8 KiB
TypeScript
68 lines
1.8 KiB
TypeScript
import React, { useEffect, useState } from 'react';
|
|
import ReactDOM from 'react-dom';
|
|
|
|
import { ReactComponentOrElement } from '../models';
|
|
|
|
interface IonOverlayManagerProps {
|
|
onAddOverlay: (
|
|
callback: (
|
|
id: string,
|
|
component: ReactComponentOrElement,
|
|
containerElement: HTMLDivElement
|
|
) => void
|
|
) => void;
|
|
onRemoveOverlay: (callback: (id: string) => void) => void;
|
|
}
|
|
|
|
/**
|
|
* Manages overlays that are added via the useOverlay hook.
|
|
* This is a standalone component so changes to its children don't cause other descendant
|
|
* components to re-render when overlays are added. However, we need to communicate with the IonContext
|
|
* that is set up in <IonApp />, so we register callbacks so when overlays are added to IonContext,
|
|
* they ultimately added here.
|
|
*/
|
|
export const IonOverlayManager: React.FC<IonOverlayManagerProps> = ({
|
|
onAddOverlay,
|
|
onRemoveOverlay,
|
|
}) => {
|
|
const [overlays, setOverlays] = useState<{
|
|
[key: string]: {
|
|
component: any;
|
|
containerElement: HTMLDivElement;
|
|
};
|
|
}>({});
|
|
|
|
useEffect(() => {
|
|
/* Setup the callbacks that get called from <IonApp /> */
|
|
onAddOverlay(addOverlay);
|
|
onRemoveOverlay(removeOverlay);
|
|
}, []);
|
|
|
|
const addOverlay = (
|
|
id: string,
|
|
component: ReactComponentOrElement,
|
|
containerElement: HTMLDivElement
|
|
) => {
|
|
const newOverlays = { ...overlays };
|
|
newOverlays[id] = { component, containerElement };
|
|
setOverlays(newOverlays);
|
|
};
|
|
|
|
const removeOverlay = (id: string) => {
|
|
const newOverlays = { ...overlays };
|
|
delete newOverlays[id];
|
|
setOverlays(newOverlays);
|
|
};
|
|
|
|
const overlayKeys = Object.keys(overlays);
|
|
|
|
return (
|
|
<>
|
|
{overlayKeys.map((key) => {
|
|
const overlay = overlays[key];
|
|
return ReactDOM.createPortal(overlay.component, overlay.containerElement, `overlay-${key}`);
|
|
})}
|
|
</>
|
|
);
|
|
};
|