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

Commit 5295375

Browse files
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)

AltStyle によって変換されたページ (->オリジナル) /