@@ -2,7 +2,7 @@ import { MultiCompBuilder, withDefault, withViewFn } from "comps/generators";
2
2
import { trans } from "i18n" ;
3
3
import { Section , sectionNames } from "components/Section" ;
4
4
import { manualOptionsControl } from "comps/controls/optionsControl" ;
5
- import { BoolCodeControl , StringControl , jsonControl } from "comps/controls/codeControl" ;
5
+ import { BoolCodeControl , StringControl , jsonControl , NumberControl } from "comps/controls/codeControl" ;
6
6
import { IconControl } from "comps/controls/iconControl" ;
7
7
import styled from "styled-components" ;
8
8
import React , { Suspense , useContext , useEffect , useMemo , useState } from "react" ;
@@ -27,6 +27,9 @@ import { check } from "@lowcoder-ee/util/convertUtils";
27
27
import { JSONObject } from "@lowcoder-ee/util/jsonTypes" ;
28
28
import { isEmpty } from "lodash" ;
29
29
import { ThemeContext } from "@lowcoder-ee/comps/utils/themeContext" ;
30
+ import { AlignCenter } from "lowcoder-design" ;
31
+ import { AlignLeft } from "lowcoder-design" ;
32
+ import { AlignRight } from "lowcoder-design" ;
30
33
31
34
const TabBar = React . lazy ( ( ) => import ( "antd-mobile/es/components/tab-bar" ) ) ;
32
35
const TabBarItem = React . lazy ( ( ) =>
@@ -35,8 +38,6 @@ const TabBarItem = React.lazy(() =>
35
38
} ) )
36
39
) ;
37
40
38
- const TabBarHeight = 56 ;
39
- const MaxWidth = 450 ;
40
41
const AppViewContainer = styled . div `
41
42
position: absolute;
42
43
width: 100%;
@@ -46,16 +47,25 @@ const AppViewContainer = styled.div`
46
47
height: 100%;
47
48
` ;
48
49
49
- const TabLayoutViewContainer = styled . div `
50
+ const TabLayoutViewContainer = styled . div < {
51
+ maxWidth : number ;
52
+ tabBarHeight : string ;
53
+ // verticalAlignment: string;
54
+ } > `
50
55
margin: 0 auto;
51
- max-width: ${ MaxWidth } px;
56
+ max-width: ${ ( props ) => props . maxWidth } px;
52
57
position: relative;
53
- height: calc(100% - ${ TabBarHeight } px);
58
+ height: calc(100% - ${ ( props ) => props . tabBarHeight } );
59
+ display: flex;
60
+ flex-direction: column;
54
61
` ;
55
62
56
63
const TabBarWrapper = styled . div < {
57
64
$readOnly : boolean ,
58
65
$canvasBg : string ,
66
+ $tabBarHeight : string ,
67
+ $maxWidth : number ,
68
+ $verticalAlignment : string ;
59
69
} > `
60
70
max-width: inherit;
61
71
background: ${ ( props ) => ( props . $canvasBg ) } ;
@@ -64,35 +74,46 @@ const TabBarWrapper = styled.div<{
64
74
bottom: 0;
65
75
left: 0;
66
76
right: 0;
67
- width: ${ ( props ) => ( props . $readOnly ? "100%" : "418px" ) } ;
77
+ width: ${ ( props ) => props . $readOnly ? "100%" : ` ${ props . $maxWidth - 30 } px` } ;
68
78
z-index: ${ Layers . tabBar } ;
69
79
padding-bottom: env(safe-area-inset-bottom, 0);
70
80
71
81
.adm-tab-bar-wrap {
72
82
overflow: auto;
73
- height: ${ TabBarHeight } px;
83
+ height: ${ ( props ) => props . $tabBarHeight } ;
84
+ display: flex;
85
+ flex-wrap: wrap;
86
+ align-content: ${ ( props ) => props . $verticalAlignment } ;
74
87
}
75
88
` ;
76
89
77
90
const StyledTabBar = styled ( TabBar ) < {
91
+ $showSeparator : boolean ,
78
92
$tabStyle : NavLayoutStyleType ,
79
93
$tabItemStyle : NavLayoutItemStyleType ,
80
94
$tabItemHoverStyle : NavLayoutItemHoverStyleType ,
81
95
$tabItemActiveStyle : NavLayoutItemActiveStyleType ,
96
+ $navIconSize : string ;
82
97
} > `
83
98
width: ${ ( props ) => `calc(100% - ${ props . $tabStyle . margin } - ${ props . $tabStyle . margin } )` } ;
84
99
border: ${ ( props ) => props . $tabStyle . border } ;
85
100
background: ${ ( props ) => props . $tabStyle . background } ;
86
101
border-radius: ${ ( props ) => props . $tabStyle . radius } ;
87
102
margin: ${ ( props ) => props . $tabStyle . margin } ;
88
103
padding: ${ ( props ) => props . $tabStyle . padding } ;
89
-
104
+
105
+ ${ ( props ) => props . $showSeparator ? `
90
106
.adm-tab-bar-item:not(:last-child) {
91
- border-right: ${ ( props ) => props . $tabStyle . border } ;
107
+ border-right: ${ props . $tabStyle . border } ;
92
108
}
109
+ ` : '' }
110
+
93
111
.adm-tab-bar-item-icon, .adm-tab-bar-item-title {
94
112
color: ${ ( props ) => props . $tabStyle . text } ;
95
113
}
114
+ .adm-tab-bar-item-icon, {
115
+ font-size: ${ ( props ) => props . $navIconSize } ;
116
+ }
96
117
97
118
.adm-tab-bar-item {
98
119
background-color: ${ ( props ) => props . $tabItemStyle ?. background } ;
@@ -124,6 +145,22 @@ const defaultStyle = {
124
145
padding : '0px' ,
125
146
}
126
147
148
+ const AlignTop = styled ( AlignLeft ) `
149
+ transform: rotate(90deg);
150
+ ` ;
151
+ const AlignBottom = styled ( AlignRight ) `
152
+ transform: rotate(90deg);
153
+ ` ;
154
+ const AlignVerticalCenter = styled ( AlignCenter ) `
155
+ transform: rotate(90deg);
156
+ ` ;
157
+
158
+ const VerticalAlignmentOptions = [
159
+ { label : < AlignTop /> , value : "flex-start" } ,
160
+ { label : < AlignVerticalCenter /> , value : "stretch" } ,
161
+ { label : < AlignBottom /> , value : "flex-end" } ,
162
+ ] as const ;
163
+
127
164
type MenuItemStyleOptionValue = "normal" | "hover" | "active" ;
128
165
129
166
type JsonItemNode = {
@@ -164,7 +201,14 @@ function convertTreeData(data: any) {
164
201
return data === "" ? [ ] : checkDataNodes ( data ) ?? [ ] ;
165
202
}
166
203
167
- function TabBarView ( props : TabBarProps ) {
204
+ function TabBarView ( props : TabBarProps & {
205
+ tabBarHeight : string ;
206
+ maxWidth : number ;
207
+ verticalAlignment : string ;
208
+ showSeparator : boolean ;
209
+ navIconSize : string ;
210
+ }
211
+ ) {
168
212
const {
169
213
canvasBg, tabStyle, tabItemStyle, tabItemHoverStyle, tabItemActiveStyle,
170
214
} = props ;
@@ -173,6 +217,9 @@ function TabBarView(props: TabBarProps) {
173
217
< TabBarWrapper
174
218
$readOnly = { props . readOnly }
175
219
$canvasBg = { canvasBg }
220
+ $tabBarHeight = { props . tabBarHeight }
221
+ $maxWidth = { props . maxWidth }
222
+ $verticalAlignment = { props . verticalAlignment }
176
223
>
177
224
< StyledTabBar
178
225
onChange = { ( key : string ) => {
@@ -185,6 +232,8 @@ function TabBarView(props: TabBarProps) {
185
232
$tabItemStyle = { tabItemStyle }
186
233
$tabItemHoverStyle = { tabItemHoverStyle }
187
234
$tabItemActiveStyle = { tabItemActiveStyle }
235
+ $showSeparator = { props . showSeparator }
236
+ $navIconSize = { props . navIconSize }
188
237
>
189
238
{ props . tabs . map ( ( tab ) => {
190
239
return (
@@ -249,6 +298,11 @@ let MobileTabLayoutTmp = (function () {
249
298
initOptions : [ ] ,
250
299
} ) ,
251
300
backgroundImage : withDefault ( StringControl , "" ) ,
301
+ tabBarHeight : withDefault ( StringControl , "56px" ) ,
302
+ navIconSize : withDefault ( StringControl , "32px" ) ,
303
+ maxWidth : withDefault ( NumberControl , 450 ) ,
304
+ verticalAlignment : dropdownControl ( VerticalAlignmentOptions , "stretch" ) ,
305
+ showSeparator : withDefault ( BoolCodeControl , true ) ,
252
306
navStyle : withDefault ( styleControl ( NavLayoutStyle ) , defaultStyle ) ,
253
307
navItemStyle : withDefault ( styleControl ( NavLayoutItemStyle ) , defaultStyle ) ,
254
308
navItemHoverStyle : withDefault ( styleControl ( NavLayoutItemHoverStyle ) , { } ) ,
@@ -279,6 +333,13 @@ let MobileTabLayoutTmp = (function () {
279
333
label : `Background Image` ,
280
334
placeholder : 'https://temp.im/350x400' ,
281
335
} ) }
336
+ { children . showSeparator . propertyView ( { label : trans ( "navLayout.mobileNavVerticalShowSeparator" ) } ) }
337
+ { children . tabBarHeight . propertyView ( { label : trans ( "navLayout.mobileNavBarHeight" ) } ) }
338
+ { children . navIconSize . propertyView ( { label : trans ( "navLayout.mobileNavIconSize" ) } ) }
339
+ { children . maxWidth . propertyView ( { label : trans ( "navLayout.mobileNavVerticalMaxWidth" ) } ) }
340
+ { children . verticalAlignment . propertyView (
341
+ { label : trans ( "navLayout.mobileNavVerticalOrientation" ) , radioButton : true }
342
+ ) }
282
343
</ Section >
283
344
< Section name = { trans ( "navLayout.navStyle" ) } >
284
345
{ children . navStyle . getPropertyView ( ) }
@@ -318,6 +379,11 @@ MobileTabLayoutTmp = withViewFn(MobileTabLayoutTmp, (comp) => {
318
379
const backgroundImage = comp . children . backgroundImage . getView ( ) ;
319
380
const jsonItems = comp . children . jsonItems . getView ( ) ;
320
381
const dataOptionType = comp . children . dataOptionType . getView ( ) ;
382
+ const tabBarHeight = comp . children . tabBarHeight . getView ( ) ;
383
+ const navIconSize = comp . children . navIconSize . getView ( ) ;
384
+ const maxWidth = comp . children . maxWidth . getView ( ) ;
385
+ const verticalAlignment = comp . children . verticalAlignment . getView ( ) ;
386
+ const showSeparator = comp . children . showSeparator . getView ( ) ;
321
387
const bgColor = ( useContext ( ThemeContext ) ?. theme || defaultTheme ) . canvas ;
322
388
323
389
useEffect ( ( ) => {
@@ -384,20 +450,25 @@ MobileTabLayoutTmp = withViewFn(MobileTabLayoutTmp, (comp) => {
384
450
tabItemStyle = { navItemStyle }
385
451
tabItemHoverStyle = { navItemHoverStyle }
386
452
tabItemActiveStyle = { navItemActiveStyle }
453
+ tabBarHeight = { tabBarHeight }
454
+ navIconSize = { navIconSize }
455
+ maxWidth = { maxWidth }
456
+ verticalAlignment = { verticalAlignment }
457
+ showSeparator = { showSeparator }
387
458
/>
388
459
) ;
389
460
390
461
if ( readOnly ) {
391
462
return (
392
- < TabLayoutViewContainer >
463
+ < TabLayoutViewContainer maxWidth = { maxWidth } tabBarHeight = { tabBarHeight } >
393
464
< AppViewContainer > { appView } </ AppViewContainer >
394
465
{ tabBarView }
395
466
</ TabLayoutViewContainer >
396
467
) ;
397
468
}
398
469
399
470
return (
400
- < CanvasContainer $maxWidth = { MaxWidth } id = { CanvasContainerID } >
471
+ < CanvasContainer $maxWidth = { maxWidth } id = { CanvasContainerID } >
401
472
< EditorContainer > { appView } </ EditorContainer >
402
473
{ tabBarView }
403
474
</ CanvasContainer >
0 commit comments