@@ -12,35 +12,57 @@ import searchIcon from '@ui5/webcomponents-icons/dist/search.js';
12
12
import { enrichEventWithDetails , useI18nBundle , useStylesheet } from '@ui5/webcomponents-react-base' ;
13
13
import { clsx } from 'clsx' ;
14
14
import 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' ;
16
26
import { MANAGE , MY_VIEWS , SAVE , SAVE_AS , SEARCH , SEARCH_VARIANT , SELECT_VIEW } from '../../i18n/i18n-defaults.js' ;
17
27
import { stopPropagation } from '../../internal/stopPropagation.js' ;
18
28
import type { SelectedVariant } from '../../internal/VariantManagementContext.js' ;
19
29
import { 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' ;
31
41
import { FlexBox } from '../FlexBox/index.js' ;
32
42
import type { ManageViewsDialogPropTypes } from './ManageViewsDialog.js' ;
33
43
import { ManageViewsDialog } from './ManageViewsDialog.js' ;
34
44
import { SaveViewDialog } from './SaveViewDialog.js' ;
35
- import type { VariantManagementPropTypes } from './types.js' ;
45
+ import type { SelectedVariantWithStringBool , VariantManagementPropTypes } from './types.js' ;
36
46
import type { VariantItemPropTypes } from './VariantItem.js' ;
37
47
import { classNames , styleData } from './VariantManagement.module.css.js' ;
38
48
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
+
39
59
/**
40
60
* The VariantManagement can be used to manage variants (views). You can use this component to create and maintain personalization changes.
41
61
*
42
62
* __Note:__ On the user interface, variants are generally referred to as "views".
43
63
*
64
+ * __Note:__ Each `VariantManagement` component can only have one default and one selected variant.
65
+ *
44
66
* ### Matching header styles
45
67
*
46
68
* 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>
117
139
const [ popoverOpen , setPopoverOpen ] = useState ( false ) ;
118
140
const [ manageViewsDialogOpen , setManageViewsDialogOpen ] = useState ( false ) ;
119
141
const [ saveAsDialogOpen , setSaveAsDialogOpen ] = useState ( false ) ;
120
- const [ selectedVariant , setSelectedVariant ] = useState < SelectedVariant | undefined > ( ( ) => {
142
+ const [ selectedVariant , setSelectedVariantState ] = useState < SelectedVariant | undefined > ( ( ) => {
121
143
const currentSelectedVariant = safeChildren . find (
122
144
( item ) => isValidElement ( item ) && ( item as ReactElement < VariantItemPropTypes > ) . props . selected
123
145
) as ComponentElement < any , any > ;
124
146
if ( currentSelectedVariant ) {
125
147
return { ...currentSelectedVariant . props , variantItem : currentSelectedVariant . ref } ;
126
148
}
127
149
} ) ;
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
+
128
180
const [ selectedSaveViewInputProps , setSelectedSaveViewInputProps ] = useState (
129
181
selectedVariant ?. saveViewInputProps ?? { }
130
182
) ;
@@ -258,8 +310,13 @@ const VariantManagement = forwardRef<HTMLDivElement, VariantManagementPropTypes>
258
310
setSelectedSaveViewInputProps ( selectedChild ?. props . saveViewInputProps ?? { } ) ;
259
311
} , [ selectedVariant , safeChildren ] ) ;
260
312
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
+ } ) ;
263
320
selectVariantEventRef . current = e ;
264
321
if ( closeOnItemSelect ) {
265
322
handleClose ( ) ;
@@ -317,19 +374,14 @@ const VariantManagement = forwardRef<HTMLDivElement, VariantManagementPropTypes>
317
374
}
318
375
} , [ safeChildrenWithFavorites ] ) ;
319
376
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 ;
327
378
328
379
return (
329
380
< div className = { variantManagementClasses } style = { style } { ...rest } ref = { ref } >
330
381
< VariantManagementContext . Provider
331
382
value = { {
332
- selectVariantItem : setSelectedVariant
383
+ selectVariantItem : setSelectedVariant ,
384
+ selectedVariant
333
385
} }
334
386
>
335
387
< FlexBox onClick = { disabled ? undefined : handleOpenVariantManagement } >
0 commit comments