@@ -19,7 +19,7 @@ import {
1919 styled ,
2020 Typography ,
2121} from '@mui/material' ;
22- import { TreeItem , TreeView , TreeViewClasses } from '@mui/x-tree-view' ;
22+ import { TreeItem , SimpleTreeView , SimpleTreeViewClasses } from '@mui/x-tree-view' ;
2323import {
2424 Check as CheckIcon ,
2525 ChevronRight as ChevronRightIcon ,
@@ -64,6 +64,14 @@ const defaultStyles = {
6464export const generateTreeViewFinderClass = ( className : string ) => `GsiTreeViewFinder-${ className } ` ;
6565const composeClasses = makeComposeClasses ( generateTreeViewFinderClass ) ;
6666
67+ function CustomExpandIcon ( { className } : Readonly < { className ?: string } > ) {
68+ return < ChevronRightIcon className = { className } /> ;
69+ }
70+
71+ function CustomCollapseIcon ( { className } : Readonly < { className ?: string } > ) {
72+ return < ExpandMoreIcon className = { className } /> ;
73+ }
74+
6775export interface TreeViewFinderNodeProps {
6876 id : UUID ;
6977 name : string ;
@@ -85,7 +93,7 @@ export interface TreeViewFinderProps {
8593 selected ?: string [ ] ;
8694 expanded ?: string [ ] ;
8795 multiSelect ?: boolean ;
88- classes ?: Partial < TreeViewClasses > ;
96+ classes ?: Partial < SimpleTreeViewClasses > ;
8997 className ?: string ;
9098
9199 // dialog props
@@ -99,7 +107,7 @@ export interface TreeViewFinderProps {
99107 // data management props
100108 onlyLeaves ?: boolean ;
101109 data ?: TreeViewFinderNodeProps [ ] ;
102- onTreeBrowse ?: ( nodeId : string ) => void ;
110+ onTreeBrowse ?: ( itemId : string ) => void ;
103111 sortMethod ?: ( a : TreeViewFinderNodeProps , b : TreeViewFinderNodeProps ) => number ;
104112}
105113
@@ -175,7 +183,7 @@ function TreeViewFinderComponant(props: Readonly<TreeViewFinderProps>) {
175183 const isValidationDisabled = ( ) => {
176184 return (
177185 selected ?. length === 0 ||
178- ( selected ?. length === selectedProp ?. length && selected ?. every ( ( nodeId ) => selectedProp ?. includes ( nodeId ) ) )
186+ ( selected ?. length === selectedProp ?. length && selected ?. every ( ( itemId ) => selectedProp ?. includes ( itemId ) ) )
179187 ) ;
180188 } ;
181189
@@ -191,22 +199,22 @@ function TreeViewFinderComponant(props: Readonly<TreeViewFinderProps>) {
191199 } , [ ] ) ;
192200
193201 const findParents = (
194- nodeId : string ,
202+ itemId : string ,
195203 nodes : TreeViewFinderNodeProps [ ] ,
196204 parentPath : TreeViewFinderNodeProps [ ] = [ ]
197205 ) : TreeViewFinderNodeProps [ ] | null => {
198206 let result : TreeViewFinderNodeProps [ ] | null = null ;
199207
200208 nodes . some ( ( node ) => {
201209 // If the current node matches the selected node, set result and break
202- if ( node . id === nodeId ) {
210+ if ( node . id === itemId ) {
203211 result = parentPath ;
204212 return true ;
205213 }
206214
207215 // If the current node has children, recursively search them
208216 if ( node . children ) {
209- const childResult = findParents ( nodeId , node . children , [ ...parentPath , node ] ) ;
217+ const childResult = findParents ( itemId , node . children , [ ...parentPath , node ] ) ;
210218 if ( childResult ) {
211219 result = childResult ;
212220 return true ;
@@ -232,34 +240,34 @@ function TreeViewFinderComponant(props: Readonly<TreeViewFinderProps>) {
232240 return [ ] ;
233241 }
234242 return selected
235- . map ( ( nodeId ) => {
236- const selectedNode = mapPrintedNodes [ nodeId ] ;
243+ . map ( ( itemId ) => {
244+ const selectedNode = mapPrintedNodes [ itemId ] ;
237245 if ( ! selectedNode ) {
238246 return null ;
239247 }
240248
241- const parents = findParents ( nodeId , data ?? [ ] ) ;
249+ const parents = findParents ( itemId , data ?? [ ] ) ;
242250
243251 return {
244252 ...selectedNode ,
245253 parents : parents ?? [ ] ,
246254 } ;
247255 } )
248- . filter ( ( node ) => node !== null ) ;
256+ . filter ( ( node ) => node !== null ) as TreeViewFinderNodeProps [ ] ;
249257 } ;
250258
251- const handleNodeToggle = ( _e : React . SyntheticEvent , nodeIds : string [ ] ) => {
259+ const handleNodeToggle = ( _e : React . SyntheticEvent , itemIds : string [ ] ) => {
252260 // onTreeBrowse proc only on last node clicked and only when expanded
253- nodeIds . every ( ( nodeId ) => {
254- if ( ! expanded ?. includes ( nodeId ) ) {
261+ itemIds . every ( ( itemId ) => {
262+ if ( ! expanded ?. includes ( itemId ) ) {
255263 // proc onTreeBrowse here
256- onTreeBrowse ?.( nodeId ) ;
264+ onTreeBrowse ?.( itemId ) ;
257265 return false ; // break loop to call onTreeBrowse only once
258266 }
259267 return true ;
260268 } ) ;
261269
262- setExpanded ( nodeIds ) ;
270+ setExpanded ( itemIds ) ;
263271 // will proc onNodeSelect then ...
264272 } ;
265273
@@ -288,7 +296,7 @@ function TreeViewFinderComponant(props: Readonly<TreeViewFinderProps>) {
288296 // if we have selected elements by default, we scroll to it
289297 if ( selectedProp . length > 0 && autoScrollAllowed ) {
290298 // we check if all expanded nodes by default all already expanded first
291- const isNodeExpanded = expandedProp ?. every ( ( nodeId ) => expanded ?. includes ( nodeId ) ) ;
299+ const isNodeExpanded = expandedProp ?. every ( ( itemId ) => expanded ?. includes ( itemId ) ) ;
292300
293301 // we got the last element that we suppose to scroll to
294302 const lastScrollRef = scrollRef . current [ scrollRef . current . length - 1 ] ;
@@ -304,11 +312,11 @@ function TreeViewFinderComponant(props: Readonly<TreeViewFinderProps>) {
304312 } , [ expanded , selectedProp , expandedProp , data , autoScrollAllowed ] ) ;
305313
306314 /* User Interaction management */
307- const handleNodeSelect = ( _e : React . SyntheticEvent , values : string | string [ ] ) => {
315+ const handleNodeSelect = ( _e : React . SyntheticEvent , values : string | string [ ] | null ) => {
308316 // Default management
309317 if ( multiSelect && Array . isArray ( values ) ) {
310- setSelected ( values . filter ( ( nodeId ) => isSelectable ( mapPrintedNodes [ nodeId ] ) ) ) ;
311- } else if ( ! Array . isArray ( values ) ) {
318+ setSelected ( values . filter ( ( itemId ) => isSelectable ( mapPrintedNodes [ itemId ] ) ) ) ;
319+ } else if ( typeof values === 'string' ) {
312320 // Toggle selection to allow unselection
313321 if ( selected ?. includes ( values ) ) {
314322 setSelected ( [ ] ) ;
@@ -348,7 +356,7 @@ function TreeViewFinderComponant(props: Readonly<TreeViewFinderProps>) {
348356 return null ;
349357 }
350358
351- if ( isSelectable ( node ) && selected ?. find ( ( nodeId ) => nodeId === node . id ) ) {
359+ if ( isSelectable ( node ) && selected ?. find ( ( itemId ) => itemId === node . id ) ) {
352360 return < CheckIcon className = { composeClasses ( classes , cssLabelIcon ) } /> ;
353361 }
354362 if ( node . icon ) {
@@ -365,36 +373,39 @@ function TreeViewFinderComponant(props: Readonly<TreeViewFinderProps>) {
365373 </ div >
366374 ) ;
367375 } ;
376+
368377 const showChevron = ( node : TreeViewFinderNodeProps ) => {
369- // by defaut show Chevron if childrenCount is null or undefined otherwise only if > 0
370- return ! ! ( node . childrenCount == null || ( node . childrenCount && node . childrenCount > 0 ) ) ;
378+ return ! ! ( node . childrenCount && node . childrenCount > 0 ) ;
371379 } ;
372380
373381 const renderTree = ( node : TreeViewFinderNodeProps ) => {
374382 if ( ! node ) {
375383 return null ;
376384 }
377385 let childrenNodes = null ;
378-
379- if ( Array . isArray ( node . children ) ) {
380- if ( node . children . length ) {
381- const sortedChildren = node . children . sort ( sortMethod ) ;
382- childrenNodes = sortedChildren . map ( ( child ) => renderTree ( child ) ) ;
383- } else {
384- childrenNodes = [ false ] ; // Pass non empty Array here to simulate a child then this node isn't considered as a leaf.
385- }
386+ const showExpandIcon = showChevron ( node ) ;
387+ if ( Array . isArray ( node . children ) && node . children . length > 0 ) {
388+ childrenNodes = node . children . toSorted ( sortMethod ) . map ( renderTree ) ;
389+ } else if ( showExpandIcon ) {
390+ childrenNodes = [ < span key = "placeholder" style = { { display : 'none' } } /> ] ; // simulate placeholder so expand icon is shown
386391 }
387392 return (
388393 < TreeItem
389394 key = { node . id }
390- nodeId = { node . id }
395+ itemId = { node . id }
391396 label = { renderTreeItemLabel ( node ) }
392- expandIcon = {
393- showChevron ( node ) ? < ChevronRightIcon className = { composeClasses ( classes , cssIcon ) } /> : null
394- }
395- collapseIcon = {
396- showChevron ( node ) ? < ExpandMoreIcon className = { composeClasses ( classes , cssIcon ) } /> : null
397- }
397+ slots = { {
398+ expandIcon : CustomExpandIcon ,
399+ collapseIcon : CustomCollapseIcon ,
400+ } }
401+ slotProps = { {
402+ expandIcon : {
403+ className : composeClasses ( classes , cssIcon ) ,
404+ } ,
405+ collapseIcon : {
406+ className : composeClasses ( classes , cssIcon ) ,
407+ } ,
408+ } }
398409 ref = { ( element ) => {
399410 if ( selectedProp ?. includes ( node . id ) ) {
400411 scrollRef . current . push ( element ) ;
@@ -445,17 +456,15 @@ function TreeViewFinderComponant(props: Readonly<TreeViewFinderProps>) {
445456 { contentText ?? intl . formatMessage ( { id : 'treeview_finder/contentText' } , { multiSelect } ) }
446457 </ DialogContentText >
447458
448- < TreeView
449- // Controlled props
450- expanded = { expanded }
451- // events
452- onNodeToggle = { handleNodeToggle }
453- onNodeSelect = { handleNodeSelect }
459+ < SimpleTreeView
460+ expandedItems = { expanded }
461+ onExpandedItemsChange = { handleNodeToggle }
462+ onSelectedItemsChange = { handleNodeSelect }
454463 // Uncontrolled props
455464 { ...getTreeViewSelectionProps ( ) }
456465 >
457466 { data && Array . isArray ( data ) ? data . sort ( sortMethod ) . map ( ( child ) => renderTree ( child ) ) : null }
458- </ TreeView >
467+ </ SimpleTreeView >
459468 </ DialogContent >
460469 < DialogActions >
461470 < CancelButton
0 commit comments