@@ -42,8 +42,12 @@ export interface BaseMenuProps extends Partial<PureSettings>, PrivateSiderMenuPr
4242}
4343
4444// vue props
45- export const VueBaseMenuProps = {
45+ export const baseMenuProps = {
4646 locale : Boolean ,
47+ i18n : {
48+ type : Function as PropType < FormatMessage > ,
49+ default : ( t : string ) : string => t ,
50+ } ,
4751 menuData : Array as PropType < MenuDataItem [ ] > ,
4852 // top-nav-header: horizontal
4953 mode : {
@@ -131,42 +135,118 @@ const IconFont = createFromIconfontCN({
131135 scriptUrl : defaultSettings . iconfontUrl ,
132136} ) ;
133137
134- const LazyIcon = ( props : any ) => {
135- const { icon, prefixCls } = props ;
138+ const LazyIcon = ( props : {
139+ icon : VNode | string ;
140+ iconPrefixes ?: string ;
141+ prefixCls ?: string ;
142+ } ) => {
143+ const { icon, iconPrefixes = 'icon-' , prefixCls = 'ant-pro' } = props ;
136144 if ( ! icon ) {
137145 return null ;
138146 }
139147 if ( typeof icon === 'string' && icon !== '' ) {
140148 if ( isUrl ( icon ) || isImg ( icon ) ) {
141149 return < img src = { icon } alt = "icon" class = { `${ prefixCls } -sider-menu-icon` } /> ;
142150 }
143- if ( icon . startsWith ( 'icon-' ) ) {
151+ if ( icon . startsWith ( iconPrefixes ) ) {
144152 return < IconFont type = { icon } /> ;
145153 }
146154 }
147155 if ( isVNode ( icon ) ) {
148156 return icon ;
149157 }
150- const LazyIcon = resolveComponent ( icon ) as any ;
151- return ( typeof LazyIcon === 'function' && < LazyIcon /> ) || null ;
158+ const DynamicIcon = resolveComponent ( icon ) as any ;
159+ return ( typeof LazyIcon === 'function' && < DynamicIcon /> ) || null ;
152160} ;
153161
154- LazyIcon . icon = {
155- type : [ String , Function , Object ] as PropType < string | Function | VNodeChild | JSX . Element > ,
162+ LazyIcon . props = {
163+ icon : {
164+ type : [ String , Function , Object ] as PropType < string | Function | VNode | JSX . Element > ,
165+ } ,
166+ iconPrefixes : String ,
167+ prefixCls : String ,
156168} ;
157169
170+ class MenuUtil {
171+ props : BaseMenuProps ;
172+
173+ constructor ( props : BaseMenuProps ) {
174+ this . props = props ;
175+ }
176+
177+ getNavMenuItems = ( menusData : MenuDataItem [ ] = [ ] , isChildren : boolean ) => {
178+ return menusData . map ( item => this . getSubMenuOrItem ( item , isChildren ) ) . filter ( item => item ) ;
179+ }
180+
181+ getSubMenuOrItem = ( item : MenuDataItem , isChildren : boolean ) => {
182+ if ( Array . isArray ( item . children )
183+ && item . children . length > 0
184+ && ! item ?. meta ?. hideInMenu ) {
185+ const { prefixCls, i18n } = this . props ;
186+ const menuTitle = i18n && i18n ( item . meta ?. title ) || item . meta ?. title ;
187+ const defaultTitle = item ?. meta . icon ? (
188+ < span class = { `${ prefixCls } -menu-item` } >
189+ { ! isChildren && < LazyIcon icon = { item . meta . icon } /> }
190+ < span class = { `${ prefixCls } -menu-item-title` } > { menuTitle } </ span >
191+ </ span >
192+ ) : (
193+ < span class = { `${ prefixCls } -menu-item` } > { menuTitle } </ span >
194+ ) ;
195+ const MenuComponent = item . meta ?. type === 'group' ? Menu . ItemGroup : Menu . SubMenu ;
196+ return (
197+ < MenuComponent title = { defaultTitle } key = { item . path } >
198+ { this . getNavMenuItems ( item . children , true ) }
199+ </ MenuComponent >
200+ ) ;
201+ }
202+
203+ return (
204+ < Menu . Item
205+ inlineIndent = { 24 }
206+ disabled = { item . meta ?. disabled }
207+ key = { item . path }
208+ // onClick={}
209+ >
210+ { this . getMenuItem ( item , isChildren ) }
211+ </ Menu . Item >
212+ ) ;
213+ }
214+
215+ getMenuItem = ( item : MenuDataItem , isChildren : boolean ) => {
216+ const meta = Object . assign ( { } , item . meta ) ;
217+ const target = meta . target || null ;
218+ const hasUrl = isUrl ( item . path ) ;
219+ const CustomTag : any = resolveComponent ( ( target && 'a' ) || 'router-link' ) ;
220+ const props = { to : { name : item . name } } ;
221+ const attrs = hasUrl || target ? { href : item . path , target : target } : { } ;
222+
223+ const { prefixCls, i18n } = this . props ;
224+ const menuTitle = i18n && i18n ( item . meta ?. title ) || item . meta ?. title ;
225+ const defaultTitle = item ?. meta . icon ? (
226+ < span class = { `${ prefixCls } -menu-item` } >
227+ < CustomTag { ...attrs } { ...props } >
228+ { ! isChildren && < LazyIcon icon = { item . meta . icon } /> }
229+ < span class = { `${ prefixCls } -menu-item-title` } > { menuTitle } </ span >
230+ </ CustomTag >
231+ </ span >
232+ ) : (
233+ < span class = { `${ prefixCls } -menu-item` } > { menuTitle } </ span >
234+ ) ;
235+
236+ return defaultTitle ;
237+ }
238+
239+ conversionPath = ( path : string ) => {
240+ if ( path && path . indexOf ( 'http' ) === 0 ) {
241+ return path ;
242+ }
243+ return `/${ path || '' } ` . replace ( / \/ + / g, '/' ) ;
244+ } ;
245+ }
246+
158247export default defineComponent ( {
159248 name : 'BaseMenu' ,
160- props : Object . assign (
161- { } ,
162- {
163- i18n : {
164- type : Function as PropType < FormatMessage > ,
165- default : ( t : string ) : string => t ,
166- } ,
167- } ,
168- VueBaseMenuProps ,
169- ) ,
249+ props : baseMenuProps ,
170250 emits : [ 'update:openKeys' , 'update:selectedKeys' ] ,
171251 setup ( props , { emit } ) {
172252 const { mode, i18n } = toRefs ( props ) ;
@@ -184,6 +264,8 @@ export default defineComponent({
184264 } ) : void => {
185265 emit ( 'update:selectedKeys' , params . selectedKeys ) ;
186266 } ;
267+ // TODO :: add `Menu` onClick custom handle.
268+
187269 return ( ) => (
188270 < Menu
189271 key = "Menu"
0 commit comments