Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit496c100

Browse files
author
FalkWolsky
committed
SplitLayout Component
1 parent15a98e8 commit496c100

File tree

13 files changed

+328
-64
lines changed

13 files changed

+328
-64
lines changed

‎client/packages/lowcoder/src/comps/comps/splitLayout/splitLayout.tsx‎

Lines changed: 231 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -3,109 +3,155 @@ import { Splitter } from "antd";
33
importstyledfrom"styled-components";
44
import{DispatchType,RecordConstructorToView,wrapDispatch}from"lowcoder-core";
55
import{CompAction,CompActionTypes,deleteCompAction,wrapChildAction}from"lowcoder-core";
6-
import{ColumnOptionControl}from"comps/controls/optionsControl";
7-
import{NumberControl}from"comps/controls/codeControl";
6+
import{SplitColumnOptionControl}from"comps/controls/optionsControl";
7+
import{NumberControl,StringControl}from"comps/controls/codeControl";
88
import{BoolControl}from"comps/controls/boolControl";
9+
import{dropdownControl}from"comps/controls/dropdownControl";
910
import{styleControl}from"comps/controls/styleControl";
10-
import{SplitLayoutColStyle,SplitLayoutColStyleType,AnimationStyle}from"comps/controls/styleControlConstants";
11+
import{SplitLayoutColStyle,SplitLayoutRowStyle,SplitLayoutRowStyleType,SplitLayoutColStyleType,AnimationStyle,heightCalculator}from"comps/controls/styleControlConstants";
1112
import{sameTypeMap,UICompBuilder,withDefault}from"comps/generators";
1213
import{addMapChildAction}from"comps/generators/sameTypeMap";
1314
import{BackgroundColorContext}from"comps/utils/backgroundColorContext";
14-
import{Section,sectionNames}from"lowcoder-design";
15+
import{Section,sectionNames}from"lowcoder-design";
1516
import{trans}from"i18n";
16-
import{SimpleContainerComp}from"../containerBase/simpleContainerComp";
1717
import{ContainerBaseProps,gridItemCompToGridItems,InnerGrid}from"../containerComp/containerView";
18+
import{useContext}from"react";
19+
import{EditorContext}from"comps/editorState";
20+
21+
import{disabledPropertyView,hiddenPropertyView}from"comps/utils/propertyUtils";
1822
import{DisabledContext}from"comps/generators/uiCompBuilder";
19-
import{useScreenInfo}from"../../hooks/screenInfoComp";
23+
import{JSONObject,JSONValue}from"util/jsonTypes";
24+
import{IContainer}from"../containerBase/iContainer";
25+
import{SimpleContainerComp}from"../containerBase/simpleContainerComp";
26+
import{CompTree,mergeCompTrees}from"../containerBase/utils";
27+
import{NameGenerator}from"comps/utils";
28+
import{AutoHeightControl}from"comps/controls/autoHeightControl";
29+
import{messageInstance}from"lowcoder-design/src/components/GlobalInstances";
30+
import{NameConfigHidden,withExposingConfigs}from"comps/generators/withExposing";
31+
importSliderControlfrom"@lowcoder-ee/comps/controls/sliderControl";
32+
import{getBackgroundStyle}from"@lowcoder-ee/util/styleUtils";
33+
import_from"lodash";
2034

21-
constSplitPanelWrapper=styled(Splitter.Panel)<{$collapsible:boolean}>`
22-
flex-grow: 1;
23-
${(props)=>props.$collapsible&&`min-width: 50px;`}
35+
import{
36+
HorizontalIcon,
37+
VerticalIcon,
38+
}from"lowcoder-design/src/icons";
39+
import{BackgroundColor}from"@lowcoder-ee/constants/style";
40+
41+
constSplitPanelWrapper=styled(Splitter.Panel)<{}>`
2442
`;
2543

26-
exportinterfaceSplitterLayoutTypes{
27-
orientation:"horizontal"|"vertical";
28-
}
44+
constSplitterWrapper=styled.div<{$style:SplitLayoutRowStyleType}>`
45+
border-radius:${(props)=>props.$style?.radius||"0px"};
46+
border-width:${(props)=>props.$style?.borderWidth||"0px"};
47+
border-color:${(props)=>props.$style?.border||"transparent"};
48+
border-style:${(props)=>props.$style?.borderStyle||"solid"};
49+
margin:${(props)=>props.$style?.margin||"0px"};
50+
padding:${(props)=>props.$style?.padding||"0px"};
51+
${(props)=>(props.$style ?getBackgroundStyle(props.$style) :"")}
52+
`;
2953

30-
/*
54+
constOrientationOptions=[
55+
{
56+
label:<HorizontalIcon/>,
57+
value:"horizontal",
58+
},
59+
{
60+
label:<VerticalIcon/>,
61+
value:"vertical",
62+
},
63+
]asconst;
3164

3265
constchildrenMap={
3366
disabled:BoolControl,
34-
columns:ColumnOptionControl,
67+
columns:SplitColumnOptionControl,
3568
containers:withDefault(sameTypeMap(SimpleContainerComp),{
3669
0:{view:{},layout:{}},
3770
1:{view:{},layout:{}},
3871
}),
39-
collapsiblePanels: BoolControl,
40-
orientation: withDefault(ColumnOptionControl, "horizontal"),
41-
panelCount: withDefault(NumberControl, 2),
72+
autoHeight:AutoHeightControl,
73+
horizontalGridCells:SliderControl,
74+
verticalGridCells:SliderControl,
75+
orientation:dropdownControl(OrientationOptions,"horizontal"),
76+
matchColumnsHeight:withDefault(BoolControl,true),
4277
columnStyle:styleControl(SplitLayoutColStyle,"columnStyle"),
78+
bodyStyle:styleControl(SplitLayoutRowStyle,'bodyStyle'),
4379
animationStyle:styleControl(AnimationStyle,"animationStyle"),
80+
mainScrollbar:withDefault(BoolControl,false),
4481
};
4582

4683
typeViewProps=RecordConstructorToView<typeofchildrenMap>;
4784
typeSplitLayoutProps=ViewProps&{dispatch:DispatchType};
85+
4886
typeColumnContainerProps=Omit<ContainerBaseProps,"style">&{
4987
style:SplitLayoutColStyleType;
88+
matchColumnsHeight:boolean;
89+
backgroundColor:string;
90+
backgroundImage:string;
91+
padding:string;
92+
orientation:string;
93+
margin:string;
5094
};
5195

5296
constColumnContainer=(props:ColumnContainerProps)=>{
5397
return(
5498
<InnerGrid
5599
{...props}
56-
emptyRows={15}
57100
radius={props.style.radius}
58-
style={props.style}
101+
bgColor={props.backgroundColor}
102+
style={{
103+
...props.style,
104+
height:props.orientation==="horizontal"
105+
?(props.matchColumnsHeight ?heightCalculator(props.margin) :"auto")
106+
:(props.autoHeight ?"100%" :"auto"),
107+
}}
59108
/>
60109
);
61110
};
62111

63112
constSplitLayout=(props:SplitLayoutProps)=>{
64-
const screenInfo = useScreenInfo();
65-
const containerRef = useRef<HTMLDivElement | null>(null);
66-
const [componentWidth, setComponentWidth] = useState<number | null>(null);
67-
68-
let { columns, containers, dispatch, collapsiblePanels, orientation, panelCount, columnStyle } = props;
69-
70-
useEffect(() => {
71-
if (!containerRef.current) return;
72-
const resizeObserver = new ResizeObserver((entries) => {
73-
for (let entry of entries) {
74-
setComponentWidth(entry.contentRect.width);
75-
}
76-
});
77-
78-
resizeObserver.observe(containerRef.current);
79-
return () => resizeObserver.disconnect();
80-
}, []);
81113

82114
return(
83-
<BackgroundColorContext.Provider value={props.style?.background}>
115+
<BackgroundColorContext.Providervalue={props.columnStyle.background}>
84116
<DisabledContext.Providervalue={props.disabled}>
85-
<div ref={containerRef} style={{ height: "100%" }}>
86-
<Splitter layout={orientation}>
87-
{Array.from({ length: panelCount }, (_, index) => {
88-
const id = String(index);
89-
const childDispatch = wrapDispatch(wrapDispatch(dispatch, "containers"), id);
90-
if (!containers[id]) return null;
91-
const containerProps = containers[id].children;
92-
117+
<SplitterWrapper$style={props.bodyStyle}>
118+
<Splitterstyle={{overflow:props.mainScrollbar ?"auto" :"hidden"}}layout={props.orientation}>
119+
{props.columns.map((col,index)=>{
120+
constid=String(col.id);
121+
constchildDispatch=wrapDispatch(wrapDispatch(props.dispatch,"containers"),id);
122+
constcontainerProps=props.containers[id]?.children;
93123
return(
94-
<SplitPanelWrapper key={id} $collapsible={collapsiblePanels}>
124+
<SplitPanelWrapper
125+
key={id}
126+
collapsible={col.collapsible}
127+
{...(col.minWidth!==undefined ?{min:col.minWidth} :{})}
128+
{...(col.maxWidth!==undefined ?{max:col.maxWidth} :{})}
129+
{...(col.width!==undefined ?{defaultSize:col.width} :{})}
130+
>
95131
<ColumnContainer
96132
layout={containerProps.layout.getView()}
97133
items={gridItemCompToGridItems(containerProps.items.getView())}
98134
positionParams={containerProps.positionParams.getView()}
99135
dispatch={childDispatch}
100-
style={columnStyle}
136+
style={props.columnStyle}
137+
backgroundColor={col.backgroundColor}
138+
backgroundImage={col.backgroundImage}
139+
padding={col.padding}
140+
autoHeight={props.autoHeight}
141+
horizontalGridCells={props.horizontalGridCells}
142+
emptyRows={props.verticalGridCells}
143+
matchColumnsHeight={props.matchColumnsHeight}
144+
orientation={props.orientation}
145+
margin={props.columnStyle.margin}
101146
/>
102147
</SplitPanelWrapper>
103148
);
104149
})}
105150
</Splitter>
106-
</div>
151+
</SplitterWrapper>
107152
</DisabledContext.Provider>
108153
</BackgroundColorContext.Provider>
154+
109155
);
110156
};
111157

@@ -116,27 +162,151 @@ export const SplitLayoutBaseComp = (function () {
116162
<Sectionname={sectionNames.basic}>
117163
{children.columns.propertyView({title:trans("splitLayout.column")})}
118164
</Section>
119-
<Section name={sectionNames.layout}>
120-
{children.panelCount.propertyView({ label: trans("splitLayout.panelCount") })}
121-
{children.collapsiblePanels.propertyView({ label: trans("splitLayout.collapsiblePanels") })}
122-
{children.orientation.propertyView({ label: trans("splitLayout.orientation") })}
123-
</Section>
124-
<Section name={sectionNames.style}>
125-
{children.columnStyle.getPropertyView()}
126-
{children.animationStyle.getPropertyView()}
127-
</Section>
165+
166+
{(useContext(EditorContext).editorModeStatus==="logic"||useContext(EditorContext).editorModeStatus==="both")&&(
167+
<Sectionname={sectionNames.interaction}>
168+
{disabledPropertyView(children)}
169+
{hiddenPropertyView(children)}
170+
</Section>
171+
)}
172+
{["layout","both"].includes(useContext(EditorContext).editorModeStatus)&&(
173+
<>
174+
<Sectionname={sectionNames.layout}>
175+
{children.orientation.propertyView({
176+
label:trans("splitLayout.orientation"),
177+
radioButton:true,
178+
tooltip:trans("splitLayout.orientationTooltip"),
179+
})}
180+
{children.autoHeight.getPropertyView()}
181+
{(!children.autoHeight.getView())&&children.mainScrollbar.propertyView({
182+
label:trans("prop.mainScrollbar")
183+
})}
184+
{(children.orientation.getView()=="horizontal")&&
185+
children.matchColumnsHeight.propertyView({label:trans("splitLayout.matchColumnsHeight")}
186+
)}
187+
{children.horizontalGridCells.propertyView({
188+
label:trans('prop.horizontalGridCells'),
189+
})}
190+
{children.verticalGridCells.propertyView({
191+
label:trans('prop.verticalGridCells'),
192+
})}
193+
</Section>
194+
<Sectionname={sectionNames.bodyStyle}>
195+
{children.bodyStyle.getPropertyView()}
196+
</Section>
197+
<Sectionname={sectionNames.detailStyle}>
198+
{children.columnStyle.getPropertyView()}
199+
</Section>
200+
<Sectionname={sectionNames.animationStyle}hasTooltip={true}>
201+
{children.animationStyle.getPropertyView()}
202+
</Section>
203+
</>
204+
)}
128205
</>
129206
))
130207
.build();
131208
})();
132209

133-
class SplitLayoutImplComp extends SplitLayoutBaseComp {
210+
classSplitLayoutImplCompextendsSplitLayoutBaseCompimplementsIContainer{
211+
privatesyncContainers(): this{
212+
constcolumns=this.children.columns.getView();
213+
constids:Set<string>=newSet(columns.map((column)=>String(column.id)));
214+
letcontainers=this.children.containers.getView();
215+
// delete
216+
constactions:CompAction[]=[];
217+
Object.keys(containers).forEach((id)=>{
218+
if(!ids.has(id)){
219+
// log.debug("syncContainers delete. ids=", ids, " id=", id);
220+
actions.push(wrapChildAction("containers",wrapChildAction(id,deleteCompAction())));
221+
}
222+
});
223+
// new
224+
ids.forEach((id)=>{
225+
if(!containers.hasOwnProperty(id)){
226+
// log.debug("syncContainers new containers: ", containers, " id: ", id);
227+
actions.push(
228+
wrapChildAction("containers",addMapChildAction(id,{layout:{},items:{}}))
229+
);
230+
}
231+
});
232+
// log.debug("syncContainers. actions: ", actions);
233+
letinstance=this;
234+
actions.forEach((action)=>{
235+
instance=instance.reduce(action);
236+
});
237+
returninstance;
238+
}
239+
134240
overridereduce(action:CompAction): this{
241+
constcolumns=this.children.columns.getView();
242+
if(action.type===CompActionTypes.CUSTOM){
243+
constvalue=action.valueasJSONObject;
244+
if(value.type==="push"){
245+
constitemValue=value.valueasJSONObject;
246+
if(_.isEmpty(itemValue.key))itemValue.key=itemValue.label;
247+
action={
248+
...action,
249+
value:{
250+
...value,
251+
value:{ ...itemValue},
252+
},
253+
}asCompAction;
254+
}
255+
const{ path}=action;
256+
if(value.type==="delete"&&path[0]==='columns'&&columns.length<=1){
257+
messageInstance.warning(trans("responsiveLayout.atLeastOneColumnError"));
258+
// at least one column
259+
returnthis;
260+
}
261+
}
262+
// log.debug("before super reduce. action: ", action);
135263
letnewInstance=super.reduce(action);
264+
if(action.type===CompActionTypes.UPDATE_NODES_V2){
265+
// Need eval to get the value in StringControl
266+
newInstance=newInstance.syncContainers();
267+
}
268+
// log.debug("reduce. instance: ", this, " newInstance: ", newInstance);
136269
returnnewInstance;
137270
}
138-
}
139271

140-
*/
272+
realSimpleContainer(key?:string):SimpleContainerComp|undefined{
273+
returnObject.values(this.children.containers.children).find((container)=>
274+
container.realSimpleContainer(key)
275+
);
276+
}
277+
278+
getCompTree():CompTree{
279+
constcontainerMap=this.children.containers.getView();
280+
constcompTrees=Object.values(containerMap).map((container)=>container.getCompTree());
281+
returnmergeCompTrees(compTrees);
282+
}
283+
284+
findContainer(key:string):IContainer|undefined{
285+
constcontainerMap=this.children.containers.getView();
286+
for(constcontainerofObject.values(containerMap)){
287+
constfoundContainer=container.findContainer(key);
288+
if(foundContainer){
289+
returnfoundContainer===container ?this :foundContainer;
290+
}
291+
}
292+
returnundefined;
293+
}
294+
295+
getPasteValue(nameGenerator:NameGenerator):JSONValue{
296+
constcontainerMap=this.children.containers.getView();
297+
constcontainerPasteValueMap=_.mapValues(containerMap,(container)=>
298+
container.getPasteValue(nameGenerator)
299+
);
300+
301+
return{ ...this.toJsonValue(),containers:containerPasteValueMap};
302+
}
303+
304+
overrideautoHeight():boolean{
305+
returnthis.children.autoHeight.getView();
306+
}
307+
}
141308

142-
exportconstSplitLayoutComp=null;
309+
exportconstSplitLayoutComp=withExposingConfigs(
310+
SplitLayoutImplComp,
311+
[NameConfigHidden]
312+
);

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp