1- import { Layout , Menu as AntdMenu , MenuProps } from "antd" ;
1+ import { Layout , Menu as AntdMenu , MenuProps , Segmented } from "antd" ;
22import MainContent from "components/layout/MainContent" ;
33import { LayoutMenuItemComp , LayoutMenuItemListComp } from "comps/comps/layout/layoutMenuItemComp" ;
44import { menuPropertyView } from "comps/comps/navComp/components/MenuItemList" ;
@@ -8,17 +8,47 @@ import { withDispatchHook } from "comps/generators/withDispatchHook";
88import { NameAndExposingInfo } from "comps/utils/exposingTypes" ;
99import { ALL_APPLICATIONS_URL } from "constants/routesURL" ;
1010import { TopHeaderHeight } from "constants/style" ;
11- import { Section , sectionNames } from "lowcoder-design" ;
11+ import { Section , controlItem , sectionNames } from "lowcoder-design" ;
1212import { trans } from "i18n" ;
1313import { EditorContainer , EmptyContent } from "pages/common/styledComponent" ;
1414import { useCallback , useEffect , useMemo , useState } from "react" ;
15- import styled from "styled-components" ;
15+ import styled , { css } from "styled-components" ;
1616import { isUserViewMode , useAppPathParam } from "util/hooks" ;
1717import { StringControl } from "comps/controls/codeControl" ;
1818import { styleControl } from "comps/controls/styleControl" ;
19- import { NavLayoutStyle } from "comps/controls/styleControlConstants" ;
19+ import {
20+ NavLayoutStyle ,
21+ NavLayoutItemStyle ,
22+ NavLayoutItemStyleType ,
23+ NavLayoutItemHoverStyle ,
24+ NavLayoutItemHoverStyleType ,
25+ NavLayoutItemActiveStyle ,
26+ NavLayoutItemActiveStyleType ,
27+ } from "comps/controls/styleControlConstants" ;
28+ import { dropdownControl } from "comps/controls/dropdownControl" ;
2029
2130const DEFAULT_WIDTH = 240 ;
31+ const ModeOptions = [
32+ { label : trans ( "navLayout.modeInline" ) , value : "inline" } ,
33+ { label : trans ( "navLayout.modeVertical" ) , value : "vertical" } ,
34+ ] as const ;
35+
36+ type MenuItemStyleOptionValue = "normal" | "hover" | "active" ;
37+
38+ const menuItemStyleOptions = [
39+ {
40+ value : "normal" ,
41+ label : "Normal" ,
42+ } ,
43+ {
44+ value : "hover" ,
45+ label : "Hover" ,
46+ } ,
47+ {
48+ value : "active" ,
49+ label : "Active" ,
50+ }
51+ ]
2252
2353const StyledSide = styled ( Layout . Sider ) `
2454 max-height: calc(100vh - ${ TopHeaderHeight } );
@@ -44,34 +74,138 @@ const ContentWrapper = styled.div`
4474 }
4575` ;
4676
77+ const StyledMenu = styled ( AntdMenu ) < {
78+ $navItemStyle ?: NavLayoutItemStyleType & { width : string } ,
79+ $navItemHoverStyle ?: NavLayoutItemHoverStyleType ,
80+ $navItemActiveStyle ?: NavLayoutItemActiveStyleType ,
81+ } > `
82+ .ant-menu-item {
83+ height: auto;
84+ width: ${ ( props ) => props . $navItemStyle ?. width } ;
85+ background-color: ${ ( props ) => props . $navItemStyle ?. background } ;
86+ color: ${ ( props ) => props . $navItemStyle ?. text } ;
87+ border-radius: ${ ( props ) => props . $navItemStyle ?. radius } !important;
88+ border: ${ ( props ) => `1px solid ${ props . $navItemStyle ?. border } ` } ;
89+ margin: ${ ( props ) => props . $navItemStyle ?. margin } ;
90+ padding: ${ ( props ) => props . $navItemStyle ?. padding } ;
91+
92+ }
93+ .ant-menu-item-active {
94+ background-color: ${ ( props ) => props . $navItemHoverStyle ?. background } !important;
95+ color: ${ ( props ) => props . $navItemHoverStyle ?. text } !important;
96+ border: ${ ( props ) => `1px solid ${ props . $navItemHoverStyle ?. border } ` } ;
97+ }
98+
99+ .ant-menu-item-selected {
100+ background-color: ${ ( props ) => props . $navItemActiveStyle ?. background } !important;
101+ color: ${ ( props ) => props . $navItemActiveStyle ?. text } !important;
102+ border: ${ ( props ) => `1px solid ${ props . $navItemActiveStyle ?. border } ` } ;
103+ }
104+
105+ .ant-menu-submenu {
106+ margin: ${ ( props ) => props . $navItemStyle ?. margin } ;
107+ width: ${ ( props ) => props . $navItemStyle ?. width } ;
108+
109+ .ant-menu-submenu-title {
110+ width: 100%;
111+ height: auto !important;
112+ background-color: ${ ( props ) => props . $navItemStyle ?. background } ;
113+ color: ${ ( props ) => props . $navItemStyle ?. text } ;
114+ border-radius: ${ ( props ) => props . $navItemStyle ?. radius } !important;
115+ border: ${ ( props ) => `1px solid ${ props . $navItemStyle ?. border } ` } ;
116+ margin: 0;
117+ padding: ${ ( props ) => props . $navItemStyle ?. padding } ;
118+
119+ }
120+
121+ .ant-menu-item {
122+ width: 100%;
123+ }
124+
125+ &.ant-menu-submenu-active {
126+ >.ant-menu-submenu-title {
127+ width: 100%;
128+ background-color: ${ ( props ) => props . $navItemHoverStyle ?. background } !important;
129+ color: ${ ( props ) => props . $navItemHoverStyle ?. text } !important;
130+ border: ${ ( props ) => `1px solid ${ props . $navItemHoverStyle ?. border } ` } ;
131+ }
132+ }
133+ &.ant-menu-submenu-selected {
134+ >.ant-menu-submenu-title {
135+ width: 100%;
136+ background-color: ${ ( props ) => props . $navItemActiveStyle ?. background } !important;
137+ color: ${ ( props ) => props . $navItemActiveStyle ?. text } !important;
138+ border: ${ ( props ) => `1px solid ${ props . $navItemActiveStyle ?. border } ` } ;
139+ }
140+ }
141+ }
142+
143+ ` ;
144+
145+ const defaultStyle = {
146+ radius : '0px' ,
147+ margin : '0px' ,
148+ padding : '0px' ,
149+ }
150+
47151let NavTmpLayout = ( function ( ) {
48152 const childrenMap = {
49153 items : withDefault ( LayoutMenuItemListComp , [
50154 {
51155 label : trans ( "menuItem" ) + " 1" ,
52156 } ,
53157 ] ) ,
54- width : StringControl ,
55- style : styleControl ( NavLayoutStyle ) ,
158+ width : withDefault ( StringControl , DEFAULT_WIDTH ) ,
159+ mode : dropdownControl ( ModeOptions , "inline" ) ,
160+ navStyle : withDefault ( styleControl ( NavLayoutStyle ) , defaultStyle ) ,
161+ navItemStyle : withDefault ( styleControl ( NavLayoutItemStyle ) , defaultStyle ) ,
162+ navItemHoverStyle : withDefault ( styleControl ( NavLayoutItemHoverStyle ) , { } ) ,
163+ navItemActiveStyle : withDefault ( styleControl ( NavLayoutItemActiveStyle ) , { } ) ,
56164 } ;
57165 return new MultiCompBuilder ( childrenMap , ( props ) => {
58166 return null ;
59167 } )
60168 . setPropertyViewFn ( ( children ) => {
169+ const [ styleSegment , setStyleSegment ] = useState ( 'normal' )
170+
61171 return (
62- < >
172+ < div style = { { overflowY : 'auto' } } >
63173 < Section name = { trans ( "menu" ) } > { menuPropertyView ( children . items ) } </ Section >
64174 < Section name = { sectionNames . layout } >
65175 { children . width . propertyView ( {
66- label : trans ( "drawer .width" ) ,
67- tooltip : trans ( "drawer .widthTooltip" ) ,
176+ label : trans ( "navLayout .width" ) ,
177+ tooltip : trans ( "navLayout .widthTooltip" ) ,
68178 placeholder : DEFAULT_WIDTH + "" ,
69- } ) }
179+ } ) }
180+ { children . mode . propertyView ( {
181+ label : trans ( "labelProp.position" ) ,
182+ radioButton : true
183+ } ) }
70184 </ Section >
71- < Section name = { sectionNames . style } >
72- { children . style . getPropertyView ( ) }
185+ < Section name = { trans ( "navLayout.navStyle" ) } >
186+ { children . navStyle . getPropertyView ( ) }
73187 </ Section >
74- </ >
188+ < Section name = { trans ( "navLayout.navItemStyle" ) } >
189+ { controlItem ( { } , (
190+ < Segmented
191+ block
192+ options = { menuItemStyleOptions }
193+ value = { styleSegment }
194+ // className="comp-panel-tab"
195+ onChange = { ( k ) => setStyleSegment ( k as MenuItemStyleOptionValue ) }
196+ />
197+ ) ) }
198+ { styleSegment === 'normal' && (
199+ children . navItemStyle . getPropertyView ( )
200+ ) }
201+ { styleSegment === 'hover' && (
202+ children . navItemHoverStyle . getPropertyView ( )
203+ ) }
204+ { styleSegment === 'active' && (
205+ children . navItemActiveStyle . getPropertyView ( )
206+ ) }
207+ </ Section >
208+ </ div >
75209 ) ;
76210 } )
77211 . build ( ) ;
@@ -82,13 +216,19 @@ NavTmpLayout = withViewFn(NavTmpLayout, (comp) => {
82216 const isViewMode = isUserViewMode ( pathParam ) ;
83217 const [ selectedKey , setSelectedKey ] = useState ( "" ) ;
84218 const items = useMemo ( ( ) => comp . children . items . getView ( ) , [ comp . children . items ] ) ;
85-
219+ const navWidth = useMemo ( ( ) => comp . children . width . getView ( ) , [ comp . children . width ] ) ;
220+ const navMode = useMemo ( ( ) => comp . children . mode . getView ( ) , [ comp . children . mode ] ) ;
221+ const navStyle = useMemo ( ( ) => comp . children . navStyle . getView ( ) , [ comp . children . navStyle ] ) ;
222+ const navItemStyle = useMemo ( ( ) => comp . children . navItemStyle . getView ( ) , [ comp . children . navItemStyle ] ) ;
223+ const navItemHoverStyle = useMemo ( ( ) => comp . children . navItemHoverStyle . getView ( ) , [ comp . children . navItemHoverStyle ] ) ;
224+ const navItemActiveStyle = useMemo ( ( ) => comp . children . navItemActiveStyle . getView ( ) , [ comp . children . navItemActiveStyle ] ) ;
225+ console . log ( navItemActiveStyle ) ;
86226 // filter out hidden. unauthorised items filtered by server
87227 const filterItem = useCallback ( ( item : LayoutMenuItemComp ) : boolean => {
88228 return ! item . children . hidden . getView ( ) ;
89229 } , [ ] ) ;
90230
91- const generateItemKeyRecord = useCallback ( ( items : LayoutMenuItemComp [ ] ) => {
231+ const generateItemKeyRecord = ( items : LayoutMenuItemComp [ ] ) => {
92232 const result : Record < string , LayoutMenuItemComp > = { } ;
93233 items . forEach ( ( item ) => {
94234 const subItems = item . children . items . getView ( ) ;
@@ -98,13 +238,13 @@ NavTmpLayout = withViewFn(NavTmpLayout, (comp) => {
98238 result [ item . getItemKey ( ) ] = item ;
99239 } ) ;
100240 return result ;
101- } , [ items ] )
241+ }
102242
103243 const itemKeyRecord = useMemo ( ( ) => {
104244 return generateItemKeyRecord ( items )
105- } , [ generateItemKeyRecord , items ] ) ;
245+ } , [ items ] ) ;
106246
107- const onMenuItemClick = ( { key} : { key : string } ) => {
247+ const onMenuItemClick = useCallback ( ( { key} : { key : string } ) => {
108248 const itemComp = itemKeyRecord [ key ] ;
109249 const url = [
110250 ALL_APPLICATIONS_URL ,
@@ -113,7 +253,7 @@ NavTmpLayout = withViewFn(NavTmpLayout, (comp) => {
113253 itemComp . getItemKey ( ) ,
114254 ] . join ( "/" ) ;
115255 itemComp . children . action . act ( url ) ;
116- }
256+ } , [ pathParam . applicationId , pathParam . viewMode , itemKeyRecord ] )
117257
118258 const getMenuItem = useCallback (
119259 ( itemComps : LayoutMenuItemComp [ ] ) : MenuProps [ "items" ] => {
@@ -131,7 +271,7 @@ NavTmpLayout = withViewFn(NavTmpLayout, (comp) => {
131271 } ;
132272 } ) ;
133273 } ,
134- [ filterItem ]
274+ [ onMenuItemClick , filterItem ]
135275 ) ;
136276
137277 const menuItems = useMemo ( ( ) => getMenuItem ( items ) , [ items , getMenuItem ] ) ;
@@ -210,15 +350,47 @@ NavTmpLayout = withViewFn(NavTmpLayout, (comp) => {
210350 }
211351 }
212352
353+ const getVerticalMargin = ( margin : string [ ] ) => {
354+ if ( margin . length === 1 ) return `${ margin [ 0 ] } ` ;
355+ if ( margin . length === 2 ) return `(${ margin [ 0 ] } + ${ margin [ 0 ] } )` ;
356+ if ( margin . length === 3 || margin . length === 4 )
357+ return `(${ margin [ 0 ] } + ${ margin [ 2 ] } )` ;
358+
359+ return '0px' ;
360+ }
361+ const getHorizontalMargin = ( margin : string [ ] ) => {
362+ if ( margin . length === 1 ) return `(${ margin [ 0 ] } + ${ margin [ 0 ] } )` ;
363+ if ( margin . length === 2 ) return `(${ margin [ 1 ] } + ${ margin [ 1 ] } )` ;
364+ if ( margin . length === 3 || margin . length === 4 )
365+ return `(${ margin [ 1 ] } + ${ margin [ 3 ] } )` ;
366+
367+ return '0px' ;
368+ }
369+
213370 let content = (
214371 < Layout >
215- < StyledSide theme = "light" width = { DEFAULT_WIDTH } >
216- < AntdMenu
372+ < StyledSide theme = "light" width = { navWidth } >
373+ < StyledMenu
217374 items = { menuItems }
218- mode = "inline"
219- style = { { height : "100%" } }
375+ mode = { navMode }
376+ style = { {
377+ height : `calc(100% - ${ getVerticalMargin ( navStyle . margin . split ( ' ' ) ) } )` ,
378+ width : `calc(100% - ${ getHorizontalMargin ( navStyle . margin . split ( ' ' ) ) } )` ,
379+ borderRadius : navStyle . radius ,
380+ color : navStyle . text ,
381+ margin : navStyle . margin ,
382+ padding : navStyle . padding ,
383+ background : navStyle . background ,
384+ borderRight : `1px solid ${ navStyle . border } ` ,
385+ } }
220386 defaultOpenKeys = { defaultOpenKeys }
221387 selectedKeys = { [ selectedKey ] }
388+ $navItemStyle = { {
389+ width : `calc(100% - ${ getHorizontalMargin ( navItemStyle . margin . split ( ' ' ) ) } )` ,
390+ ...navItemStyle
391+ } }
392+ $navItemHoverStyle = { navItemHoverStyle }
393+ $navItemActiveStyle = { navItemActiveStyle }
222394 />
223395 </ StyledSide >
224396 < MainContent > { pageView } </ MainContent >
0 commit comments