@ui5/webcomponents-react
Version:
React Wrapper for UI5 Web Components and additional components
198 lines (194 loc) • 7.05 kB
JavaScript
'use client';
import ButtonDesign from '@ui5/webcomponents/dist/types/ButtonDesign.js';
import IconMode from '@ui5/webcomponents/dist/types/IconMode.js';
import PopupAccessibleRole from '@ui5/webcomponents/dist/types/PopupAccessibleRole.js';
import TitleLevel from '@ui5/webcomponents/dist/types/TitleLevel.js';
import ValueState from '@ui5/webcomponents-base/dist/types/ValueState.js';
import iconSysHelp from '@ui5/webcomponents-icons/dist/sys-help-2.js';
import { useI18nBundle, useStylesheet } from '@ui5/webcomponents-react-base';
import { clsx } from 'clsx';
import { cloneElement, forwardRef, isValidElement, useId } from 'react';
import { MessageBoxAction } from '../../enums/MessageBoxAction.js';
import { MessageBoxType } from '../../enums/MessageBoxType.js';
import { ABORT, CANCEL, CLOSE, CONFIRMATION, DELETE, ERROR, IGNORE, INFORMATION, NO, OK, RETRY, SUCCESS, WARNING, YES } from '../../i18n/i18n-defaults.js';
import { Button, Dialog, Icon, Text, Title } from '../../webComponents/index.js';
import { classNames, styleData } from './MessageBox.module.css.js';
// eslint-disable-next-line @typescript-eslint/no-redundant-type-constituents
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
const getIcon = (icon, type, classes) => {
if (/*#__PURE__*/isValidElement(icon)) return icon;
switch (type) {
case MessageBoxType.Confirm:
return /*#__PURE__*/_jsx(Icon, {
name: iconSysHelp,
mode: IconMode.Decorative,
className: classes.confirmIcon
});
default:
return null;
}
};
const convertMessageBoxTypeToState = type => {
switch (type) {
case MessageBoxType.Information:
return ValueState.Information;
case MessageBoxType.Success:
return ValueState.Positive;
case MessageBoxType.Warning:
return ValueState.Critical;
case MessageBoxType.Error:
return ValueState.Negative;
default:
return ValueState.None;
}
};
const getActions = (actions, type) => {
if (actions && actions.length > 0) {
return actions;
}
if (type === MessageBoxType.Confirm) {
return [MessageBoxAction.OK, MessageBoxAction.Cancel];
}
if (type === MessageBoxType.Error) {
return [MessageBoxAction.Close];
}
return [MessageBoxAction.OK];
};
/**
* The `MessageBox` component provides easier methods to create a `Dialog`, such as standard alerts, confirmation dialogs, or arbitrary message dialogs.
*/
const MessageBox = /*#__PURE__*/forwardRef((props, ref) => {
const {
open,
type = MessageBoxType.Confirm,
children,
className,
titleText,
icon,
actions = [],
emphasizedAction = MessageBoxAction.OK,
onClose,
initialFocus,
...rest
} = props;
useStylesheet(styleData, MessageBox.displayName);
const i18nBundle = useI18nBundle('@ui5/webcomponents-react');
const actionTranslations = {
[MessageBoxAction.Abort]: i18nBundle.getText(ABORT),
[MessageBoxAction.Cancel]: i18nBundle.getText(CANCEL),
[MessageBoxAction.Close]: i18nBundle.getText(CLOSE),
[MessageBoxAction.Delete]: i18nBundle.getText(DELETE),
[MessageBoxAction.Ignore]: i18nBundle.getText(IGNORE),
[MessageBoxAction.No]: i18nBundle.getText(NO),
[MessageBoxAction.OK]: i18nBundle.getText(OK),
[MessageBoxAction.Retry]: i18nBundle.getText(RETRY),
[MessageBoxAction.Yes]: i18nBundle.getText(YES)
};
const titleToRender = () => {
if (titleText) {
return titleText;
}
switch (type) {
case MessageBoxType.Confirm:
return i18nBundle.getText(CONFIRMATION);
case MessageBoxType.Error:
return i18nBundle.getText(ERROR);
case MessageBoxType.Information:
return i18nBundle.getText(INFORMATION);
case MessageBoxType.Success:
return i18nBundle.getText(SUCCESS);
case MessageBoxType.Warning:
return i18nBundle.getText(WARNING);
default:
return null;
}
};
const handleDialogClose = e => {
if (typeof props.onBeforeClose === 'function') {
props.onBeforeClose(e);
}
if (e.detail.escPressed && typeof onClose === 'function') {
onClose(undefined, e.detail.escPressed);
}
};
const handleOnClose = e => {
const {
action
} = e.currentTarget.dataset;
if (typeof onClose === 'function') {
onClose(action);
}
};
const messageBoxId = useId();
const internalActions = getActions(actions, type);
const getInitialFocus = () => {
const index = internalActions.findIndex(action => action === initialFocus);
if (index !== -1 && typeof internalActions[index] === 'string') {
return `${messageBoxId}-action-${index}`;
}
return initialFocus;
};
// @ts-expect-error: footer, headerText and onClose are already omitted via prop types
const {
footer: _0,
headerText: _1,
onClose: _2,
onBeforeClose: _3,
...restWithoutOmitted
} = rest;
const iconToRender = getIcon(icon, type, classNames);
const needsCustomHeader = !props.header && !!iconToRender;
return /*#__PURE__*/_jsxs(Dialog, {
open: open,
ref: ref,
className: clsx(classNames.messageBox, className),
onBeforeClose: handleDialogClose,
accessibleNameRef: needsCustomHeader ? `${messageBoxId}-title ${messageBoxId}-text` : undefined,
accessibleRole: PopupAccessibleRole.AlertDialog,
...restWithoutOmitted,
headerText: titleToRender(),
state: convertMessageBoxTypeToState(type),
initialFocus: getInitialFocus(),
"data-type": type,
children: [needsCustomHeader && /*#__PURE__*/_jsxs("div", {
slot: "header",
className: classNames.header,
children: [iconToRender, iconToRender && /*#__PURE__*/_jsx("span", {
className: classNames.spacer
}), /*#__PURE__*/_jsx(Title, {
id: `${messageBoxId}-title`,
level: TitleLevel.H1,
children: titleToRender()
})]
}), /*#__PURE__*/_jsx(Text, {
id: `${messageBoxId}-text`,
children: children
}), /*#__PURE__*/_jsx("div", {
slot: "footer",
className: classNames.footer,
children: internalActions.map((action, index) => {
if (typeof action !== 'string' && /*#__PURE__*/isValidElement(action)) {
return /*#__PURE__*/cloneElement(action, {
onClick: action?.props?.onClick ? e => {
action?.props?.onClick(e);
handleOnClose(e);
} : handleOnClose,
'data-action': action?.props?.['data-action'] ?? `${index}: custom action`
});
}
if (typeof action === 'string') {
return /*#__PURE__*/_jsx(Button, {
id: `${messageBoxId}-action-${index}`,
design: emphasizedAction === action ? ButtonDesign.Emphasized : ButtonDesign.Transparent,
onClick: handleOnClose,
"data-action": action,
children: actionTranslations[action] ?? action
}, `${action}-${index}`);
}
return null;
})
})]
});
});
MessageBox.displayName = 'MessageBox';
export { MessageBox };