Skip to content

Commit fc6a843

Browse files
Merge pull request #204 from gridaco/designer/icon
Icons loader update: New icons set from Unicons (by IconScout) Radix-UI Icons for Editor apps.
2 parents e9b2eb2 + bfef3c5 commit fc6a843

File tree

12 files changed

+842
-442
lines changed

12 files changed

+842
-442
lines changed

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,12 @@
2828
- [Flutter] Poligon Node support with XImage (svg)
2929
- [Lint] Primal naming & grouping linting for better code export quality. this is tracked sperately on [lint](https://github.com/bridgedxyz/lint)
3030

31+
## [2022.12.0.1] - 2022-12-6 (schduled)
32+
33+
- New Icons set added.
34+
- Unicon Icons
35+
- Radix-ui Icons
36+
3137
## [2022.4.0.3] - 2022-04-29
3238

3339
- New feature: Publish as website

figma-core/event-handlers/create-icon.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import { NamedIconConfig } from "@reflect-ui/core";
21
import { EK_CREATE_ICON, EK_ICON_DRAG_AND_DROPPED } from "@core/constant";
32
import { PluginSdkService } from "@plugin-sdk/service";
43
import { IconPlacement, renderSvgIcon } from "../reflect-render/icons.render";
@@ -7,7 +6,12 @@ import { addEventHandler } from "../code-thread";
76
interface CreateIconProps {
87
key: string;
98
svg: string;
10-
config: NamedIconConfig;
9+
config: {
10+
name: string;
11+
size: number;
12+
variant?: string;
13+
package: string;
14+
};
1115
}
1216

1317
function createIcon(

figma-core/reflect-render/icons.render/index.ts

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ export function renderSvgIcon(
1818
data: string,
1919
color: Color = "#000000",
2020
placement: IconPlacement = "center",
21-
config?: NamedIconConfig
21+
config?: { size: number; name: string; package: string; variant?: string }
2222
): FrameNode {
2323
console.log(`inserting icon with name ${name} and data ${data}`);
2424

@@ -47,7 +47,7 @@ export function renderSvgIcon(
4747

4848
// operate extra manipulation if config is available.
4949
if (config) {
50-
const size = Number(config.default_size);
50+
const size = Number(config.size);
5151
node.resize(size, size);
5252
}
5353

@@ -62,14 +62,19 @@ export function renderSvgIcon(
6262

6363
export function buildReflectIconNameForRender(
6464
name: string,
65-
config: NamedIconConfig
65+
config: { name: string; package: string; variant?: string }
6666
): string {
67-
if (config.host == "material") {
68-
return `icons/mdi_${name}`;
69-
} else if (config.host == "ant-design") {
70-
return `icons/antd-${name}`;
71-
} else {
72-
return `icons/${name}`;
67+
switch (config.package) {
68+
case "material":
69+
return `icons/mdi_${name}`;
70+
case "ant-design":
71+
return `icons/antd-${name}`;
72+
case "radix-ui":
73+
return `icons/radix-${name}`;
74+
case "unicons":
75+
return `icons/unicons-${name}`;
76+
default:
77+
return `icons/${name}`;
7378
}
7479
}
7580

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
// save recently used items
2+
3+
import type { Icon } from "./resources";
4+
5+
const _k_store_key = "icons-load-history";
6+
7+
export class IconsLoadHistory {
8+
private readonly data: Array<Icon> = [];
9+
10+
constructor(readonly max: number = 50) {
11+
const items = localStorage.getItem(_k_store_key);
12+
if (items) {
13+
this.data = JSON.parse(items);
14+
}
15+
}
16+
17+
list(to: number = Infinity): Array<Icon> {
18+
return Array.from(this.data).reverse().slice(0, to);
19+
}
20+
21+
push(item: Icon) {
22+
const index = this.data.findIndex(
23+
(i) =>
24+
i.package === item.package &&
25+
i.name === item.name &&
26+
i.variant === item.variant
27+
);
28+
if (index >= 0) {
29+
this.data.splice(index, 1);
30+
}
31+
this.data.push(item);
32+
33+
if (this.data.length > this.max) {
34+
this.data.shift();
35+
}
36+
37+
this.save();
38+
}
39+
40+
private save() {
41+
localStorage.setItem(_k_store_key, JSON.stringify(this.data));
42+
}
43+
}
Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
import React, { useEffect, useRef, useState } from "react";
2+
import Tooltip from "@material-ui/core/Tooltip";
3+
import {
4+
EK_CREATE_ICON,
5+
EK_ICON_DRAG_AND_DROPPED,
6+
} from "@core/constant/ek.constant";
7+
import CircularProgress from "@material-ui/core/CircularProgress";
8+
import { Draggable } from "@plugin-sdk/draggable";
9+
import { assistant as analytics } from "@analytics.bridged.xyz/internal";
10+
import styled from "@emotion/styled";
11+
import { IconMeta, Icon, loadSvg, makeIconUrl, useIcons } from "./resources";
12+
13+
type IconItemProps = Icon & { onClick: () => void };
14+
15+
export function IconItem({ onClick, ...props }: IconItemProps) {
16+
const { package: _package, name, variant } = props;
17+
const [loading, setLoading] = useState(false);
18+
const [loaded, setLoaded] = useState(false);
19+
const [downloading, setDownloading] = useState<boolean>(false);
20+
21+
const _aid = name + " " + variant; // id for analytics
22+
23+
useEffect(() => {
24+
setTimeout(() => {
25+
setLoading(!loaded);
26+
}, 5);
27+
}, [loaded]);
28+
29+
const _onUserLoadIconToCanvas = () => {
30+
// ANALYTICS
31+
analytics.event_load_icon({
32+
icon_name: _aid,
33+
});
34+
};
35+
36+
async function loadData() {
37+
_onUserLoadIconToCanvas();
38+
try {
39+
setDownloading(true);
40+
const svg = await loadSvg(props, {
41+
disable_cache: true,
42+
});
43+
const data = {
44+
key: name,
45+
svg: svg,
46+
config: {
47+
name: props.name,
48+
variant: props.variant,
49+
size: props.size,
50+
package: props.package,
51+
},
52+
};
53+
return data;
54+
} catch (_) {
55+
throw _;
56+
} finally {
57+
setDownloading(false);
58+
}
59+
}
60+
61+
const onclick = () => {
62+
onClick();
63+
_onUserLoadIconToCanvas();
64+
loadData().then((d) => {
65+
parent.postMessage(
66+
{
67+
pluginMessage: {
68+
type: EK_CREATE_ICON,
69+
data: d,
70+
},
71+
},
72+
"*"
73+
);
74+
});
75+
};
76+
77+
return (
78+
<Draggable customDataLoader={loadData} eventKey={EK_ICON_DRAG_AND_DROPPED}>
79+
<Tooltip
80+
title={`${name} (${variant ?? "default"}) (${_package})`}
81+
placement="top"
82+
PopperProps={{
83+
popperOptions: {
84+
modifiers: {
85+
offset: {
86+
offset: "-1px, -20px",
87+
},
88+
},
89+
},
90+
}}
91+
>
92+
<IconButton onClick={onclick} disabled={downloading}>
93+
{downloading ? (
94+
<CircularProgress size={24} />
95+
) : (
96+
<svg
97+
width="24"
98+
height="24"
99+
style={{
100+
borderRadius: 4,
101+
background: loading ? "rgba(0, 0, 0, 0.1)" : "none",
102+
transition: "background 0.3s",
103+
}}
104+
>
105+
<image
106+
className="unicons"
107+
xlinkHref={makeIconUrl(props)}
108+
onLoad={() => setLoaded(true)}
109+
width="24"
110+
height="24"
111+
/>
112+
</svg>
113+
)}
114+
</IconButton>
115+
</Tooltip>
116+
</Draggable>
117+
);
118+
}
119+
120+
const IconButton = styled.button`
121+
background-color: #fff;
122+
border: none;
123+
height: 48px !important;
124+
width: 48px;
125+
display: flex;
126+
align-items: center;
127+
justify-content: center;
128+
129+
&:hover {
130+
background-color: #eeeeee;
131+
border-radius: 8px;
132+
display: flex;
133+
align-items: center;
134+
justify-content: center;
135+
transition: 0.25s;
136+
}
137+
`;

0 commit comments

Comments
 (0)