1
- import { MultiCompBuilder , withViewFn } from "comps/generators" ;
1
+ import { MultiCompBuilder , withDefault , withViewFn } from "comps/generators" ;
2
2
import { trans } from "i18n" ;
3
- import { Section } from "components/Section" ;
3
+ import { Section , sectionNames } from "components/Section" ;
4
4
import { manualOptionsControl } from "comps/controls/optionsControl" ;
5
- import { BoolCodeControl , StringControl } from "comps/controls/codeControl" ;
5
+ import { BoolCodeControl , StringControl , jsonControl } from "comps/controls/codeControl" ;
6
6
import { IconControl } from "comps/controls/iconControl" ;
7
7
import styled from "styled-components" ;
8
- import React , { Suspense , useContext , useState } from "react" ;
8
+ import React , { Suspense , useContext , useMemo , useState } from "react" ;
9
9
import { registerLayoutMap } from "comps/comps/uiComp" ;
10
10
import { AppSelectComp } from "comps/comps/layout/appSelectComp" ;
11
11
import { NameAndExposingInfo } from "comps/utils/exposingTypes" ;
@@ -17,6 +17,18 @@ import { Layers } from "constants/Layers";
17
17
import { ExternalEditorContext } from "util/context/ExternalEditorContext" ;
18
18
import { default as Skeleton } from "antd/es/skeleton" ;
19
19
import { hiddenPropertyView } from "comps/utils/propertyUtils" ;
20
+ import { dropdownControl } from "@lowcoder-ee/comps/controls/dropdownControl" ;
21
+ import { DataOption , DataOptionType , ModeOptions , jsonMenuItems , menuItemStyleOptions , mobileNavJsonMenuItems } from "./navLayoutConstants" ;
22
+ import { styleControl } from "@lowcoder-ee/comps/controls/styleControl" ;
23
+ import { NavLayoutItemActiveStyle , NavLayoutItemHoverStyle , NavLayoutItemStyle , NavLayoutStyle } from "@lowcoder-ee/comps/controls/styleControlConstants" ;
24
+ import Segmented from "antd/es/segmented" ;
25
+ import { controlItem } from "components/control" ;
26
+ import { MenuItemNode } from "./navLayout" ;
27
+ import { check } from "@lowcoder-ee/util/convertUtils" ;
28
+ import { JSONObject } from "@lowcoder-ee/util/jsonTypes" ;
29
+ import { getCompContainer , useCompContainer , useCompInstance } from "@lowcoder-ee/comps/utils/useCompInstance" ;
30
+ import { ModuleComp } from "../moduleComp/moduleComp" ;
31
+ import { evalAndReduceWithExposing } from "comps/utils" ;
20
32
21
33
const TabBar = React . lazy ( ( ) => import ( "antd-mobile/es/components/tab-bar" ) ) ;
22
34
const TabBarItem = React . lazy ( ( ) =>
@@ -61,6 +73,21 @@ const TabBarWrapper = styled.div<{ $readOnly: boolean }>`
61
73
}
62
74
` ;
63
75
76
+ const defaultStyle = {
77
+ radius : '0px' ,
78
+ margin : '0px' ,
79
+ padding : '0px' ,
80
+ }
81
+
82
+ type MenuItemStyleOptionValue = "normal" | "hover" | "active" ;
83
+
84
+ type JsonItemNode = {
85
+ label : string ;
86
+ hidden ?: boolean ;
87
+ icon ?: any ;
88
+ app ?: JSONObject ,
89
+ }
90
+
64
91
type TabBarProps = {
65
92
tabs : Array < {
66
93
title : string ;
@@ -72,7 +99,23 @@ type TabBarProps = {
72
99
readOnly : boolean ;
73
100
} ;
74
101
102
+ function checkDataNodes ( value : any , key ?: string ) : JsonItemNode [ ] | undefined {
103
+ return check ( value , [ "array" , "undefined" ] , key , ( node , k ) => {
104
+ check ( node , [ "object" ] , k ) ;
105
+ check ( node [ "label" ] , [ "string" ] , "label" ) ;
106
+ check ( node [ "hidden" ] , [ "boolean" , "undefined" ] , "hidden" ) ;
107
+ check ( node [ "icon" ] , [ "string" , "undefined" ] , "icon" ) ;
108
+ check ( node [ "app" ] , [ "object" , "undefined" ] , "app" ) ;
109
+ return node ;
110
+ } ) ;
111
+ }
112
+
113
+ function convertTreeData ( data : any ) {
114
+ return data === "" ? [ ] : checkDataNodes ( data ) ?? [ ] ;
115
+ }
116
+
75
117
function TabBarView ( props : TabBarProps ) {
118
+ console . log ( props ) ;
76
119
return (
77
120
< Suspense fallback = { < Skeleton /> } >
78
121
< TabBarWrapper $readOnly = { props . readOnly } >
@@ -126,6 +169,8 @@ const TabOptionComp = (function () {
126
169
127
170
let MobileTabLayoutTmp = ( function ( ) {
128
171
const childrenMap = {
172
+ dataOptionType : dropdownControl ( DataOptionType , DataOption . Manual ) ,
173
+ jsonItems : jsonControl < JsonItemNode [ ] > ( convertTreeData , mobileNavJsonMenuItems ) ,
129
174
tabs : manualOptionsControl ( TabOptionComp , {
130
175
initOptions : [
131
176
{
@@ -142,17 +187,67 @@ let MobileTabLayoutTmp = (function () {
142
187
} ,
143
188
] ,
144
189
} ) ,
190
+ backgroundImage : withDefault ( StringControl , "" ) ,
191
+ mode : dropdownControl ( ModeOptions , "inline" ) ,
192
+ navStyle : withDefault ( styleControl ( NavLayoutStyle ) , defaultStyle ) ,
193
+ navItemStyle : withDefault ( styleControl ( NavLayoutItemStyle ) , defaultStyle ) ,
194
+ navItemHoverStyle : withDefault ( styleControl ( NavLayoutItemHoverStyle ) , { } ) ,
195
+ navItemActiveStyle : withDefault ( styleControl ( NavLayoutItemActiveStyle ) , { } ) ,
145
196
} ;
146
197
return new MultiCompBuilder ( childrenMap , ( props ) => {
147
198
return null ;
148
199
} )
149
200
. setPropertyViewFn ( ( children ) => {
201
+ const [ styleSegment , setStyleSegment ] = useState ( 'normal' )
150
202
return (
151
- < >
203
+ < div style = { { overflowY : 'auto' } } >
152
204
< Section name = { trans ( "aggregation.tabBar" ) } >
153
- { children . tabs . propertyView ( { } ) }
205
+ { children . dataOptionType . propertyView ( {
206
+ radioButton : true ,
207
+ type : "oneline" ,
208
+ } ) }
209
+ { /* {children.tabs.propertyView({}) } */ }
210
+ {
211
+ children . dataOptionType . getView ( ) === DataOption . Manual
212
+ ? children . tabs . propertyView ( { } )
213
+ : children . jsonItems . propertyView ( {
214
+ label : "Json Data" ,
215
+ } )
216
+ }
154
217
</ Section >
155
- </ >
218
+ < Section name = { sectionNames . layout } >
219
+ { children . mode . propertyView ( {
220
+ label : trans ( "labelProp.position" ) ,
221
+ radioButton : true
222
+ } ) }
223
+ { children . backgroundImage . propertyView ( {
224
+ label : `Background Image` ,
225
+ placeholder : 'https://temp.im/350x400' ,
226
+ } ) }
227
+ </ Section >
228
+ < Section name = { trans ( "navLayout.navStyle" ) } >
229
+ { children . navStyle . getPropertyView ( ) }
230
+ </ Section >
231
+ < Section name = { trans ( "navLayout.navItemStyle" ) } >
232
+ { controlItem ( { } , (
233
+ < Segmented
234
+ block
235
+ options = { menuItemStyleOptions }
236
+ value = { styleSegment }
237
+ onChange = { ( k ) => setStyleSegment ( k as MenuItemStyleOptionValue ) }
238
+ />
239
+ ) ) }
240
+ { styleSegment === 'normal' && (
241
+ children . navItemStyle . getPropertyView ( )
242
+ ) }
243
+ { styleSegment === 'hover' && (
244
+ children . navItemHoverStyle . getPropertyView ( )
245
+ ) }
246
+ { styleSegment === 'active' && (
247
+ children . navItemActiveStyle . getPropertyView ( )
248
+ ) }
249
+ </ Section >
250
+ </ div >
156
251
) ;
157
252
} )
158
253
. build ( ) ;
@@ -161,20 +256,56 @@ let MobileTabLayoutTmp = (function () {
161
256
MobileTabLayoutTmp = withViewFn ( MobileTabLayoutTmp , ( comp ) => {
162
257
const [ tabIndex , setTabIndex ] = useState ( 0 ) ;
163
258
const { readOnly } = useContext ( ExternalEditorContext ) ;
164
- const tabViews = (
165
- comp . children . tabs . children . manual . getView ( ) as unknown as Array <
166
- ConstructorToComp < typeof TabOptionComp >
167
- >
168
- ) . filter ( ( tab ) => ! tab . children . hidden . getView ( ) ) ;
169
- const currentTab = tabViews [ tabIndex ] ;
170
- const appView = ( currentTab &&
171
- currentTab . children . app . getAppId ( ) &&
172
- currentTab . children . app . getView ( ) ) || (
173
- < EmptyContent
174
- text = { readOnly ? "" : trans ( "aggregation.emptyTabTooltip" ) }
175
- style = { { height : "100%" , backgroundColor : "white" } }
176
- />
177
- ) ;
259
+ const tabs = comp . children . tabs . getView ( ) ;
260
+ const navMode = comp . children . mode . getView ( ) ;
261
+ const navStyle = comp . children . navStyle . getView ( ) ;
262
+ const navItemStyle = comp . children . navItemStyle . getView ( ) ;
263
+ const navItemHoverStyle = comp . children . navItemHoverStyle . getView ( ) ;
264
+ const navItemActiveStyle = comp . children . navItemActiveStyle . getView ( ) ;
265
+ const backgroundImage = comp . children . backgroundImage . getView ( ) ;
266
+ const jsonItems = comp . children . jsonItems . getView ( ) ;
267
+ const dataOptionType = comp . children . dataOptionType . getView ( ) ;
268
+ // const tabViews = (
269
+ // comp.children.tabs.children.manual.getView() as unknown as Array<
270
+ // ConstructorToComp<typeof TabOptionComp>
271
+ // >
272
+ // ).filter((tab) => !tab.children.hidden.getView());
273
+ const tabViews = useMemo ( ( ) => {
274
+ if ( dataOptionType === DataOption . Manual ) {
275
+ return ( comp . children . tabs . children . manual . getView ( ) as unknown as Array <
276
+ ConstructorToComp < typeof TabOptionComp >
277
+ >
278
+ ) . filter ( ( tab ) => ! tab . children . hidden . getView ( ) ) ;
279
+ }
280
+ return jsonItems . filter ( item => ! Boolean ( item . hidden ) ) . map ( ( item ) => {
281
+ const container = getCompContainer ( {
282
+ Comp : TabOptionComp ,
283
+ initialValue : {
284
+ ...item ,
285
+ }
286
+ } )
287
+ if ( container ) {
288
+ container . initialized = true ;
289
+ container . comp = evalAndReduceWithExposing ( container . comp ) ;
290
+ }
291
+ return container ! . comp as unknown as ConstructorToComp < typeof TabOptionComp >
292
+ } )
293
+ } , [ dataOptionType ] )
294
+
295
+ console . log ( tabViews ) ;
296
+
297
+ const appView = useMemo ( ( ) => {
298
+ const currentTab = tabViews [ tabIndex ] ;
299
+
300
+ return ( currentTab &&
301
+ currentTab . children . app . getAppId ( ) &&
302
+ currentTab . children . app . getView ( ) ) || (
303
+ < EmptyContent
304
+ text = { readOnly ? "" : trans ( "aggregation.emptyTabTooltip" ) }
305
+ style = { { height : "100%" , backgroundColor : "white" } }
306
+ />
307
+ )
308
+ } , [ tabIndex ] ) ;
178
309
179
310
const tabBarView = (
180
311
< TabBarView
0 commit comments