Skip to content

Commit d4546e9

Browse files
authored
Merge pull request #849 from lowcoder-org/individualClass
Set an individual class for components
2 parents f21c70f + 09bd3ca commit d4546e9

File tree

3 files changed

+79
-10
lines changed

3 files changed

+79
-10
lines changed

client/packages/lowcoder/src/comps/generators/uiCompBuilder.tsx

+72-9
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { BoolCodeControl } from "comps/controls/codeControl";
1+
import { BoolCodeControl, StringControl } from "comps/controls/codeControl";
22
import React, { ReactNode, useContext, useRef } from "react";
33
import { ExternalEditorContext } from "util/context/ExternalEditorContext";
44
import { Comp, CompParams, MultiBaseComp } from "lowcoder-core";
@@ -22,10 +22,14 @@ import {
2222
MethodConfigsType,
2323
withMethodExposing,
2424
} from "./withMethodExposing";
25+
import { Section } from "lowcoder-design";
26+
import { trans } from "i18n";
2527

2628
export type NewChildren<ChildrenCompMap extends Record<string, Comp<unknown>>> =
2729
ChildrenCompMap & {
2830
hidden: InstanceType<typeof BoolCodeControl>;
31+
className: InstanceType<typeof StringControl>;
32+
dataTestId: InstanceType<typeof StringControl>;
2933
};
3034

3135
export function HidableView(props: {
@@ -50,12 +54,51 @@ export function HidableView(props: {
5054
}
5155
}
5256

57+
export function ExtendedComponentView(props: {
58+
children: JSX.Element | React.ReactNode;
59+
className: string;
60+
dataTestId: string;
61+
}) {
62+
if (!props.className && !props.dataTestId) {
63+
return <>{props.children}</>;
64+
}
65+
66+
return (
67+
<div className={props.className} data-testid={props.dataTestId}>
68+
{props.children}
69+
</div>
70+
);
71+
}
72+
73+
export function ExtendedPropertyView<
74+
ChildrenCompMap extends Record<string, Comp<unknown>>,
75+
>(props: {
76+
children: JSX.Element | React.ReactNode,
77+
childrenMap: NewChildren<ChildrenCompMap>
78+
}
79+
) {
80+
return (
81+
<>
82+
{props.children}
83+
<Section name={trans("prop.component")}>
84+
{props.childrenMap.className?.propertyView({ label: trans("prop.className") })}
85+
{props.childrenMap.dataTestId?.propertyView({ label: trans("prop.dataTestId") })}
86+
</Section>
87+
</>
88+
);
89+
}
90+
5391
export function uiChildren<
5492
ChildrenCompMap extends Record<string, Comp<unknown>>,
5593
>(
5694
childrenMap: ToConstructor<ChildrenCompMap>
5795
): ToConstructor<NewChildren<ChildrenCompMap>> {
58-
return { ...childrenMap, hidden: BoolCodeControl } as any;
96+
return {
97+
...childrenMap,
98+
hidden: BoolCodeControl,
99+
className: StringControl,
100+
dataTestId: StringControl
101+
} as any;
59102
}
60103

61104
type ViewReturn = ReactNode;
@@ -89,10 +132,22 @@ export class UICompBuilder<
89132
setPropertyViewFn(
90133
propertyViewFn: PropertyViewFnTypeForComp<NewChildren<ChildrenCompMap>>
91134
) {
92-
this.propertyViewFn = propertyViewFn;
135+
this.propertyViewFn = this.decoratePropertyViewFn(propertyViewFn);
93136
return this;
94137
}
95138

139+
decoratePropertyViewFn(
140+
propertyViewFn: PropertyViewFnTypeForComp<NewChildren<ChildrenCompMap>>
141+
): PropertyViewFnTypeForComp<NewChildren<ChildrenCompMap>> {
142+
return (childrenMap, dispatch) => {
143+
return (
144+
<ExtendedPropertyView childrenMap={childrenMap}>
145+
{propertyViewFn(childrenMap, dispatch)}
146+
</ExtendedPropertyView>
147+
);
148+
};
149+
}
150+
96151
setExposeStateConfigs(
97152
configs: ExposingConfig<ChildrenToComp<ChildrenCompMap>>[]
98153
) {
@@ -110,8 +165,11 @@ export class UICompBuilder<
110165
}
111166

112167
build() {
113-
if (this.childrenMap.hasOwnProperty("hidden")) {
114-
throw new Error("already has hidden");
168+
const reservedProps = ["hidden", "className", "dataTestId"];
169+
for (const reservedProp of reservedProps) {
170+
if (this.childrenMap.hasOwnProperty(reservedProp)) {
171+
throw new Error(`Property »${reservedProp}« is reserved and must not be implemented in components!`);
172+
}
115173
}
116174
const newChildrenMap = uiChildren(this.childrenMap);
117175
const builder = this;
@@ -122,7 +180,7 @@ export class UICompBuilder<
122180
ToNodeType<NewChildren<ChildrenCompMap>>
123181
> {
124182
ref: React.RefObject<HTMLDivElement> = React.createRef();
125-
183+
126184
override parseChildrenFromValue(
127185
params: CompParams<ToDataType<NewChildren<ChildrenCompMap>>>
128186
): NewChildren<ChildrenCompMap> {
@@ -185,8 +243,13 @@ function UIView(props: { comp: any; viewFn: any }) {
185243
//END ADD BY FRED
186244

187245
return (
188-
<HidableView hidden={childrenProps.hidden as boolean}>
189-
{props.viewFn(childrenProps, comp.dispatch)}
190-
</HidableView>
246+
<ExtendedComponentView
247+
className={childrenProps.className as string}
248+
dataTestId={childrenProps.dataTestId as string}
249+
>
250+
<HidableView hidden={childrenProps.hidden as boolean}>
251+
{props.viewFn(childrenProps, comp.dispatch)}
252+
</HidableView>
253+
</ExtendedComponentView>
191254
);
192255
}

client/packages/lowcoder/src/i18n/locales/de.ts

+4-1
Original file line numberDiff line numberDiff line change
@@ -195,7 +195,10 @@ export const de: typeof en = {
195195
"showBody": "Hauptbereich zeigen",
196196
"showFooter": "Fußbereich anzeigen",
197197
"maskClosable": "Zum Schließen auf \"Schließen\" klicken",
198-
"showMask": "Maske darstellen"
198+
"showMask": "Maske darstellen",
199+
"component": "Komponente",
200+
"className": "Klasse",
201+
"dataTestId": "Test ID",
199202
},
200203
"autoHeightProp": {
201204
...en.autoHeightProp,

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

+3
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,9 @@ export const en = {
211211
"baseURL": "Lowcoder API Base URL",
212212
"horizontal": "Horizontal",
213213
"minHorizontalWidth": "Minimum Horizontal Width",
214+
"component": "Component",
215+
"className": "Class",
216+
"dataTestId": "Test ID",
214217
},
215218
"autoHeightProp": {
216219
"auto": "Auto",

0 commit comments

Comments
 (0)