@ui5/webcomponents-react
Version:
React Wrapper for UI5 Web Components and additional components
291 lines (275 loc) • 8 kB
JavaScript
'use client';
import { createRef, useEffect, useSyncExternalStore, createElement as _createElement } from 'react';
import { createPortal } from 'react-dom';
import { getRandomId } from '../../internal/getRandomId.js';
import { ModalStore } from '../../internal/ModalStore.js';
import { Dialog } from '../../webComponents/Dialog/index.js';
import { Menu } from '../../webComponents/Menu/index.js';
import { Popover } from '../../webComponents/Popover/index.js';
import { ResponsivePopover } from '../../webComponents/ResponsivePopover/index.js';
import { Toast } from '../../webComponents/Toast/index.js';
import { MessageBox } from '../MessageBox/index.js';
/**
* @since 2.19.0
*/
/**
* @since 2.19.0
*/
import { Fragment as _Fragment, jsx as _jsx } from "react/jsx-runtime";
function autoClose(props) {
const openPopovers = ModalStore.getPopoversWithSameOpener(props.opener);
openPopovers.forEach(popover => {
const popoverRef = popover.ref;
if (popoverRef.current) {
popoverRef.current.open = false;
}
});
}
/**
* @deprecated Passing `container` directly is deprecated. Use the `config` object with `config.container` instead.
*/
function showDialogFn(props, containerOrConfig) {
const isContainer = containerOrConfig instanceof Element || containerOrConfig instanceof DocumentFragment;
const id = getRandomId();
const ref = /*#__PURE__*/createRef();
ModalStore.addModal({
Component: Dialog,
props: {
...props,
open: true,
onClose: event => {
if (typeof props.onClose === 'function') {
props.onClose(event);
}
ModalStore.removeModal(id);
}
},
ref,
container: isContainer ? containerOrConfig : containerOrConfig?.container,
id
});
return {
ref,
close: () => {
if (ref.current) {
ref.current.open = false;
}
}
};
}
/**
* @deprecated Passing `container` directly is deprecated. Use the `config` object with `config.container` instead.
*/
function showPopoverFn(props, containerOrConfig) {
const isContainer = containerOrConfig instanceof Element || containerOrConfig instanceof DocumentFragment;
const id = getRandomId();
const ref = /*#__PURE__*/createRef();
if (!isContainer && containerOrConfig?.autoClosePopovers) {
autoClose(props);
}
ModalStore.addModal({
Component: Popover,
props: {
...props,
open: true,
onClose: event => {
if (typeof props.onClose === 'function') {
props.onClose(event);
}
ModalStore.removeModal(id);
}
},
ref,
container: isContainer ? containerOrConfig : containerOrConfig?.container,
id
});
return {
ref,
close: () => {
if (ref.current) {
ref.current.open = false;
}
}
};
}
/**
* @deprecated Passing `container` directly is deprecated. Use the `config` object with `config.container` instead.
*/
function showResponsivePopoverFn(props, containerOrConfig) {
const isContainer = containerOrConfig instanceof Element || containerOrConfig instanceof DocumentFragment;
const id = getRandomId();
const ref = /*#__PURE__*/createRef();
if (!isContainer && containerOrConfig?.autoClosePopovers) {
autoClose(props);
}
ModalStore.addModal({
Component: ResponsivePopover,
props: {
...props,
open: true,
onClose: event => {
if (typeof props.onClose === 'function') {
props.onClose(event);
}
ModalStore.removeModal(id);
}
},
ref,
container: isContainer ? containerOrConfig : containerOrConfig?.container,
id
});
return {
ref,
close: () => {
if (ref.current) {
ref.current.open = false;
}
}
};
}
/**
* @deprecated Passing `container` directly is deprecated. Use the `config` object with `config.container` instead.
*/
function showMenuFn(props, containerOrConfig) {
const isContainer = containerOrConfig instanceof Element || containerOrConfig instanceof DocumentFragment;
const id = getRandomId();
const ref = /*#__PURE__*/createRef();
if (!isContainer && containerOrConfig?.autoClosePopovers) {
autoClose(props);
}
ModalStore.addModal({
Component: Menu,
props: {
...props,
open: true,
onClose: event => {
if (typeof props.onClose === 'function') {
props.onClose(event);
}
ModalStore.removeModal(id);
}
},
ref,
container: isContainer ? containerOrConfig : containerOrConfig?.container,
id
});
return {
ref,
close: () => {
if (ref.current) {
ref.current.open = false;
}
}
};
}
/**
* @deprecated Passing `container` directly is deprecated. Use the `config` object with `config.container` instead.
*/
function showMessageBoxFn(props, containerOrConfig) {
const isContainer = containerOrConfig instanceof Element || containerOrConfig instanceof DocumentFragment;
const id = getRandomId();
const ref = /*#__PURE__*/createRef();
ModalStore.addModal({
// @ts-expect-error: props type safety is covered by the `props` property
Component: MessageBox,
props: {
...props,
open: true,
onClose: event => {
if (typeof props.onClose === 'function') {
props.onClose(event);
}
ModalStore.removeModal(id);
}
},
ref,
container: isContainer ? containerOrConfig : containerOrConfig?.container,
id
});
return {
ref,
close: () => {
if (ref.current) {
ref.current.open = false;
}
}
};
}
/**
* @deprecated Passing `container` directly is deprecated. Use the `config` object with `config.container` instead.
*/
function showToastFn(props, containerOrConfig) {
const isContainer = containerOrConfig instanceof Element || containerOrConfig instanceof DocumentFragment;
const ref = /*#__PURE__*/createRef();
const id = getRandomId();
ModalStore.addModal({
Component: Toast,
props: {
...props,
open: true,
onClose: event => {
if (typeof props.onClose === 'function') {
props.onClose(event);
}
ModalStore.removeModal(id);
}
},
ref,
container: isContainer ? containerOrConfig : containerOrConfig?.container,
id
});
return {
ref
};
}
/**
* Utility class for opening modals in an imperative way.
*
* These static helper methods might be useful for showing e.g. Toasts or MessageBoxes after successful or failed
* network calls.
*
* **In order to use these helpers, please make sure to render the `Modals` component somewhere in your application tree.**
*
* @since 0.22.2
*/
export function Modals() {
const modals = useSyncExternalStore(ModalStore.subscribe, ModalStore.getSnapshot, ModalStore.getServerSnapshot);
useEffect(() => {
return () => {
ModalStore.getSnapshot().forEach(modal => {
ModalStore.removeModal(modal.id);
});
};
}, []);
return /*#__PURE__*/_jsx(_Fragment, {
children: modals.map(modal => {
if (modal?.Component) {
if (modal.container) {
return /*#__PURE__*/createPortal(
/*#__PURE__*/
// @ts-expect-error: ref is supported by all supported modals
_createElement(modal.Component, {
...modal.props,
ref: modal.ref,
key: modal.id,
"data-id": modal.id
}), modal.container);
}
// @ts-expect-error: ref is supported by all supported modals
return /*#__PURE__*/_createElement(modal.Component, {
...modal.props,
ref: modal.ref,
key: modal.id,
"data-id": modal.id
});
}
})
});
}
Modals.displayName = 'Modals';
Modals.showDialog = showDialogFn;
Modals.showPopover = showPopoverFn;
Modals.showResponsivePopover = showResponsivePopoverFn;
Modals.showMenu = showMenuFn;
Modals.showMessageBox = showMessageBoxFn;
Modals.showToast = showToastFn;