Skip to content

Commit 5295375

Browse files
authored
Merge pull request #703 from lowcoder-org/remix-icons
Icon Component
2 parents f42e8e7 + 48b46cc commit 5295375

File tree

14 files changed

+353
-74
lines changed

14 files changed

+353
-74
lines changed

client/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@
7878
"chalk": "4",
7979
"number-precision": "^1.6.0",
8080
"react-player": "^2.11.0",
81+
"remixicon-react": "^1.0.0",
8182
"tui-image-editor": "^3.15.3"
8283
}
8384
}

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

Lines changed: 112 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,29 @@
11
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
22
import type { IconDefinition } from "@fortawesome/free-regular-svg-icons";
3-
import { default as Popover } from "antd/es/popover";
4-
import { ActionType } from '@rc-component/trigger/lib/interface';
3+
// import type { IconDefinition as IconDefinitionBrands } from "@fortawesome/free-brands-svg-icons";
4+
import { Popover } from "antd";
5+
import { ActionType } from "@rc-component/trigger/lib/interface";
56
import { TacoInput } from "components/tacoInput";
67
import { Tooltip } from "components/toolTip";
78
import { trans } from "i18n/design";
89
import _ from "lodash";
9-
import { ReactNode, useEffect, useCallback, useMemo, useRef, useState } from "react";
10+
import {
11+
ReactNode,
12+
useEffect,
13+
useCallback,
14+
useMemo,
15+
useRef,
16+
useState,
17+
} from "react";
1018
import Draggable from "react-draggable";
1119
import { default as List, ListRowProps } from "react-virtualized/dist/es/List";
1220
import styled from "styled-components";
1321
import { CloseIcon, SearchIcon } from "icons";
22+
import { ANTDICON } from "icons/antIcon";
23+
import { Divider } from "antd-mobile";
1424

1525
const PopupContainer = styled.div`
16-
width: 408px;
26+
width: 580px;
1727
background: #ffffff;
1828
box-shadow: 0 0 10px 0 rgba(0, 0, 0, 0.1);
1929
border-radius: 8px;
@@ -76,25 +86,28 @@ const IconList = styled(List)`
7686
background-color: rgba(139, 143, 163, 0.36);
7787
}
7888
`;
89+
7990
const IconRow = styled.div`
8091
padding: 0 6px;
8192
display: flex;
82-
align-items: center;
93+
align-items: flex-start; /* Align items to the start to allow different heights */
8394
justify-content: space-between;
8495
8596
&:last-child {
8697
gap: 8px;
8798
justify-content: flex-start;
8899
}
89100
`;
101+
90102
const IconItemContainer = styled.div`
91-
width: 40px;
92-
height: 40px;
103+
width: 60px;
93104
display: flex;
94-
align-items: center;
95-
justify-content: center;
105+
flex-direction: column;
106+
align-items: center;
107+
justify-content: flex-start;
96108
cursor: pointer;
97-
font-size: 20px;
109+
font-size: 28px;
110+
margin-bottom: 24px;
98111
99112
&:hover {
100113
border: 1px solid #315efb;
@@ -108,13 +121,41 @@ const IconItemContainer = styled.div`
108121
}
109122
`;
110123

124+
const IconWrapper = styled.div`
125+
height: auto;
126+
display: flex;
127+
align-items: center;
128+
justify-content: center;
129+
`;
130+
131+
const IconKeyDisplay = styled.div`
132+
font-size: 8px;
133+
color: #8b8fa3;
134+
margin-top: 4px; /* Space between the icon and the text */
135+
text-align: center;
136+
word-wrap: break-word; /* Ensure text wraps */
137+
width: 100%; /* Ensure the container can grow */
138+
`;
139+
111140
class Icon {
112141
readonly title: string;
113-
constructor(readonly def: IconDefinition, readonly names: string[]) {
114-
this.title = def.iconName.split("-").map(_.upperFirst).join(" ");
142+
constructor(readonly def: IconDefinition | any, readonly names: string[]) {
143+
if (def?.iconName) {
144+
this.title = def.iconName.split("-").map(_.upperFirst).join(" ");
145+
} else {
146+
this.title = names[0].slice(5);
147+
this.def = def;
148+
}
115149
}
116150
getView() {
117-
return <FontAwesomeIcon icon={this.def} style={{ width: "1em", height: "1em" }} />;
151+
if (this.names[0]?.startsWith("antd/")) return this.def;
152+
else
153+
return (
154+
<FontAwesomeIcon
155+
icon={this.def}
156+
style={{ width: "1em", height: "1em"}}
157+
/>
158+
);
118159
}
119160
}
120161

@@ -127,6 +168,7 @@ async function getAllIcons() {
127168
const [{ far }, { fas }] = await Promise.all([
128169
import("@fortawesome/free-regular-svg-icons"),
129170
import("@fortawesome/free-solid-svg-icons"),
171+
// import("@fontawesome/free-brands-svg-icons"),
130172
]);
131173
const ret: Record<string, Icon> = {};
132174
for (const [type, pack] of Object.entries({ solid: fas, regular: far })) {
@@ -144,14 +186,25 @@ async function getAllIcons() {
144186
}
145187
}
146188
}
189+
//append ant icon
190+
for (let key of Object.keys(ANTDICON)) {
191+
ret["antd/" + key] = new Icon(
192+
ANTDICON[key.toLowerCase() as keyof typeof ANTDICON],
193+
["antd/" + key]
194+
);
195+
}
147196
allIcons = ret;
148197
return ret;
149198
}
150199

151200
export const iconPrefix = "/icon:";
152201

153202
export function removeQuote(value?: string) {
154-
return value ? (value.startsWith('"') && value.endsWith('"') ? value.slice(1, -1) : value) : "";
203+
return value
204+
? value.startsWith('"') && value.endsWith('"')
205+
? value.slice(1, -1)
206+
: value
207+
: "";
155208
}
156209

157210
function getIconKey(value?: string) {
@@ -171,7 +224,8 @@ export function useIcon(value?: string) {
171224
function search(
172225
allIcons: Record<string, Icon>,
173226
searchText: string,
174-
searchKeywords?: Record<string, string>
227+
searchKeywords?: Record<string, string>,
228+
IconType?: "OnlyAntd" | "All" | "default" | undefined
175229
) {
176230
const tokens = searchText
177231
.toLowerCase()
@@ -182,6 +236,8 @@ function search(
182236
if (icon.names.length === 0) {
183237
return false;
184238
}
239+
if (IconType === "OnlyAntd" && !key.startsWith("antd/")) return false;
240+
if (IconType === "default" && key.startsWith("antd/")) return false;
185241
let text = icon.names
186242
.flatMap((name) => [name, searchKeywords?.[name]])
187243
.filter((t) => t)
@@ -198,43 +254,54 @@ const IconPopup = (props: {
198254
label?: ReactNode;
199255
onClose: () => void;
200256
searchKeywords?: Record<string, string>;
257+
IconType?: "OnlyAntd" | "All" | "default" | undefined;
201258
}) => {
202259
const [searchText, setSearchText] = useState("");
203260
const [allIcons, setAllIcons] = useState<Record<string, Icon>>({});
204261
const searchResults = useMemo(
205-
() => search(allIcons, searchText, props.searchKeywords),
262+
() => search(allIcons, searchText, props.searchKeywords, props.IconType),
206263
[searchText, allIcons]
207264
);
208265
const onChangeRef = useRef(props.onChange);
209266
onChangeRef.current = props.onChange;
210-
const onChangeIcon = useCallback((key: string) => onChangeRef.current(iconPrefix + key), []);
267+
const onChangeIcon = useCallback(
268+
(key: string) => onChangeRef.current(iconPrefix + key),
269+
[]
270+
);
211271
const columnNum = 8;
212272

213273
useEffect(() => {
214274
getAllIcons().then(setAllIcons);
215275
}, []);
216276

277+
const smallTextStyle = {
278+
fontSize: '8px'
279+
};
280+
217281
const rowRenderer = useCallback(
218282
(p: ListRowProps) => (
219283
<IconRow key={p.key} style={p.style}>
220-
{searchResults.slice(p.index * columnNum, (p.index + 1) * columnNum).map(([key, icon]) => (
221-
<Tooltip
222-
key={key}
223-
title={icon.title}
224-
placement="bottom"
225-
align={{ offset: [0, -7, 0, 0] }}
226-
destroyTooltipOnHide
227-
>
228-
<IconItemContainer
229-
tabIndex={0}
230-
onClick={() => {
231-
onChangeIcon(key);
232-
}}
284+
{searchResults
285+
.slice(p.index * columnNum, (p.index + 1) * columnNum)
286+
.map(([key, icon]) => (
287+
<Tooltip
288+
key={key}
289+
title={icon.title + ", Key: " + key}
290+
placement="bottom"
291+
align={{ offset: [0, -7, 0, 0] }}
292+
destroyTooltipOnHide
233293
>
234-
{icon.getView()}
235-
</IconItemContainer>
236-
</Tooltip>
237-
))}
294+
<IconItemContainer
295+
tabIndex={0}
296+
onClick={() => {
297+
onChangeIcon(key);
298+
}}
299+
>
300+
<IconWrapper>{icon.getView()}</IconWrapper>
301+
<IconKeyDisplay>{key}</IconKeyDisplay>
302+
</IconItemContainer>
303+
</Tooltip>
304+
))}
238305
</IconRow>
239306
),
240307
[searchResults, allIcons, onChangeIcon]
@@ -257,9 +324,9 @@ const IconPopup = (props: {
257324
</SearchDiv>
258325
<IconListWrapper>
259326
<IconList
260-
width={394}
261-
height={312}
262-
rowHeight={48}
327+
width={550}
328+
height={400}
329+
rowHeight={80}
263330
rowCount={Math.ceil(searchResults.length / columnNum)}
264331
rowRenderer={rowRenderer}
265332
/>
@@ -279,6 +346,7 @@ export const IconSelectBase = (props: {
279346
leftOffset?: number;
280347
parent?: HTMLElement | null;
281348
searchKeywords?: Record<string, string>;
349+
IconType?: "OnlyAntd" | "All" | "default" | undefined;
282350
}) => {
283351
const { setVisible, parent } = props;
284352
return (
@@ -290,7 +358,11 @@ export const IconSelectBase = (props: {
290358
onOpenChange={setVisible}
291359
getPopupContainer={parent ? () => parent : undefined}
292360
// hide the original background when dragging the popover is allowed
293-
overlayInnerStyle={{ border: "none", boxShadow: "none", background: "transparent" }}
361+
overlayInnerStyle={{
362+
border: "none",
363+
boxShadow: "none",
364+
background: "transparent",
365+
}}
294366
// when dragging is allowed, always re-location to avoid the popover exceeds the screen
295367
destroyTooltipOnHide
296368
content={
@@ -299,6 +371,7 @@ export const IconSelectBase = (props: {
299371
label={props.label}
300372
onClose={() => setVisible?.(false)}
301373
searchKeywords={props.searchKeywords}
374+
IconType={props.IconType}
302375
/>
303376
}
304377
>
@@ -312,6 +385,7 @@ export const IconSelect = (props: {
312385
label?: ReactNode;
313386
children?: ReactNode;
314387
searchKeywords?: Record<string, string>;
388+
IconType?: "OnlyAntd" | "All" | "default" | undefined;
315389
}) => {
316390
const [visible, setVisible] = useState(false);
317391
return (
Lines changed: 1 addition & 0 deletions
Loading

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

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -280,6 +280,7 @@ export { ReactComponent as SignatureIcon } from "./icon-signature.svg";
280280
export { ReactComponent as ManualIcon } from "./icon-manual.svg";
281281
export { ReactComponent as WarnIcon } from "./icon-warn.svg";
282282
export { ReactComponent as SyncManualIcon } from "./icon-sync-manual.svg";
283+
export { ReactComponent as IconCompIcon } from "icons/IconCompIcon.svg";
283284
export { ReactComponent as DangerIcon } from "./icon-danger.svg";
284285
export { ReactComponent as TableMinusIcon } from "./icon-table-minus.svg";
285286
export { ReactComponent as TablePlusIcon } from "./icon-table-plus.svg";
@@ -614,4 +615,5 @@ export { ReactComponent as MentionIcon } from "./icon-mention-comp.svg";
614615
export { ReactComponent as AutoCompleteCompIcon } from "./icon-autocomplete-comp.svg";
615616
export { ReactComponent as WidthIcon } from "./icon-width.svg";
616617
export { ReactComponent as ResponsiveLayoutCompIcon } from "./remix/layout-column-line.svg"; // Closest match for responsive layout component
617-
export { ReactComponent as TextSizeIcon } from "./icon-text-size.svg"; */
618+
export { ReactComponent as TextSizeIcon } from "./icon-text-size.svg"; */
619+

client/packages/lowcoder/package.json

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
"main": "src/index.sdk.ts",
77
"types": "src/index.sdk.ts",
88
"dependencies": {
9-
"@ant-design/icons": "^4.7.0",
9+
"@ant-design/icons": "^5.3.0",
1010
"@codemirror/autocomplete": "^6.11.1",
1111
"@codemirror/commands": "^6.3.2",
1212
"@codemirror/lang-css": "^6.2.1",
@@ -19,9 +19,10 @@
1919
"@dnd-kit/modifiers": "^5.0.0",
2020
"@dnd-kit/sortable": "^6.0.0",
2121
"@dnd-kit/utilities": "^3.1.0",
22-
"@fortawesome/fontawesome-svg-core": "^6.4.0",
23-
"@fortawesome/free-regular-svg-icons": "^6.4.0",
24-
"@fortawesome/free-solid-svg-icons": "^6.4.0",
22+
"@fortawesome/fontawesome-svg-core": "^6.5.1",
23+
"@fortawesome/free-brands-svg-icons": "^6.5.1",
24+
"@fortawesome/free-regular-svg-icons": "^6.5.1",
25+
"@fortawesome/free-solid-svg-icons": "^6.5.1",
2526
"@fortawesome/react-fontawesome": "latest",
2627
"@manaflair/redux-batch": "^1.0.0",
2728
"@rjsf/antd": "^5.15.1",

0 commit comments

Comments
 (0)