@@ -28,16 +28,32 @@ import { floppyNavigation } from '@/utils';
2828import { Icon } from '@/components' ;
2929import './index.css' ;
3030
31+ export interface MenuItem {
32+ name : string ;
33+ path ?: string ;
34+ pathPrefix ?: string ;
35+ icon ?: string ;
36+ displayName ?: string ;
37+ badgeContent ?: string | number ;
38+ children ?: MenuItem [ ] ;
39+ }
40+
3141function MenuNode ( {
3242 menu,
3343 callback,
3444 activeKey,
3545 expanding = false ,
3646 path = '/' ,
47+ } : {
48+ menu : MenuItem ;
49+ callback : ( evt : any , menu : MenuItem , href : string , isLeaf : boolean ) => void ;
50+ activeKey : string ;
51+ expanding ?: boolean ;
52+ path ?: string ;
3753} ) {
3854 const { t } = useTranslation ( 'translation' , { keyPrefix : 'nav_menus' } ) ;
39- const isLeaf = ! menu . children . length ;
40- const href = isLeaf ? `${ path } ${ menu . path } ` : '#' ;
55+ const isLeaf = ! menu . children || menu . children . length === 0 ;
56+ const href = isLeaf ? `${ path } ${ menu . path || '' } ` : '#' ;
4157
4258 return (
4359 < Nav . Item key = { menu . path } className = "w-100" >
@@ -51,7 +67,14 @@ function MenuNode({
5167 } }
5268 className = { classNames (
5369 'text-nowrap d-flex flex-nowrap align-items-center w-100' ,
54- { expanding, active : activeKey === menu . path } ,
70+ {
71+ expanding,
72+ active :
73+ activeKey === menu . path ||
74+ ( menu . path && activeKey . startsWith ( `${ menu . path } /` ) ) ||
75+ // if pathPrefix is set, activate when activeKey starts with the pathPrefix
76+ ( menu . pathPrefix && activeKey . startsWith ( menu . pathPrefix ) ) ,
77+ } ,
5578 ) } >
5679 { menu ?. icon && < Icon name = { menu . icon } className = "me-2" /> }
5780
@@ -75,7 +98,13 @@ function MenuNode({
7598 } }
7699 className = { classNames (
77100 'text-nowrap d-flex flex-nowrap align-items-center w-100' ,
78- { expanding, active : activeKey === menu . path } ,
101+ {
102+ expanding,
103+ active :
104+ activeKey === menu . path ||
105+ ( menu . path && activeKey . startsWith ( `${ menu . path } /` ) ) ||
106+ ( menu . pathPrefix && activeKey . startsWith ( menu . pathPrefix ) ) ,
107+ } ,
79108 ) } >
80109 { menu ?. icon && < Icon name = { menu . icon } className = "me-2" /> }
81110 < span className = "me-auto text-truncate" >
@@ -90,8 +119,8 @@ function MenuNode({
90119 </ Nav . Link >
91120 ) }
92121
93- { menu . children . length ? (
94- < Accordion . Collapse eventKey = { menu . path } className = "ms-4" >
122+ { menu . children && menu . children . length > 0 ? (
123+ < Accordion . Collapse eventKey = { menu . path || menu . name } className = "ms-4" >
95124 < >
96125 { menu . children . map ( ( leaf ) => {
97126 return (
@@ -100,7 +129,7 @@ function MenuNode({
100129 callback = { callback }
101130 activeKey = { activeKey }
102131 path = { path }
103- key = { leaf . path }
132+ key = { leaf . path || leaf . name }
104133 />
105134 ) ;
106135 } ) }
@@ -112,7 +141,7 @@ function MenuNode({
112141}
113142
114143interface AccordionProps {
115- menus : any [ ] ;
144+ menus : MenuItem [ ] ;
116145 path ?: string ;
117146}
118147const AccordionNav : FC < AccordionProps > = ( { menus = [ ] , path = '/' } ) => {
@@ -137,19 +166,27 @@ const AccordionNav: FC<AccordionProps> = ({ menus = [], path = '/' }) => {
137166 } ) ;
138167
139168 const splat = pathMatch && pathMatch . params [ '*' ] ;
140- let activeKey = menus [ 0 ] . path ;
169+ let activeKey : string = menus [ 0 ] ?. path || menus [ 0 ] ?. name || '' ;
170+
141171 if ( splat ) {
142172 activeKey = splat ;
143173 }
174+
144175 const getOpenKey = ( ) => {
145176 let openKey = '' ;
146177 menus . forEach ( ( li ) => {
147- if ( li . children . length ) {
178+ if ( li . children && li . children . length > 0 ) {
148179 const matchedChild = li . children . find ( ( el ) => {
149- return el . path === activeKey ;
180+ // exact match or path prefix match
181+ return (
182+ el . path === activeKey ||
183+ ( el . path && activeKey . startsWith ( `${ el . path } /` ) ) ||
184+ // if pathPrefix is set, activate when activeKey starts with the pathPrefix
185+ ( el . pathPrefix && activeKey . startsWith ( el . pathPrefix ) )
186+ ) ;
150187 } ) ;
151188 if ( matchedChild ) {
152- openKey = li . path ;
189+ openKey = li . path || li . name || '' ;
153190 }
154191 }
155192 } ) ;
@@ -181,8 +218,8 @@ const AccordionNav: FC<AccordionProps> = ({ menus = [], path = '/' }) => {
181218 path = { path }
182219 callback = { menuClick }
183220 activeKey = { activeKey }
184- expanding = { openKey === li . path }
185- key = { li . path }
221+ expanding = { openKey === ( li . path || li . name ) }
222+ key = { li . path || li . name }
186223 />
187224 ) ;
188225 } ) }
0 commit comments