1
- import { Layout , Menu as AntdMenu , MenuProps } from "antd" ;
1
+ import { Layout , Menu as AntdMenu , MenuProps , Segmented } from "antd" ;
2
2
import MainContent from "components/layout/MainContent" ;
3
3
import { LayoutMenuItemComp , LayoutMenuItemListComp } from "comps/comps/layout/layoutMenuItemComp" ;
4
4
import { menuPropertyView } from "comps/comps/navComp/components/MenuItemList" ;
@@ -8,17 +8,47 @@ import { withDispatchHook } from "comps/generators/withDispatchHook";
8
8
import { NameAndExposingInfo } from "comps/utils/exposingTypes" ;
9
9
import { ALL_APPLICATIONS_URL } from "constants/routesURL" ;
10
10
import { TopHeaderHeight } from "constants/style" ;
11
- import { Section , sectionNames } from "lowcoder-design" ;
11
+ import { Section , controlItem , sectionNames } from "lowcoder-design" ;
12
12
import { trans } from "i18n" ;
13
13
import { EditorContainer , EmptyContent } from "pages/common/styledComponent" ;
14
14
import { useCallback , useEffect , useMemo , useState } from "react" ;
15
- import styled from "styled-components" ;
15
+ import styled , { css } from "styled-components" ;
16
16
import { isUserViewMode , useAppPathParam } from "util/hooks" ;
17
17
import { StringControl } from "comps/controls/codeControl" ;
18
18
import { 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" ;
20
29
21
30
const 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
+ ]
22
52
23
53
const StyledSide = styled ( Layout . Sider ) `
24
54
max-height: calc(100vh - ${ TopHeaderHeight } );
@@ -44,34 +74,138 @@ const ContentWrapper = styled.div`
44
74
}
45
75
` ;
46
76
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
+
47
151
let NavTmpLayout = ( function ( ) {
48
152
const childrenMap = {
49
153
items : withDefault ( LayoutMenuItemListComp , [
50
154
{
51
155
label : trans ( "menuItem" ) + " 1" ,
52
156
} ,
53
157
] ) ,
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 ) , { } ) ,
56
164
} ;
57
165
return new MultiCompBuilder ( childrenMap , ( props ) => {
58
166
return null ;
59
167
} )
60
168
. setPropertyViewFn ( ( children ) => {
169
+ const [ styleSegment , setStyleSegment ] = useState ( 'normal' )
170
+
61
171
return (
62
- < >
172
+ < div style = { { overflowY : 'auto' } } >
63
173
< Section name = { trans ( "menu" ) } > { menuPropertyView ( children . items ) } </ Section >
64
174
< Section name = { sectionNames . layout } >
65
175
{ children . width . propertyView ( {
66
- label : trans ( "drawer .width" ) ,
67
- tooltip : trans ( "drawer .widthTooltip" ) ,
176
+ label : trans ( "navLayout .width" ) ,
177
+ tooltip : trans ( "navLayout .widthTooltip" ) ,
68
178
placeholder : DEFAULT_WIDTH + "" ,
69
- } ) }
179
+ } ) }
180
+ { children . mode . propertyView ( {
181
+ label : trans ( "labelProp.position" ) ,
182
+ radioButton : true
183
+ } ) }
70
184
</ Section >
71
- < Section name = { sectionNames . style } >
72
- { children . style . getPropertyView ( ) }
185
+ < Section name = { trans ( "navLayout.navStyle" ) } >
186
+ { children . navStyle . getPropertyView ( ) }
73
187
</ 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 >
75
209
) ;
76
210
} )
77
211
. build ( ) ;
@@ -82,13 +216,19 @@ NavTmpLayout = withViewFn(NavTmpLayout, (comp) => {
82
216
const isViewMode = isUserViewMode ( pathParam ) ;
83
217
const [ selectedKey , setSelectedKey ] = useState ( "" ) ;
84
218
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 ) ;
86
226
// filter out hidden. unauthorised items filtered by server
87
227
const filterItem = useCallback ( ( item : LayoutMenuItemComp ) : boolean => {
88
228
return ! item . children . hidden . getView ( ) ;
89
229
} , [ ] ) ;
90
230
91
- const generateItemKeyRecord = useCallback ( ( items : LayoutMenuItemComp [ ] ) => {
231
+ const generateItemKeyRecord = ( items : LayoutMenuItemComp [ ] ) => {
92
232
const result : Record < string , LayoutMenuItemComp > = { } ;
93
233
items . forEach ( ( item ) => {
94
234
const subItems = item . children . items . getView ( ) ;
@@ -98,13 +238,13 @@ NavTmpLayout = withViewFn(NavTmpLayout, (comp) => {
98
238
result [ item . getItemKey ( ) ] = item ;
99
239
} ) ;
100
240
return result ;
101
- } , [ items ] )
241
+ }
102
242
103
243
const itemKeyRecord = useMemo ( ( ) => {
104
244
return generateItemKeyRecord ( items )
105
- } , [ generateItemKeyRecord , items ] ) ;
245
+ } , [ items ] ) ;
106
246
107
- const onMenuItemClick = ( { key} : { key : string } ) => {
247
+ const onMenuItemClick = useCallback ( ( { key} : { key : string } ) => {
108
248
const itemComp = itemKeyRecord [ key ] ;
109
249
const url = [
110
250
ALL_APPLICATIONS_URL ,
@@ -113,7 +253,7 @@ NavTmpLayout = withViewFn(NavTmpLayout, (comp) => {
113
253
itemComp . getItemKey ( ) ,
114
254
] . join ( "/" ) ;
115
255
itemComp . children . action . act ( url ) ;
116
- }
256
+ } , [ pathParam . applicationId , pathParam . viewMode , itemKeyRecord ] )
117
257
118
258
const getMenuItem = useCallback (
119
259
( itemComps : LayoutMenuItemComp [ ] ) : MenuProps [ "items" ] => {
@@ -131,7 +271,7 @@ NavTmpLayout = withViewFn(NavTmpLayout, (comp) => {
131
271
} ;
132
272
} ) ;
133
273
} ,
134
- [ filterItem ]
274
+ [ onMenuItemClick , filterItem ]
135
275
) ;
136
276
137
277
const menuItems = useMemo ( ( ) => getMenuItem ( items ) , [ items , getMenuItem ] ) ;
@@ -210,15 +350,47 @@ NavTmpLayout = withViewFn(NavTmpLayout, (comp) => {
210
350
}
211
351
}
212
352
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
+
213
370
let content = (
214
371
< Layout >
215
- < StyledSide theme = "light" width = { DEFAULT_WIDTH } >
216
- < AntdMenu
372
+ < StyledSide theme = "light" width = { navWidth } >
373
+ < StyledMenu
217
374
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
+ } }
220
386
defaultOpenKeys = { defaultOpenKeys }
221
387
selectedKeys = { [ selectedKey ] }
388
+ $navItemStyle = { {
389
+ width : `calc(100% - ${ getHorizontalMargin ( navItemStyle . margin . split ( ' ' ) ) } )` ,
390
+ ...navItemStyle
391
+ } }
392
+ $navItemHoverStyle = { navItemHoverStyle }
393
+ $navItemActiveStyle = { navItemActiveStyle }
222
394
/>
223
395
</ StyledSide >
224
396
< MainContent > { pageView } </ MainContent >
0 commit comments