Skip to content

Commit 1c6f8bd

Browse files
committed
Tags Component Completed
1 parent c682cc0 commit 1c6f8bd

File tree

9 files changed

+270
-80
lines changed

9 files changed

+270
-80
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 { ReactComponent as VideoScreenshareCompIconSmall } from "./v2/screen-share-stream-s.svg"; // new
356356
export { ReactComponent as SignatureCompIconSmall } from "./v2/signature-s.svg";
357357
export { ReactComponent as StepCompIconSmall } from "./v2/steps-s.svg";
358+
export { ReactComponent as TagsCompIconSmall } from "./v2/tags-s.svg"
358359

359360

360361
export { ReactComponent as CandlestickChartCompIconSmall } from "./v2/candlestick-chart-s.svg"; // new
@@ -468,6 +469,7 @@ export { ReactComponent as SignatureCompIcon } from "./v2/signature-m.svg";
468469
export { ReactComponent as GanttCompIcon } from "./v2/gantt-chart-m.svg";
469470
export { ReactComponent as KanbanCompIconSmall } from "./v2/kanban-s.svg";
470471
export { ReactComponent as KanbanCompIcon } from "./v2/kanban-m.svg";
472+
export { ReactComponent as TagsCompIcon } from "./v2/tags-l.svg";
471473

472474
export { ReactComponent as CandlestickChartCompIcon } from "./v2/candlestick-chart-m.svg";
473475
export { ReactComponent as FunnelChartCompIcon } 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
return new UICompBuilder(childrenMap, (props, dispatch) => {
33-
const valueSet = new Set<any>(props.options.map((o) => o.value)); // Filter illegal default values entered by the user
33+
const valueSet = new Set<any>((props.options as any[]).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
const propsRef = useRef<RecordConstructorToView<typeof childrenMap>>(props);
4040
propsRef.current = props;
4141

42-
const valueSet = new Set<any>(props.options.map((o) => o.value)); // Filter illegal default values entered by the user
42+
const valueSet = new Set<any>((props.options as any[]).map((o: any) => o.value)); // Filter illegal default values entered by the user
4343

4444
return props.label({
4545
required: props.required,
Lines changed: 158 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -1,92 +1,179 @@
1-
import { AnimationStyle, BoolCodeControl, ButtonEventHandlerControl, CommonNameConfig, DropdownOptionControl, IconControl, LinkStyle, NameConfig, NameConfigDisabled, RefControl, Section, SelectOptionControl, StringControl, TabsOptionControl, TagsOptionControl, UICompBuilder, blurMethod, clickMethod, focusWithOptions, migrateOldData, refMethods, sectionNames, stringExposingStateControl, styleControl, withDefault, withExposingConfigs } from "@lowcoder-ee/index.sdk";
2-
import React from "react";
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+
import styled from "styled-components";
15+
import React, { useContext } from "react";
316
import { trans } from "i18n";
4-
import { buttonRefMethods } from "../buttonComp/buttonCompConstants";
517
import { Tag } from "antd";
6-
import { autoCompleteRefMethods } from "../autoCompleteComp/autoCompleteConstants";
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";
723

24+
const colors = PresetStatusColorTypes;
825

9-
// const TagsCompView = (function () {
10-
// // const childrenMap = {
11-
// // text: withDefault(StringControl, trans("link.link")),
12-
// // onEvent: ButtonEventHandlerControl,
13-
// // disabled: BoolCodeControl,
14-
// // loading: BoolCodeControl,
15-
16-
// // // style: migrateOldData(styleControl(LinkStyle, 'style')),
17-
// // animationStyle: styleControl(AnimationStyle, 'animationStyle'),
18-
// // prefixIcon: IconControl,
19-
// // suffixIcon: IconControl,
20-
// // viewRef: RefControl<HTMLElement>,
21-
// // };
26+
// These functions are used for individual tag styling
27+
function getTagColor(tagText : any, tagOptions: any[]) {
28+
const foundOption = tagOptions.find((option: { label: any; }) => option.label === tagText);
29+
if (foundOption) {
30+
if (foundOption.colorType === "preset") {
31+
return foundOption.presetColor;
32+
} else if (foundOption.colorType === "custom") {
33+
return undefined;
34+
}
35+
return foundOption.color;
36+
}
37+
const index = Math.abs(hashToNum(tagText)) % colors.length;
38+
return colors[index];
39+
}
2240

23-
// const childrenMap = {
24-
// text: stringExposingStateControl("text", "world"),
25-
// // options: TabsOptionControl,
26-
// };
27-
// return new UICompBuilder(childrenMap, (props) => {
28-
// return (
29-
// <Tag>Tag 1</Tag>
30-
// )
31-
// })
32-
// .setPropertyViewFn((children) => {
33-
// return(
34-
// <Section name={sectionNames.basic}>
35-
// {/* {children.options.propertyView({})} */}
36-
// {children.text.propertyView({ label: trans("text") })}
37-
// </Section>
38-
// )
39-
// })
40-
// .build();
41-
// })();
41+
const getTagStyle = (tagText: any, tagOptions: any[], baseStyle: any = {}) => {
42+
const foundOption = tagOptions.find((option: { label: any; }) => option.label === tagText);
43+
if (foundOption) {
44+
const style: 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+
return style;
72+
}
73+
return baseStyle;
74+
};
75+
76+
function getTagIcon(tagText: any, tagOptions: any[]) {
77+
const foundOption = tagOptions.find(option => option.label === tagText);
78+
return foundOption ? foundOption.icon : undefined;
79+
}
4280

4381
const multiTags = (function () {
82+
83+
const StyledTag = 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) return props.$customStyle.border;
93+
return props.$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+
const StyledTagContainer = styled.div`
103+
display: flex;
104+
gap: 5px;
105+
padding: 5px;
106+
`;
107+
44108
const childrenMap = {
45-
text: stringExposingStateControl("text", "world"),
46-
options: TagsOptionControl,
109+
options: TagsCompOptionsControl,
110+
style: styleControl(InputLikeStyle, 'style'),
111+
onEvent: ButtonEventHandlerControl,
112+
borderless: BoolCodeControl,
113+
enableIndividualStyling: BoolCodeControl,
47114
};
48115

49116
return new UICompBuilder(childrenMap, (props) => {
50-
const text = props.text.value;
51-
console.log(props.options)
117+
const handleClickEvent = useCompClickEventHandler({onEvent: props.onEvent});
118+
52119
return (
53-
<>
54-
{props.options.map(tag => (
55-
<Tag>{tag.label}</Tag>
56-
))}
57-
</>
58-
);
120+
<StyledTagContainer>
121+
{props.options.map((tag, index) => {
122+
123+
// Use individual styling only if enableIndividualStyling is true
124+
const tagColor = props.enableIndividualStyling ? getTagColor(tag.label, props.options) : undefined;
125+
const tagIcon = props.enableIndividualStyling ? getTagIcon(tag.label, props.options) : tag.icon;
126+
const tagStyle = 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+
);
59144
})
60145
.setPropertyViewFn((children: any) => {
61146
return (
62-
<Section name="Basic">
63-
{children.options.propertyView({})}
64-
{children.text.propertyView({ label: "Text" })}
65-
</Section>
147+
<>
148+
<Section name="Basic">
149+
{children.options.propertyView({})}
150+
</Section>
151+
152+
{["logic", "both"].includes(useContext(EditorContext).editorModeStatus) && (
153+
<Section name={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+
<Section name={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+
</>
66173
)
67174
})
68175
.build();
69176
})()
70177

71-
72-
// const childrenMap = {
73-
// text: stringExposingStateControl("text", "world"),
74-
// options: TagsOptionControl,
75-
// };
76-
77-
// const TagsCompView = new UICompBuilder(childrenMap, (props: any) => {
78-
// const text = props.text.value;
79-
// return <div>Hello {text}</div>;
80-
// })
81-
// .setPropertyViewFn((children: any) => {
82-
// return (
83-
// <Section name="Basic">
84-
// {children.options.propertyView({})}
85-
// {children.text.propertyView({ label: "Text" })}
86-
// </Section>
87-
// )
88-
// })
89-
// .build();
90-
91-
export const MultiTagsComp = withExposingConfigs(multiTags, [new NameConfig("text", "")]);
178+
export const MultiTagsComp = withExposingConfigs(multiTags, [new NameConfig("options", "")]);
92179

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy