UNPKG

@ui5/webcomponents-react

Version:

React Wrapper for UI5 Web Components and additional components

185 lines (183 loc) 7.84 kB
'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 };