@ui5/webcomponents-react
Version:
React Wrapper for UI5 Web Components and additional components
243 lines (242 loc) • 8.12 kB
JavaScript
'use client';
import ButtonDesign from '@ui5/webcomponents/dist/types/ButtonDesign.js';
import IconMode from '@ui5/webcomponents/dist/types/IconMode.js';
import ListSelectionMode from '@ui5/webcomponents/dist/types/ListSelectionMode.js';
import iconDecline from '@ui5/webcomponents-icons/dist/decline.js';
import iconSearch from '@ui5/webcomponents-icons/dist/search.js';
import { enrichEventWithDetails, useI18nBundle, useStylesheet, useSyncRef } from '@ui5/webcomponents-react-base';
import { clsx } from 'clsx';
import { forwardRef, useEffect, useState } from 'react';
import { CANCEL, CLEAR, RESET, SEARCH, SELECT, SELECTED } from '../../i18n/i18n-defaults.js';
import { Button, Dialog, FlexBox, FlexBoxAlignItems, Icon, Input, List, Text, Title } from '../../index.js';
import { classNames, styleData } from './SelectDialog.module.css.js';
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
/**
* The SelectDialog enables users to filter a comprehensive list via a search field and to select one or more items.
*/
const SelectDialog = /*#__PURE__*/forwardRef((props, ref) => {
const {
open,
children,
className,
confirmButtonText,
confirmButtonProps,
growing,
headerText,
headerTextAlignCenter,
listProps = {},
selectionMode = ListSelectionMode.Single,
numberOfSelectedItems,
rememberSelections,
showClearButton,
onClose,
onClear,
onConfirm,
onLoadMore,
onSearch,
onSearchInput,
onSearchReset,
onBeforeOpen,
onBeforeClose,
onOpen,
onCancel,
...rest
} = props;
useStylesheet(styleData, SelectDialog.displayName);
const i18nBundle = useI18nBundle('@ui5/webcomponents-react');
const [searchValue, setSearchValue] = useState('');
const [selectedItems, setSelectedItems] = useState([]);
const [listComponentRef, listRef] = useSyncRef(listProps.ref);
const [internalOpen, setInternalOpen] = useState(open);
useEffect(() => {
setInternalOpen(open);
}, [open]);
const handleBeforeOpen = e => {
const localSelectedItems = listRef.current?.getSelectedItems() ?? [];
if (typeof onBeforeOpen === 'function') {
onBeforeOpen(e);
}
if (selectionMode === ListSelectionMode.Multiple && listRef.current?.hasData) {
setSelectedItems(localSelectedItems);
}
};
const handleAfterOpen = e => {
if (typeof onOpen === 'function') {
onOpen(e);
}
listRef.current?.focusFirstItem();
};
const handleSearchInput = e => {
if (typeof onSearchInput === 'function') {
onSearchInput(enrichEventWithDetails(e, {
value: e.target.value
}));
}
setSearchValue(e.target.value);
};
const handleSearchSubmit = e => {
if (typeof onSearch === 'function') {
if (e.type === 'keyup' && e.code === 'Enter') {
onSearch(enrichEventWithDetails(e, {
value: e.target.value
}));
}
if (e.type === 'click') {
onSearch(enrichEventWithDetails(e, {
value: searchValue
}));
}
}
};
const handleResetSearch = e => {
if (typeof onSearchReset === 'function') {
onSearchReset(enrichEventWithDetails(e, {
prevValue: searchValue
}));
}
setSearchValue('');
};
const handleSelectionChange = e => {
if (typeof listProps?.onSelectionChange === 'function') {
listProps.onSelectionChange(e);
}
if (selectionMode === ListSelectionMode.Multiple) {
setSelectedItems(e.detail.selectedItems);
} else {
if (typeof onConfirm === 'function') {
onConfirm(e);
}
setInternalOpen(false);
}
};
const handleClose = e => {
setInternalOpen(false);
if (typeof onCancel === 'function') {
onCancel(e);
}
};
const handleClear = e => {
if (typeof onClear === 'function') {
onClear(enrichEventWithDetails(e, {
prevSelectedItems: selectedItems
}));
}
setSelectedItems([]);
listRef.current?.deselectSelectedItems();
};
const handleConfirm = e => {
if (typeof onConfirm === 'function') {
onConfirm(enrichEventWithDetails(e, {
selectedItems
}));
}
setInternalOpen(false);
};
const handleAfterClose = e => {
setInternalOpen(false);
if (typeof onClose === 'function') {
onClose(e);
}
if (typeof onSearchReset === 'function') {
onSearchReset(enrichEventWithDetails(e, {
prevValue: searchValue
}));
}
setSearchValue('');
if (!rememberSelections) {
listRef.current?.deselectSelectedItems();
}
};
const handleBeforeClose = e => {
if (typeof onBeforeClose === 'function') {
onBeforeClose(e);
}
if (typeof onCancel === 'function' && e.detail.escPressed) {
onCancel(e);
}
};
return /*#__PURE__*/_jsxs(Dialog, {
...rest,
open: internalOpen,
"data-component-name": "SelectDialog",
ref: ref,
className: clsx(classNames.dialog, className),
onClose: handleAfterClose,
onBeforeOpen: handleBeforeOpen,
onOpen: handleAfterOpen,
onBeforeClose: handleBeforeClose,
children: [/*#__PURE__*/_jsxs("div", {
className: classNames.headerContent,
slot: "header",
children: [showClearButton && headerTextAlignCenter && /*#__PURE__*/_jsx(Button, {
onClick: handleClear,
design: ButtonDesign.Transparent,
className: classNames.hiddenClearBtn,
tabIndex: -1,
"aria-hidden": "true",
children: i18nBundle.getText(CLEAR)
}), /*#__PURE__*/_jsx(Title, {
className: clsx(classNames.title, headerTextAlignCenter && classNames.titleCenterAlign),
children: headerText
}), showClearButton && /*#__PURE__*/_jsx(Button, {
onClick: handleClear,
design: ButtonDesign.Transparent,
className: classNames.clearBtn,
children: i18nBundle.getText(CLEAR)
}), /*#__PURE__*/_jsx(Input, {
className: classNames.input,
accessibleName: i18nBundle.getText(SEARCH),
value: searchValue,
placeholder: i18nBundle.getText(SEARCH),
onInput: handleSearchInput,
onKeyUp: handleSearchSubmit,
icon: /*#__PURE__*/_jsxs(_Fragment, {
children: [searchValue && /*#__PURE__*/_jsx(Icon, {
accessibleName: i18nBundle.getText(RESET),
title: i18nBundle.getText(RESET),
name: iconDecline,
mode: IconMode.Interactive,
onClick: handleResetSearch,
className: classNames.inputIcon
}), /*#__PURE__*/_jsx(Icon, {
mode: IconMode.Interactive,
name: iconSearch,
className: classNames.inputIcon,
onClick: handleSearchSubmit,
accessibleName: i18nBundle.getText(SEARCH),
title: i18nBundle.getText(SEARCH)
})]
})
})]
}), selectionMode === ListSelectionMode.Multiple && (!!selectedItems.length || numberOfSelectedItems > 0) && /*#__PURE__*/_jsx(FlexBox, {
alignItems: FlexBoxAlignItems.Center,
className: classNames.infoBar,
children: /*#__PURE__*/_jsx(Text, {
children: `${i18nBundle.getText(SELECTED)}: ${numberOfSelectedItems ?? selectedItems.length}`
})
}), /*#__PURE__*/_jsx(List, {
...listProps,
ref: listComponentRef,
growing: growing,
onLoadMore: onLoadMore,
selectionMode: selectionMode,
onSelectionChange: handleSelectionChange,
children: children
}), /*#__PURE__*/_jsxs("div", {
slot: "footer",
className: classNames.footer,
children: [selectionMode === ListSelectionMode.Multiple && /*#__PURE__*/_jsx(Button, {
...confirmButtonProps,
onClick: handleConfirm,
design: ButtonDesign.Emphasized,
children: confirmButtonText ?? i18nBundle.getText(SELECT)
}), /*#__PURE__*/_jsx(Button, {
onClick: handleClose,
design: ButtonDesign.Transparent,
children: i18nBundle.getText(CANCEL)
})]
})]
});
});
SelectDialog.displayName = 'SelectDialog';
export { SelectDialog };