@ui5/webcomponents-react
Version:
React Wrapper for UI5 Web Components and additional components
185 lines (183 loc) • 7.84 kB
JavaScript
'use client';
import ButtonDesign from '@ui5/webcomponents/dist/types/ButtonDesign.js';
import ListSeparator from '@ui5/webcomponents/dist/types/ListSeparator.js';
import TitleLevel from '@ui5/webcomponents/dist/types/TitleLevel.js';
import WrappingType from '@ui5/webcomponents/dist/types/WrappingType.js';
import ValueState from '@ui5/webcomponents-base/dist/types/ValueState.js';
import iconSlimArrowLeft from '@ui5/webcomponents-icons/dist/slim-arrow-left.js';
import { useI18nBundle, useStylesheet, useSyncRef } from '@ui5/webcomponents-react-base';
import { clsx } from 'clsx';
import { Children, forwardRef, Fragment, isValidElement, useCallback, useEffect, useState } from 'react';
import { FlexBoxDirection } from '../../enums/index.js';
import { ALL, LIST_NO_DATA } from '../../i18n/i18n-defaults.js';
import { MessageViewContext } from '../../internal/MessageViewContext.js';
import { Bar } from '../../webComponents/Bar/index.js';
import { Button } from '../../webComponents/Button/index.js';
import { Icon } from '../../webComponents/Icon/index.js';
import { List } from '../../webComponents/List/index.js';
import { ListItemGroup } from '../../webComponents/ListItemGroup/index.js';
import { SegmentedButton } from '../../webComponents/SegmentedButton/index.js';
import { SegmentedButtonItem } from '../../webComponents/SegmentedButtonItem/index.js';
import { Title } from '../../webComponents/Title/index.js';
import { FlexBox } from '../FlexBox/index.js';
import { classNames, styleData } from './MessageView.module.css.js';
import { getIconNameForType } from './utils.js';
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
export const resolveMessageTypes = children => {
return (children ?? []).map(message => message?.props?.type).reduce((acc, type) => {
const finalType = type === ValueState.None ? ValueState.Information : type;
if (acc.hasOwnProperty(finalType)) {
acc[finalType]++;
}
return acc;
}, {
[ValueState.Negative]: 0,
[ValueState.Critical]: 0,
[ValueState.Positive]: 0,
[ValueState.Information]: 0
});
};
export const resolveMessageGroups = children => {
const groups = (children ?? []).reduce((acc, val) => {
const groupName = val?.props?.groupName ?? '';
if (acc.hasOwnProperty(groupName)) {
acc[groupName].push(val);
} else {
acc[groupName] = [val];
}
return acc;
}, {});
return Object.entries(groups).sort((a, b) => {
return a[0].localeCompare(b[0]);
});
};
/**
* The `MessageView` is used to display a summarized list of different types of messages (error, warning, success, and information messages).
*/
const MessageView = /*#__PURE__*/forwardRef((props, ref) => {
const {
children,
groupItems,
showDetailsPageHeader,
className,
onItemSelect,
...rest
} = props;
useStylesheet(styleData, MessageView.displayName);
const [componentRef, internalRef] = useSyncRef(ref);
const i18nBundle = useI18nBundle('@ui5/webcomponents-react');
const [listFilter, setListFilter] = useState('All');
const [selectedMessage, setSelectedMessage] = useState(null);
const childrenArray = Children.toArray(children);
const messageTypes = resolveMessageTypes(childrenArray);
const filledTypes = Object.values(messageTypes).filter(count => count > 0).length;
const filteredChildren = listFilter === 'All' ? childrenArray : childrenArray.filter(message => {
if (! /*#__PURE__*/isValidElement(message)) {
return false;
}
const castMessage = message;
if (listFilter === ValueState.Information) {
return castMessage?.props?.type === ValueState.Information || castMessage?.props?.type === ValueState.None;
}
return castMessage?.props?.type === listFilter;
});
const groupedMessages = resolveMessageGroups(filteredChildren);
const navigateBack = useCallback(() => {
setSelectedMessage(null);
}, [setSelectedMessage]);
useEffect(() => {
if (internalRef.current) {
internalRef.current.navigateBack = navigateBack;
}
}, [internalRef.current, navigateBack]);
const handleListFilterChange = e => {
setListFilter(e.detail.selectedItems.at(0).dataset.key);
};
const outerClasses = clsx(classNames.container, className, selectedMessage && classNames.showDetails);
return /*#__PURE__*/_jsx("div", {
ref: componentRef,
...rest,
className: outerClasses,
children: /*#__PURE__*/_jsxs(MessageViewContext.Provider, {
value: {
selectMessage: setSelectedMessage
},
children: [/*#__PURE__*/_jsx("div", {
style: {
visibility: selectedMessage ? 'hidden' : 'visible'
},
className: classNames.messagesContainer,
children: !selectedMessage && /*#__PURE__*/_jsxs(_Fragment, {
children: [filledTypes > 1 && /*#__PURE__*/_jsx(Bar, {
startContent: /*#__PURE__*/_jsxs(SegmentedButton, {
onSelectionChange: handleListFilterChange,
children: [/*#__PURE__*/_jsx(SegmentedButtonItem, {
"data-key": "All",
selected: listFilter === 'All',
children: i18nBundle.getText(ALL)
}), Object.entries(messageTypes).map(([valueState, count]) => {
if (count === 0) {
return null;
}
return /*#__PURE__*/_jsx(SegmentedButtonItem, {
"data-key": valueState,
selected: listFilter === valueState,
icon: getIconNameForType(valueState),
className: classNames.button,
children: count
}, valueState);
})]
})
}), /*#__PURE__*/_jsx(List, {
onItemClick: onItemSelect,
noDataText: i18nBundle.getText(LIST_NO_DATA),
separators: ListSeparator.Inner,
children: groupItems ? groupedMessages.map(([groupName, items]) => {
if (!groupName) {
return items;
}
return /*#__PURE__*/_jsx(Fragment, {
children: groupName && /*#__PURE__*/_jsx(ListItemGroup, {
headerText: groupName,
children: items
})
}, groupName);
}) : filteredChildren
})]
})
}), /*#__PURE__*/_jsx("div", {
className: classNames.detailsContainer,
children: childrenArray.length > 0 ? /*#__PURE__*/_jsxs(_Fragment, {
children: [showDetailsPageHeader && selectedMessage && /*#__PURE__*/_jsx(Bar, {
startContent: /*#__PURE__*/_jsx(Button, {
design: ButtonDesign.Transparent,
icon: iconSlimArrowLeft,
onClick: navigateBack
})
}), selectedMessage && /*#__PURE__*/_jsxs(FlexBox, {
className: classNames.details,
children: [/*#__PURE__*/_jsx(Icon, {
"data-type": selectedMessage.type ?? ValueState.Negative,
name: getIconNameForType(selectedMessage.type),
className: classNames.detailsIcon
}), /*#__PURE__*/_jsxs(FlexBox, {
direction: FlexBoxDirection.Column,
className: classNames.detailsTextContainer,
children: [/*#__PURE__*/_jsx(Title, {
level: TitleLevel.H5,
className: classNames.detailsTitle,
wrappingType: WrappingType.Normal,
children: selectedMessage.titleText
}), /*#__PURE__*/_jsx("div", {
className: classNames.detailsText,
children: selectedMessage.children
})]
})]
})]
}) : null
})]
})
});
});
MessageView.displayName = 'MessageView';
export { MessageView };