Skip to content

Commit 594e68f

Browse files
authored
Merge pull request #854 from lowcoder-org/feat-ShapeComp
Adding Shapes Component
2 parents 4f06801 + b156fc0 commit 594e68f

File tree

16 files changed

+1169
-12
lines changed

16 files changed

+1169
-12
lines changed

client/packages/lowcoder-design/src/components/shapeSelect/index.tsx

Lines changed: 487 additions & 0 deletions
Large diffs are not rendered by default.

client/packages/lowcoder-design/src/i18n/design/locales/en.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ export const en = {
2323
advanced: "Advanced",
2424
validation: "Validation",
2525
layout: "Layout",
26-
labelStyle:"Label Style",
26+
labelStyle: "Label Style",
2727
style: "Style",
2828
meetings: "Meeting Settings",
2929
data: "Data",
@@ -54,6 +54,10 @@ export const en = {
5454
title: "Select icon",
5555
searchPlaceholder: "Search icon",
5656
},
57+
shapeSelect: {
58+
title: "Select shape",
59+
searchPlaceholder: "Search shape",
60+
},
5761
eventHandler: {
5862
advanced: "Advanced",
5963
},

client/packages/lowcoder-design/src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ export * from "./components/tacoInput";
4747
export * from "./components/tacoPagination";
4848
export * from "./components/toolTip";
4949
export * from "./components/video";
50+
export * from "./components/shapeSelect";
5051

5152
export * from "./icons";
5253

client/packages/lowcoder/package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
"buffer": "^6.0.3",
4242
"clsx": "^2.0.0",
4343
"cnchar": "^3.2.4",
44+
"coolshapes-react": "lowcoder-org/coolshapes-react",
4445
"copy-to-clipboard": "^3.3.3",
4546
"core-js": "^3.25.2",
4647
"echarts": "^5.4.3",
@@ -129,4 +130,4 @@
129130
"vite-plugin-svgr": "^2.2.2",
130131
"vite-tsconfig-paths": "^3.6.0"
131132
}
132-
}
133+
}
Lines changed: 159 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,159 @@
1+
import { CompParams } from "lowcoder-core";
2+
import { ToDataType } from "comps/generators/multi";
3+
import {
4+
NameConfigHidden,
5+
withExposingConfigs,
6+
} from "comps/generators/withExposing";
7+
import { NameGenerator } from "comps/utils/nameGenerator";
8+
import { Section, sectionNames } from "lowcoder-design";
9+
import { oldContainerParamsToNew } from "../containerBase";
10+
import { toSimpleContainerData } from "../containerBase/simpleContainerComp";
11+
import { ShapeTriContainer } from "./shapeTriContainer";
12+
import { ShapeControl } from "comps/controls/shapeControl";
13+
import { withDefault } from "../../generators";
14+
import {
15+
ContainerChildren,
16+
ContainerCompBuilder,
17+
} from "../triContainerComp/triContainerCompBuilder";
18+
import {
19+
disabledPropertyView,
20+
hiddenPropertyView,
21+
} from "comps/utils/propertyUtils";
22+
import { trans } from "i18n";
23+
import { BoolCodeControl } from "comps/controls/codeControl";
24+
import { DisabledContext } from "comps/generators/uiCompBuilder";
25+
import React, { useContext, useEffect, useState } from "react";
26+
import { EditorContext } from "comps/editorState";
27+
28+
export const ContainerBaseComp = (function () {
29+
const childrenMap = {
30+
disabled: BoolCodeControl,
31+
icon: withDefault(ShapeControl, ""),
32+
};
33+
return new ContainerCompBuilder(childrenMap, (props, dispatch) => {
34+
35+
36+
return (
37+
<DisabledContext.Provider value={props.disabled}>
38+
<ShapeTriContainer {...props} />
39+
</DisabledContext.Provider>
40+
);
41+
})
42+
.setPropertyViewFn((children) => {
43+
return (
44+
<>
45+
<Section name={sectionNames.basic}>
46+
{children.icon.propertyView({
47+
label: trans("iconComp.icon"),
48+
IconType: "All",
49+
})}
50+
</Section>
51+
{(useContext(EditorContext).editorModeStatus === "logic" ||
52+
useContext(EditorContext).editorModeStatus === "both") && (
53+
<Section name={sectionNames.interaction}>
54+
{disabledPropertyView(children)}
55+
{hiddenPropertyView(children)}
56+
</Section>
57+
)}
58+
59+
{(useContext(EditorContext).editorModeStatus === "layout" ||
60+
useContext(EditorContext).editorModeStatus === "both") && (
61+
<>
62+
<Section name={sectionNames.layout}>
63+
{children.container.getPropertyView()}
64+
</Section>
65+
<Section name={sectionNames.style}>
66+
{children.container.stylePropertyView()}
67+
</Section>
68+
{children.container.children.showHeader.getView() && (
69+
<Section name={"Header Style"}>
70+
{children.container.headerStylePropertyView()}
71+
</Section>
72+
)}
73+
{children.container.children.showBody.getView() && (
74+
<Section name={"Body Style"}>
75+
{children.container.bodyStylePropertyView()}
76+
</Section>
77+
)}
78+
{children.container.children.showFooter.getView() && (
79+
<Section name={"Footer Style"}>
80+
{children.container.footerStylePropertyView()}
81+
</Section>
82+
)}
83+
</>
84+
)}
85+
</>
86+
);
87+
})
88+
.build();
89+
})();
90+
91+
// Compatible with old data
92+
function convertOldContainerParams(params: CompParams<any>) {
93+
// convert older params to old params
94+
let tempParams = oldContainerParamsToNew(params);
95+
96+
if (tempParams.value) {
97+
const container = tempParams.value.container;
98+
// old params
99+
if (
100+
container &&
101+
(container.hasOwnProperty("layout") || container.hasOwnProperty("items"))
102+
) {
103+
const autoHeight = tempParams.value.autoHeight;
104+
const scrollbars = tempParams.value.scrollbars;
105+
return {
106+
...tempParams,
107+
value: {
108+
container: {
109+
showHeader: true,
110+
body: { 0: { view: container } },
111+
showBody: true,
112+
showFooter: false,
113+
autoHeight: autoHeight,
114+
scrollbars: scrollbars,
115+
},
116+
},
117+
};
118+
}
119+
}
120+
return tempParams;
121+
}
122+
123+
class ContainerTmpComp extends ContainerBaseComp {
124+
constructor(params: CompParams<any>) {
125+
super(convertOldContainerParams(params));
126+
}
127+
}
128+
129+
export const ShapeComp = withExposingConfigs(ContainerTmpComp, [NameConfigHidden]);
130+
131+
type ContainerDataType = ToDataType<ContainerChildren<{}>>;
132+
133+
export function defaultContainerData(
134+
compName: string,
135+
nameGenerator: NameGenerator
136+
): ContainerDataType {
137+
return {
138+
container: {
139+
header: toSimpleContainerData([
140+
{
141+
item: {
142+
compType: "text",
143+
name: nameGenerator.genItemName("containerTitle"),
144+
comp: {
145+
text: "### " + trans("container.title"),
146+
},
147+
},
148+
layoutItem: {
149+
i: "",
150+
h: 5,
151+
w: 24,
152+
x: 0,
153+
y: 0,
154+
},
155+
},
156+
]),
157+
},
158+
};
159+
}
Lines changed: 160 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,160 @@
1+
import { ContainerStyleType } from "comps/controls/styleControlConstants";
2+
import { EditorContext } from "comps/editorState";
3+
import { BackgroundColorContext } from "comps/utils/backgroundColorContext";
4+
import { HintPlaceHolder, ScrollBar } from "lowcoder-design";
5+
import { ReactNode, useContext, useEffect, useState } from "react";
6+
import styled, { css } from "styled-components";
7+
import { checkIsMobile } from "util/commonUtils";
8+
import {
9+
gridItemCompToGridItems,
10+
InnerGrid,
11+
} from "../containerComp/containerView";
12+
import { TriContainerViewProps } from "../triContainerComp/triContainerCompBuilder";
13+
import { Coolshape } from "coolshapes-react";
14+
15+
const getStyle = (style: ContainerStyleType) => {
16+
return css`
17+
border-color: ${style.border};
18+
border-width: ${style.borderWidth};
19+
border-radius: ${style.radius};
20+
overflow: hidden;
21+
padding: ${style.padding};
22+
${style.background && `background-color: ${style.background};`}
23+
${style.backgroundImage && `background-image: ${style.backgroundImage};`}
24+
${style.backgroundImageRepeat &&
25+
`background-repeat: ${style.backgroundImageRepeat};`}
26+
${style.backgroundImageSize &&
27+
`background-size: ${style.backgroundImageSize};`}
28+
${style.backgroundImagePosition &&
29+
`background-position: ${style.backgroundImagePosition};`}
30+
${style.backgroundImageOrigin &&
31+
`background-origin: ${style.backgroundImageOrigin};`}
32+
`;
33+
};
34+
35+
const Wrapper = styled.div<{ $style: ContainerStyleType }>`
36+
display: flex;
37+
flex-flow: column;
38+
height: 100%;
39+
border: 1px solid #d7d9e0;
40+
border-radius: 4px;
41+
${(props) => props.$style && getStyle(props.$style)}
42+
`;
43+
44+
const BodyInnerGrid = styled(InnerGrid)<{
45+
$showBorder: boolean;
46+
$backgroundColor: string;
47+
$borderColor: string;
48+
$borderWidth: string;
49+
$backgroundImage: string;
50+
$backgroundImageRepeat: string;
51+
$backgroundImageSize: string;
52+
$backgroundImagePosition: string;
53+
$backgroundImageOrigin: string;
54+
}>`
55+
border-top: ${(props) =>
56+
`${props.$showBorder ? props.$borderWidth : 0} solid ${props.$borderColor}`};
57+
flex: 1;
58+
${(props) =>
59+
props.$backgroundColor && `background-color: ${props.$backgroundColor};`}
60+
border-radius: 0;
61+
${(props) =>
62+
props.$backgroundImage && `background-image: ${props.$backgroundImage};`}
63+
${(props) =>
64+
props.$backgroundImageRepeat &&
65+
`background-repeat: ${props.$backgroundImageRepeat};`}
66+
${(props) =>
67+
props.$backgroundImageSize &&
68+
`background-size: ${props.$backgroundImageSize};`}
69+
${(props) =>
70+
props.$backgroundImagePosition &&
71+
`background-position: ${props.$backgroundImagePosition};`}
72+
${(props) =>
73+
props.$backgroundImageOrigin &&
74+
`background-origin: ${props.$backgroundImageOrigin};`}
75+
`;
76+
77+
export type TriContainerProps = TriContainerViewProps & {
78+
hintPlaceholder?: ReactNode;
79+
icon: any;
80+
};
81+
82+
export function ShapeTriContainer(props: TriContainerProps) {
83+
const { container, icon } = props;
84+
const { showHeader, showFooter } = container;
85+
// When the header and footer are not displayed, the body must be displayed
86+
const showBody = container.showBody || (!showHeader && !showFooter);
87+
const scrollbars = container.scrollbars;
88+
89+
const { items: headerItems, ...otherHeaderProps } = container.header;
90+
const { items: bodyItems, ...otherBodyProps } =
91+
container.body["0"].children.view.getView();
92+
const { items: footerItems, ...otherFooterProps } = container.footer;
93+
const { style, headerStyle, bodyStyle, footerStyle } = container;
94+
95+
const editorState = useContext(EditorContext);
96+
const maxWidth = editorState.getAppSettings().maxWidth;
97+
const isMobile = checkIsMobile(maxWidth);
98+
const paddingWidth = isMobile ? 8 : 0;
99+
100+
let [shape, setShape] = useState({ value: "star", index: 0 });
101+
useEffect(() => {
102+
if (icon.props?.value) {
103+
let shapeDetails = icon.props?.value;
104+
setShape({
105+
index: parseInt(shapeDetails?.split("_")[0]),
106+
value: shapeDetails?.split("_")[1],
107+
});
108+
}
109+
}, [icon.props]);
110+
111+
return (
112+
<div style={{ padding: style.margin, height: "100%" }}>
113+
<Wrapper $style={style}>
114+
<BackgroundColorContext.Provider value={bodyStyle.background}>
115+
<ScrollBar
116+
style={{
117+
height: container.autoHeight ? "auto" : "100%",
118+
margin: "0px",
119+
padding: "0px",
120+
}}
121+
hideScrollbar={!scrollbars}
122+
>
123+
<div style={{ position: "relative", height: "100%" }}>
124+
<Coolshape
125+
type={shape?.value as any}
126+
index={shape.index}
127+
styles={{
128+
position: "absolute",
129+
top: "0",
130+
left: "50%",
131+
transform: "translateX(-50%)",
132+
}}
133+
/>
134+
<BodyInnerGrid
135+
$showBorder={false}
136+
{...otherBodyProps}
137+
items={gridItemCompToGridItems(bodyItems)}
138+
autoHeight={container.autoHeight}
139+
emptyRows={14}
140+
minHeight={"142px"}
141+
hintPlaceholder={props.hintPlaceholder ?? HintPlaceHolder}
142+
$backgroundColor={bodyStyle?.background || "transparent"}
143+
$borderColor={style?.border}
144+
$borderWidth={style?.borderWidth}
145+
$backgroundImage={bodyStyle?.backgroundImage}
146+
$backgroundImageRepeat={bodyStyle?.backgroundImageRepeat}
147+
$backgroundImageSize={bodyStyle?.backgroundImageSize}
148+
$backgroundImagePosition={bodyStyle?.backgroundImagePosition}
149+
$backgroundImageOrigin={bodyStyle?.backgroundImageOrigin}
150+
style={{
151+
zIndex: 999,
152+
}}
153+
/>
154+
</div>
155+
</ScrollBar>
156+
</BackgroundColorContext.Provider>
157+
</Wrapper>
158+
</div>
159+
);
160+
}

0 commit comments

Comments
 (0)