@@ -12,35 +12,57 @@ import searchIcon from '@ui5/webcomponents-icons/dist/search.js';
1212import { enrichEventWithDetails , useI18nBundle , useStylesheet } from '@ui5/webcomponents-react-base' ;
1313import { clsx } from 'clsx' ;
1414import type { ComponentElement , ReactElement } from 'react' ;
15- import { Children , cloneElement , forwardRef , isValidElement , useCallback , useEffect , useRef , useState } from 'react' ;
15+ import {
16+ Children ,
17+ cloneElement ,
18+ forwardRef ,
19+ isValidElement ,
20+ useCallback ,
21+ useEffect ,
22+ useRef ,
23+ useState ,
24+ version as reactVersion
25+ } from 'react' ;
1626import { MANAGE , MY_VIEWS , SAVE , SAVE_AS , SEARCH , SEARCH_VARIANT , SELECT_VIEW } from '../../i18n/i18n-defaults.js' ;
1727import { stopPropagation } from '../../internal/stopPropagation.js' ;
1828import type { SelectedVariant } from '../../internal/VariantManagementContext.js' ;
1929import { VariantManagementContext } from '../../internal/VariantManagementContext.js' ;
20- import type { ResponsivePopoverDomRef } from '../../webComponents/index.js' ;
21- import {
22- Bar ,
23- Button ,
24- Icon ,
25- IllustratedMessage ,
26- Input ,
27- List ,
28- ResponsivePopover ,
29- Title
30- } from '../../webComponents/index.js' ;
30+ import { Bar } from '../../webComponents/Bar /index.js' ;
31+ import { Button } from '../../webComponents/Button/index.js' ;
32+ import { Icon } from '../../webComponents/Icon/index.js' ;
33+ import { IllustratedMessage } from '../../webComponents/IllustratedMessage/index.js' ;
34+ import { Input } from '../../webComponents/Input/index.js' ;
35+ import type { ListPropTypes } from '../../webComponents/List/index.js' ;
36+ import { List } from '../../webComponents/List/index.js' ;
37+ import type { ListItemStandardDomRef } from '../../webComponents/ListItemStandard/index.js' ;
38+ import type { ResponsivePopoverDomRef } from '../../webComponents/ ResponsivePopover/index.js' ;
39+ import { ResponsivePopover } from '../../webComponents/ResponsivePopover/index.js' ;
40+ import { Title } from '../../webComponents/Title /index.js' ;
3141import { FlexBox } from '../FlexBox/index.js' ;
3242import type { ManageViewsDialogPropTypes } from './ManageViewsDialog.js' ;
3343import { ManageViewsDialog } from './ManageViewsDialog.js' ;
3444import { SaveViewDialog } from './SaveViewDialog.js' ;
35- import type { VariantManagementPropTypes } from './types.js' ;
45+ import type { SelectedVariantWithStringBool , VariantManagementPropTypes } from './types.js' ;
3646import type { VariantItemPropTypes } from './VariantItem.js' ;
3747import { classNames , styleData } from './VariantManagement.module.css.js' ;
3848
49+ const booleanProps = {
50+ favorite : true ,
51+ global : true ,
52+ isDefault : true ,
53+ labelReadOnly : true ,
54+ applyAutomatically : true ,
55+ readOnly : true ,
56+ hideDelete : true
57+ } ;
58+
3959/**
4060 * The VariantManagement can be used to manage variants (views). You can use this component to create and maintain personalization changes.
4161 *
4262 * __Note:__ On the user interface, variants are generally referred to as "views".
4363 *
64+ * __Note:__ Each `VariantManagement` component can only have one default and one selected variant.
65+ *
4466 * ### Matching header styles
4567 *
4668 * To ensure consistent header styles for different use-cases of the `VariantManagement`, we recommend setting the following styles to the `ui5-title` component:
@@ -117,14 +139,44 @@ const VariantManagement = forwardRef<HTMLDivElement, VariantManagementPropTypes>
117139 const [ popoverOpen , setPopoverOpen ] = useState ( false ) ;
118140 const [ manageViewsDialogOpen , setManageViewsDialogOpen ] = useState ( false ) ;
119141 const [ saveAsDialogOpen , setSaveAsDialogOpen ] = useState ( false ) ;
120- const [ selectedVariant , setSelectedVariant ] = useState < SelectedVariant | undefined > ( ( ) => {
142+ const [ selectedVariant , setSelectedVariantState ] = useState < SelectedVariant | undefined > ( ( ) => {
121143 const currentSelectedVariant = safeChildren . find (
122144 ( item ) => isValidElement ( item ) && ( item as ReactElement < VariantItemPropTypes > ) . props . selected
123145 ) as ComponentElement < any , any > ;
124146 if ( currentSelectedVariant ) {
125147 return { ...currentSelectedVariant . props , variantItem : currentSelectedVariant . ref } ;
126148 }
127149 } ) ;
150+ const setSelectedVariant = ( variant : SelectedVariantWithStringBool ) => {
151+ if ( variant ) {
152+ const stringToBoolVariant = Object . entries ( variant ) . reduce ( ( acc , [ key , val ] ) => {
153+ if ( booleanProps [ key ] ) {
154+ if ( typeof val === 'boolean' ) {
155+ acc [ key ] = val ;
156+ return acc ;
157+ }
158+ if ( val === 'false' ) {
159+ acc [ key ] = false ;
160+ return acc ;
161+ }
162+ if ( val === 'true' ) {
163+ acc [ key ] = true ;
164+ return acc ;
165+ }
166+ if ( reactVersion . startsWith ( '19' ) && val === '' ) {
167+ acc [ key ] = true ;
168+ return acc ;
169+ }
170+ }
171+ acc [ key ] = val ;
172+ return acc ;
173+ } , { } ) as SelectedVariant ;
174+ setSelectedVariantState ( stringToBoolVariant ) ;
175+ } else {
176+ setSelectedVariantState ( variant as SelectedVariant ) ;
177+ }
178+ } ;
179+
128180 const [ selectedSaveViewInputProps , setSelectedSaveViewInputProps ] = useState (
129181 selectedVariant ?. saveViewInputProps ?? { }
130182 ) ;
@@ -258,8 +310,13 @@ const VariantManagement = forwardRef<HTMLDivElement, VariantManagementPropTypes>
258310 setSelectedSaveViewInputProps ( selectedChild ?. props . saveViewInputProps ?? { } ) ;
259311 } , [ selectedVariant , safeChildren ] ) ;
260312
261- const handleVariantItemSelect = ( e ) => {
262- setSelectedVariant ( { ...e . detail . selectedItems [ 0 ] . dataset , variantItem : e . detail . selectedItems [ 0 ] } ) ;
313+ const handleVariantItemSelect : ListPropTypes [ 'onSelectionChange' ] = ( e ) => {
314+ const targetItem = e . detail . targetItem as unknown as ListItemStandardDomRef ;
315+ const dataset = targetItem . dataset as unknown as SelectedVariantWithStringBool ;
316+ setSelectedVariant ( {
317+ ...dataset ,
318+ variantItem : targetItem
319+ } ) ;
263320 selectVariantEventRef . current = e ;
264321 if ( closeOnItemSelect ) {
265322 handleClose ( ) ;
@@ -317,19 +374,14 @@ const VariantManagement = forwardRef<HTMLDivElement, VariantManagementPropTypes>
317374 }
318375 } , [ safeChildrenWithFavorites ] ) ;
319376
320- //todo: selectedVariant type needs to be enhanced for React19 (data attributes: true => "", false => "false")
321- const showSaveBtn =
322- dirtyState &&
323- selectedVariant &&
324- ( typeof selectedVariant ?. readOnly === 'string'
325- ? selectedVariant . readOnly !== '' && selectedVariant . readOnly === 'false'
326- : ! selectedVariant . readOnly ) ;
377+ const showSaveBtn = dirtyState && selectedVariant && ! selectedVariant . readOnly ;
327378
328379 return (
329380 < div className = { variantManagementClasses } style = { style } { ...rest } ref = { ref } >
330381 < VariantManagementContext . Provider
331382 value = { {
332- selectVariantItem : setSelectedVariant
383+ selectVariantItem : setSelectedVariant ,
384+ selectedVariant
333385 } }
334386 >
335387 < FlexBox onClick = { disabled ? undefined : handleOpenVariantManagement } >
0 commit comments