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

Commitb7f1d33

Browse files
Merge pull request#1818 from kamalqureshi/tags_component
Tags component
2 parents12f2d45 +3ede19e commitb7f1d33

File tree

11 files changed

+340
-8
lines changed

11 files changed

+340
-8
lines changed

‎client/packages/lowcoder-design/src/icons/index.tsx‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -355,6 +355,7 @@ export { ReactComponent as VideoCameraStreamCompIconSmall } from "./v2/camera-st
355355
export{ReactComponentasVideoScreenshareCompIconSmall}from"./v2/screen-share-stream-s.svg";// new
356356
export{ReactComponentasSignatureCompIconSmall}from"./v2/signature-s.svg";
357357
export{ReactComponentasStepCompIconSmall}from"./v2/steps-s.svg";
358+
export{ReactComponentasTagsCompIconSmall}from"./v2/tags-s.svg"
358359

359360

360361
export{ReactComponentasCandlestickChartCompIconSmall}from"./v2/candlestick-chart-s.svg";// new
@@ -468,6 +469,7 @@ export { ReactComponent as SignatureCompIcon } from "./v2/signature-m.svg";
468469
export{ReactComponentasGanttCompIcon}from"./v2/gantt-chart-m.svg";
469470
export{ReactComponentasKanbanCompIconSmall}from"./v2/kanban-s.svg";
470471
export{ReactComponentasKanbanCompIcon}from"./v2/kanban-m.svg";
472+
export{ReactComponentasTagsCompIcon}from"./v2/tags-l.svg";
471473

472474
export{ReactComponentasCandlestickChartCompIcon}from"./v2/candlestick-chart-m.svg";
473475
export{ReactComponentasFunnelChartCompIcon}from"./v2/funnel-chart-m.svg";
Lines changed: 10 additions & 0 deletions
Loading
Lines changed: 10 additions & 0 deletions
Loading

‎client/packages/lowcoder/src/comps/comps/selectInputComp/multiSelectComp.tsx‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ let MultiSelectBasicComp = (function () {
3030
padding:PaddingControl,
3131
};
3232
returnnewUICompBuilder(childrenMap,(props,dispatch)=>{
33-
constvalueSet=newSet<any>(props.options.map((o)=>o.value));// Filter illegal default values entered by the user
33+
constvalueSet=newSet<any>((props.optionsasany[]).map((o:any)=>o.value));// Filter illegal default values entered by the user
3434
const[
3535
validateState,
3636
handleChange,

‎client/packages/lowcoder/src/comps/comps/selectInputComp/selectComp.tsx‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ let SelectBasicComp = (function () {
3939
constpropsRef=useRef<RecordConstructorToView<typeofchildrenMap>>(props);
4040
propsRef.current=props;
4141

42-
constvalueSet=newSet<any>(props.options.map((o)=>o.value));// Filter illegal default values entered by the user
42+
constvalueSet=newSet<any>((props.optionsasany[]).map((o:any)=>o.value));// Filter illegal default values entered by the user
4343

4444
returnprops.label({
4545
required:props.required,
Lines changed: 179 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,179 @@
1+
import{
2+
BoolCodeControl,
3+
ButtonEventHandlerControl,
4+
InputLikeStyle,
5+
NameConfig,
6+
Section,
7+
UICompBuilder,
8+
hiddenPropertyView,
9+
sectionNames,
10+
showDataLoadingIndicatorsPropertyView,
11+
styleControl,
12+
withExposingConfigs
13+
}from"@lowcoder-ee/index.sdk";
14+
importstyledfrom"styled-components";
15+
importReact,{useContext}from"react";
16+
import{trans}from"i18n";
17+
import{Tag}from"antd";
18+
import{EditorContext}from"comps/editorState";
19+
import{PresetStatusColorTypes}from"antd/es/_util/colors";
20+
import{hashToNum}from"util/stringUtils";
21+
import{TagsCompOptionsControl}from"comps/controls/optionsControl";
22+
import{useCompClickEventHandler}from"@lowcoder-ee/comps/utils/useCompClickEventHandler";
23+
24+
constcolors=PresetStatusColorTypes;
25+
26+
// These functions are used for individual tag styling
27+
functiongetTagColor(tagText :any,tagOptions:any[]){
28+
constfoundOption=tagOptions.find((option:{label:any;})=>option.label===tagText);
29+
if(foundOption){
30+
if(foundOption.colorType==="preset"){
31+
returnfoundOption.presetColor;
32+
}elseif(foundOption.colorType==="custom"){
33+
returnundefined;
34+
}
35+
returnfoundOption.color;
36+
}
37+
constindex=Math.abs(hashToNum(tagText))%colors.length;
38+
returncolors[index];
39+
}
40+
41+
constgetTagStyle=(tagText:any,tagOptions:any[],baseStyle:any={})=>{
42+
constfoundOption=tagOptions.find((option:{label:any;})=>option.label===tagText);
43+
if(foundOption){
44+
conststyle:any={ ...baseStyle};
45+
46+
if(foundOption.colorType==="custom"){
47+
style.backgroundColor=foundOption.color;
48+
style.color=foundOption.textColor;
49+
style.border=`1px solid${foundOption.color}`;
50+
}
51+
52+
if(foundOption.border){
53+
style.borderColor=foundOption.border;
54+
if(!foundOption.colorType||foundOption.colorType!=="custom"){
55+
style.border=`1px solid${foundOption.border}`;
56+
}
57+
}
58+
59+
if(foundOption.radius){
60+
style.borderRadius=foundOption.radius;
61+
}
62+
63+
if(foundOption.margin){
64+
style.margin=foundOption.margin;
65+
}
66+
67+
if(foundOption.padding){
68+
style.padding=foundOption.padding;
69+
}
70+
71+
returnstyle;
72+
}
73+
returnbaseStyle;
74+
};
75+
76+
functiongetTagIcon(tagText:any,tagOptions:any[]){
77+
constfoundOption=tagOptions.find(option=>option.label===tagText);
78+
returnfoundOption ?foundOption.icon :undefined;
79+
}
80+
81+
constmultiTags=(function(){
82+
83+
constStyledTag=styled(Tag)<{$style:any,$bordered:boolean,$customStyle:any}>`
84+
display: flex;
85+
justify-content: center;
86+
align-items: center;
87+
width: 100%;
88+
background:${(props)=>props.$customStyle?.backgroundColor||props.$style?.background};
89+
color:${(props)=>props.$customStyle?.color||props.$style?.text};
90+
border-radius:${(props)=>props.$customStyle?.borderRadius||props.$style?.borderRadius};
91+
border:${(props)=>{
92+
if(props.$customStyle?.border)returnprops.$customStyle.border;
93+
returnprops.$bordered ?`${props.$style?.borderStyle}${props.$style?.borderWidth}${props.$style?.border}` :'none';
94+
}};
95+
padding:${(props)=>props.$customStyle?.padding||props.$style?.padding};
96+
margin:${(props)=>props.$customStyle?.margin||props.$style?.margin};
97+
font-size:${(props)=>props.$style?.textSize};
98+
font-weight:${(props)=>props.$style?.fontWeight};
99+
cursor: pointer;
100+
`;
101+
102+
constStyledTagContainer=styled.div`
103+
display: flex;
104+
gap: 5px;
105+
padding: 5px;
106+
`;
107+
108+
constchildrenMap={
109+
options:TagsCompOptionsControl,
110+
style:styleControl(InputLikeStyle,'style'),
111+
onEvent:ButtonEventHandlerControl,
112+
borderless:BoolCodeControl,
113+
enableIndividualStyling:BoolCodeControl,
114+
};
115+
116+
returnnewUICompBuilder(childrenMap,(props)=>{
117+
consthandleClickEvent=useCompClickEventHandler({onEvent:props.onEvent});
118+
119+
return(
120+
<StyledTagContainer>
121+
{props.options.map((tag,index)=>{
122+
123+
// Use individual styling only if enableIndividualStyling is true
124+
consttagColor=props.enableIndividualStyling ?getTagColor(tag.label,props.options) :undefined;
125+
consttagIcon=props.enableIndividualStyling ?getTagIcon(tag.label,props.options) :tag.icon;
126+
consttagStyle=props.enableIndividualStyling ?getTagStyle(tag.label,props.options,props.style) :{};
127+
128+
return(
129+
<StyledTag
130+
key={`tag-${index}`}
131+
$style={props.style}
132+
$bordered={!props.borderless}
133+
$customStyle={tagStyle}
134+
icon={tagIcon}
135+
color={tagColor}
136+
onClick={()=>handleClickEvent()}
137+
>
138+
{tag.label}
139+
</StyledTag>
140+
);
141+
})}
142+
</StyledTagContainer>
143+
);
144+
})
145+
.setPropertyViewFn((children:any)=>{
146+
return(
147+
<>
148+
<Sectionname="Basic">
149+
{children.options.propertyView({})}
150+
</Section>
151+
152+
{["logic","both"].includes(useContext(EditorContext).editorModeStatus)&&(
153+
<Sectionname={sectionNames.interaction}>
154+
{children.onEvent.getPropertyView()}
155+
{hiddenPropertyView(children)}
156+
{showDataLoadingIndicatorsPropertyView(children)}
157+
</Section>
158+
)}
159+
160+
{["layout","both"].includes(
161+
useContext(EditorContext).editorModeStatus
162+
)&&(
163+
<Sectionname={sectionNames.style}>
164+
{children.enableIndividualStyling.propertyView({
165+
label:trans("style.individualStyling"),
166+
tooltip:trans("style.individualStylingTooltip")
167+
})}
168+
{children.borderless.propertyView({label:trans("style.borderless")})}
169+
{children.style.getPropertyView()}
170+
</Section>
171+
)}
172+
</>
173+
)
174+
})
175+
.build();
176+
})()
177+
178+
exportconstMultiTagsComp=withExposingConfigs(multiTags,[newNameConfig("options","")]);
179+

‎client/packages/lowcoder/src/comps/controls/optionsControl.tsx‎

Lines changed: 106 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -557,6 +557,7 @@ const TabsOption = new MultiCompBuilder(
557557
</>
558558
))
559559
.build();
560+
560561

561562
exportconstTabsOptionControl=manualOptionsControl(TabsOption,{
562563
initOptions:[
@@ -567,6 +568,37 @@ export const TabsOptionControl = manualOptionsControl(TabsOption, {
567568
autoIncField:"id",
568569
});
569570

571+
constTagsOption=newMultiCompBuilder(
572+
{
573+
id:valueComp<number>(-1),
574+
label:StringControl,
575+
icon:IconControl,
576+
iconPosition:withDefault(LeftRightControl,"left"),
577+
hidden:BoolCodeControl,
578+
},
579+
(props)=>props
580+
)
581+
.setPropertyViewFn((children)=>(
582+
<>
583+
{children.label.propertyView({label:trans("label")})}
584+
{children.icon.propertyView({label:trans("icon")})}
585+
{children.iconPosition.propertyView({
586+
label:trans("tabbedContainer.iconPosition"),
587+
radioButton:true,
588+
})}
589+
{hiddenPropertyView(children)}
590+
</>
591+
))
592+
.build();
593+
594+
exportconstTagsOptionControl=optionsControl(TagsOption,{
595+
initOptions:[
596+
{id:0,label:"Option 1"},
597+
{id:1,label:"Option 2"},
598+
],
599+
autoIncField:"id",
600+
});
601+
570602
constStyledIcon=styled.span`
571603
margin: 0 4px 0 14px;
572604
`;
@@ -750,14 +782,83 @@ export const StepOptionControl = optionsControl(StepOption, {
750782
uniqField:"label",
751783
});
752784

785+
letTagsCompOptions=newMultiCompBuilder(
786+
{
787+
label:StringControl,
788+
icon:IconControl,
789+
colorType:withDefault(dropdownControl([
790+
{label:trans("style.preset"),value:"preset"},
791+
{label:trans("style.custom"),value:"custom"},
792+
]asconst,"preset"),"preset"),
793+
presetColor:withDefault(dropdownControl(TAG_PRESET_COLORS,"blue"),"blue"),
794+
color:withDefault(ColorControl,"#1890ff"),
795+
textColor:withDefault(ColorControl,"#ffffff"),
796+
border:withDefault(ColorControl,""),
797+
radius:withDefault(RadiusControl,""),
798+
margin:withDefault(StringControl,""),
799+
padding:withDefault(StringControl,""),
800+
},
801+
(props)=>props
802+
).build();
803+
804+
TagsCompOptions=classextendsTagsCompOptionsimplementsOptionCompProperty{
805+
propertyView(param:{autoMap?:boolean}){
806+
constcolorType=this.children.colorType.getView();
807+
return(
808+
<>
809+
{this.children.label.propertyView({label:trans("coloredTagOptionControl.tag")})}
810+
{this.children.icon.propertyView({label:trans("coloredTagOptionControl.icon")})}
811+
{this.children.colorType.propertyView({
812+
label:trans("style.colorType"),
813+
radioButton:true
814+
})}
815+
{colorType==="preset"&&this.children.presetColor.propertyView({
816+
label:trans("style.presetColor")
817+
})}
818+
{colorType==="custom"&&(
819+
<>
820+
{this.children.color.propertyView({label:trans("coloredTagOptionControl.color")})}
821+
{this.children.textColor.propertyView({label:trans("style.textColor")})}
822+
</>
823+
)}
824+
{this.children.border.propertyView({
825+
label:trans('style.border')
826+
})}
827+
{this.children.radius.propertyView({
828+
label:trans('style.borderRadius'),
829+
preInputNode:<StyledIconas={IconRadius}title=""/>,
830+
placeholder:'3px',
831+
})}
832+
{this.children.margin.propertyView({
833+
label:trans('style.margin'),
834+
preInputNode:<StyledIconas={ExpandIcon}title=""/>,
835+
placeholder:'3px',
836+
})}
837+
{this.children.padding.propertyView({
838+
label:trans('style.padding'),
839+
preInputNode:<StyledIconas={CompressIcon}title=""/>,
840+
placeholder:'3px',
841+
})}
842+
</>
843+
);
844+
}
845+
};
846+
847+
exportconstTagsCompOptionsControl=optionsControl(TagsCompOptions,{
848+
initOptions:[
849+
{label:"Option 1",colorType:"preset",presetColor:"blue"},
850+
{label:"Option 2",colorType:"preset",presetColor:"green"}
851+
],
852+
uniqField:"label",
853+
});
753854

754855
letColoredTagOption=newMultiCompBuilder(
755856
{
756857
label:StringControl,
757858
icon:IconControl,
758859
colorType:withDefault(dropdownControl([
759-
{label:"Preset",value:"preset"},
760-
{label:"Custom",value:"custom"},
860+
{label:trans("style.preset"),value:"preset"},
861+
{label:trans("style.custom"),value:"custom"},
761862
]asconst,"preset"),"preset"),
762863
presetColor:withDefault(dropdownControl(TAG_PRESET_COLORS,"blue"),"blue"),
763864
color:withDefault(ColorControl,"#1890ff"),
@@ -779,16 +880,16 @@ ColoredTagOption = class extends ColoredTagOption implements OptionCompProperty
779880
{this.children.label.propertyView({label:trans("coloredTagOptionControl.tag")})}
780881
{this.children.icon.propertyView({label:trans("coloredTagOptionControl.icon")})}
781882
{this.children.colorType.propertyView({
782-
label:"Color Type",
883+
label:trans("style.colorType"),
783884
radioButton:true
784885
})}
785886
{colorType==="preset"&&this.children.presetColor.propertyView({
786-
label:"Preset Color"
887+
label:trans("style.presetColor")
787888
})}
788889
{colorType==="custom"&&(
789890
<>
790891
{this.children.color.propertyView({label:trans("coloredTagOptionControl.color")})}
791-
{this.children.textColor.propertyView({label:"Text Color"})}
892+
{this.children.textColor.propertyView({label:trans("style.textColor")})}
792893
</>
793894
)}
794895
{this.children.border.propertyView({

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp