Skip to content

Commit abbb6ec

Browse files
authored
Merge pull request #19 from author-more/feat/add-icons-core-ui
feat: add icons - coreui
2 parents af96231 + 77d7540 commit abbb6ec

File tree

10 files changed

+93
-20
lines changed

10 files changed

+93
-20
lines changed

bin/config.ts

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,12 @@
1-
export const iconPackages = [
1+
type IconPackage = {
2+
id: string;
3+
variant?: string;
4+
iconsDir: string;
5+
getVariantFromIconName?: (iconName: string) => string;
6+
normaliseAttributes?: (svg: string) => string;
7+
};
8+
9+
export const iconPackages: IconPackage[] = [
210
{
311
id: "lucide",
412
variant: "regular",
@@ -50,4 +58,11 @@ export const iconPackages = [
5058
variant: "regular",
5159
iconsDir: "../node_modules/feather-icons/dist/icons",
5260
},
61+
...["free", "flag"].map((variant) => ({
62+
id: `core-ui`,
63+
variant,
64+
iconsDir: `../node_modules/@coreui/icons/svg/${variant}`,
65+
normaliseAttributes: (svg: string) =>
66+
svg.replace(/fill="var\(--ci-primary-color, currentColor\)"/g, ""),
67+
})),
5368
];

bin/generateIconSets.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,15 +14,17 @@ iconPackages.forEach(
1414
iconsDir,
1515
variant,
1616
getVariantFromIconName,
17+
normaliseAttributes,
1718
}: (typeof iconPackages)[number]) => {
1819
const files = getFilesByExtension(iconsDir, ".svg");
1920

2021
const icons: Record<string, Record<string, Icon>> = {};
2122
for (const file of files) {
2223
const svg = readFile(iconsDir, file);
2324

24-
const attributes = svg.match(/<svg([^>]*)>/)?.[1];
25-
const elements = svg.match(/<svg[^>]*>([\s\S]*)<\/svg>/)?.[1];
25+
const svgNormalised = normaliseAttributes?.(svg) || svg;
26+
const attributes = svgNormalised.match(/<svg([^>]*)>/)?.[1];
27+
const elements = svgNormalised.match(/<svg[^>]*>([\s\S]*)<\/svg>/)?.[1];
2628

2729
if (!attributes || !elements) {
2830
throw new Error(`Failed to parse the SVG: ${file}`);

package-lock.json

Lines changed: 7 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
"generate-data": "tsx ./bin/generateIconSets.ts"
1414
},
1515
"dependencies": {
16+
"@coreui/icons": "^3.0.1",
1617
"@material-design-icons/svg": "^0.14.13",
1718
"@penpot/plugin-styles": "^0.10.0",
1819
"@phosphor-icons/core": "^2.1.1",

src/App.tsx

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,16 @@ import {
1010
iconLibraries,
1111
defaultIconSetSettings,
1212
getIconSetsByVariant,
13-
DEFAULT_ICON_SIZE,
1413
DATA_KEY_ICON_SETS_SETTINGS,
14+
getNormalisedIconSize,
1515
} from "./icons";
1616
import Select from "./Select";
1717
import LinkTag from "./LinkTag";
1818
import { toSortedBy } from "./sort";
1919
import { Bug, ChevronDown, ChevronRight, Lightbulb } from "lucide-react";
2020
import { sendMessage } from "./window";
2121
import { filterByPhrase } from "./search";
22+
import { parseAttributes } from "./dataStructure";
2223

2324
function App() {
2425
const url = new URL(window.location.href);
@@ -112,19 +113,23 @@ function App() {
112113
svg: { attributes, elements },
113114
},
114115
]) => {
116+
const parsedAttributes =
117+
parseAttributes(`${attributes} ${customSvgAttributes}`) || {};
118+
115119
const svg = `<svg ${attributes}>${elements}</svg>`;
116120
const icon = (
117-
<Icon
118-
attributes={`${attributes} ${customSvgAttributes}`}
119-
elements={elements}
120-
/>
121+
<Icon attributes={parsedAttributes} elements={elements} />
122+
);
123+
const size = getNormalisedIconSize(
124+
parseInt(parsedAttributes.width, 10),
125+
parseInt(parsedAttributes.height, 10),
121126
);
122127

123128
return (
124129
<IconButton
125130
key={`icon-${name}`}
126131
label={`Insert icon: ${name}`}
127-
onClick={() => handleIconButtonClick(name, svg)}
132+
onClick={() => handleIconButtonClick(name, svg, size)}
128133
onMouseEnter={() => setHoveredIcon({ name, library })}
129134
onMouseLeave={() => setHoveredIcon(null)}
130135
>
@@ -135,8 +140,12 @@ function App() {
135140
);
136141
}
137142

138-
function handleIconButtonClick(name: string, svg: string) {
139-
sendMessage("insert-icon", { name, svg, size: DEFAULT_ICON_SIZE });
143+
function handleIconButtonClick(
144+
name: string,
145+
svg: string,
146+
size: { width: number; height: number },
147+
) {
148+
sendMessage("insert-icon", { name, svg, size });
140149
}
141150

142151
function toggleShowIcons(id: string) {

src/Icon.css

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
svg {
2+
height: auto;
3+
}

src/Icon.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
1-
import { parseAttributes } from "./dataStructure";
1+
import "./Icon.css";
22

33
type IconProps = {
4-
attributes: string;
4+
attributes: Record<string, string>;
55
elements: string;
66
};
77

88
export default function Icon({ attributes, elements }: IconProps) {
9-
const { class: className, ...rest } = parseAttributes(attributes) || {};
9+
const { class: className, ...rest } = attributes || {};
1010

1111
return (
1212
<svg

src/icons.ts

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,22 @@ export const iconLibraries: IconLibrary[] = [
141141
},
142142
icons: generateVariants("feather", ["regular"]),
143143
},
144+
{
145+
id: "core-ui",
146+
name: "CoreUI Free",
147+
website: "https://coreui.io/icons/",
148+
license: {
149+
name: "CC BY 4.0, CC0 1.0 Universal",
150+
url: "https://github.com/coreui/coreui-icons/blob/main/LICENSE",
151+
},
152+
icons: generateVariants("core-ui", ["free", "flag"]),
153+
iconSettings: {
154+
svg: {
155+
attributes: 'fill="currentColor"',
156+
},
157+
},
158+
defaultSettings: { selectedVariant: "free" },
159+
},
144160
];
145161

146162
export const defaultIconSetSettings: Record<string, IconSetSettings> =
@@ -207,3 +223,15 @@ export function getVariantOptions(icons: IconSetVariant[]) {
207223
value: variant,
208224
}));
209225
}
226+
227+
export function getNormalisedIconSize(
228+
originalWidth: number,
229+
originalHeight: number,
230+
) {
231+
const ratio =
232+
originalWidth && originalHeight ? originalWidth / originalHeight : 1;
233+
const width = DEFAULT_ICON_SIZE;
234+
const height = Math.round(width / ratio);
235+
236+
return { width, height };
237+
}

src/plugin.ts

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,12 @@ type InsertIconPluginEvent = {
2222
content: {
2323
name: string;
2424
svg: string;
25-
size: number;
25+
size: IconSize;
2626
};
2727
};
2828

29+
type IconSize = { width: number; height: number };
30+
2931
type SetDataPluginEvent = {
3032
type: "set-plugin-data";
3133
content: PluginData;
@@ -71,18 +73,18 @@ penpot.ui.onMessage<PluginUIEvent>(({ type, content }) => {
7173
function insertIcon({
7274
name,
7375
svg,
74-
size,
76+
size: { width, height },
7577
}: {
7678
name: string;
7779
svg: string;
78-
size: number;
80+
size: IconSize;
7981
}) {
8082
const icon = penpot.createShapeFromSvg(svg);
8183
if (icon) {
8284
icon.name = name;
8385
icon.x = penpot.viewport.center.x;
8486
icon.y = penpot.viewport.center.y;
85-
icon.resize(size, size);
87+
icon.resize(width, height);
8688
}
8789
}
8890

tests/icon.spec.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,18 @@ const testIcons = [
55
{
66
name: "a-arrow-down",
77
svg: '<svg class="lucide lucide-a-arrow-down" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M3.5 13h6" /> <path d="m2 16 4.5-9 4.5 9" /> <path d="M18 7v9" /> <path d="m14 12 4 4 4-4" /></svg>',
8-
size: 24,
8+
size: {
9+
width: 24,
10+
height: 24,
11+
},
912
},
1013
{
1114
name: "pickaxe",
1215
svg: '<svg class="lucide lucide-pickaxe" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M14.531 12.469 6.619 20.38a1 1 0 1 1-3-3l7.912-7.912" /> <path d="M15.686 4.314A12.5 12.5 0 0 0 5.461 2.958 1 1 0 0 0 5.58 4.71a22 22 0 0 1 6.318 3.393" /> <path d="M17.7 3.7a1 1 0 0 0-1.4 0l-4.6 4.6a1 1 0 0 0 0 1.4l2.6 2.6a1 1 0 0 0 1.4 0l4.6-4.6a1 1 0 0 0 0-1.4z" /> <path d="M19.686 8.314a12.501 12.501 0 0 1 1.356 10.225 1 1 0 0 1-1.751-.119 22 22 0 0 0-3.393-6.319" /></svg>',
13-
size: 24,
16+
size: {
17+
width: 24,
18+
height: 24,
19+
},
1420
},
1521
];
1622

0 commit comments

Comments
 (0)