-
-
Notifications
You must be signed in to change notification settings - Fork 0
/
simple-icons.tsx
124 lines (109 loc) · 3.15 KB
/
simple-icons.tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
import {addPropertyControls, ControlType} from 'framer';
import React, {useState, useEffect, useRef} from 'react';
import {titleToSlug} from 'simple-icons/sdk';
type Icon = {
title: string;
hex: string;
slug?: string;
};
const getIconKey = (slug: string) => {
return 'si' + slug.charAt(0).toUpperCase() + slug.slice(1);
};
const latestListResponse = await fetch(
'https://cdn.jsdelivr.net/npm/simple-icons@latest/_data/simple-icons.json',
{cache: 'no-cache'},
);
const latestJson = (await latestListResponse.json()) as {icons: Icon[]};
const allSlugs = latestJson.icons.map(
(icon) => icon.slug ?? titleToSlug(icon.title),
);
const allTitles = latestJson.icons.map((icon) => icon.title);
const icons: Record<string, Icon> = Object.fromEntries(
latestJson.icons.map((icon) => {
const slug = icon.slug ?? titleToSlug(icon.title);
return [getIconKey(slug), icon];
}),
);
// Prepare icons data
const iconSlugs: string[] = allSlugs;
const iconNames: string[] = allTitles;
const getIconBrandColor = (slug: string) => {
const icon = icons[getIconKey(slug)]!;
return '#' + icon.hex;
};
/**
* @framerSupportedLayoutWidth fixed
* @framerSupportedLayoutHeight fixed
*/
export default function SimpleIcons({
icon = 'framer',
color = 'brand',
customColor = '#757575',
}: {
icon?: string;
color?: string;
customColor?: string;
}): JSX.Element {
// Fetch icon SVG from jsDelivr.
// This is used instead of cdn.simpleicons.org because it has CORS errors when fetching.
const url = `https://cdn.jsdelivr.net/npm/simple-icons@latest/icons/${icon}.svg`;
const [svgElement, setSvgElement] = useState<HTMLElement>();
const svgReference = useRef<HTMLDivElement>(null);
const brandColor = getIconBrandColor(icon);
useEffect(() => {
// eslint-disable-next-line @typescript-eslint/no-floating-promises
fetch(url)
.then(async (response) => response.text())
.then((data) => {
const parser = new DOMParser();
const svgDocument = parser.parseFromString(data, 'image/svg+xml');
setSvgElement(svgDocument.documentElement);
console.log(svgElement);
});
}, [url]);
useEffect(() => {
if (svgElement) {
const existingSvgElement = svgReference.current?.querySelector('svg');
if (existingSvgElement) {
existingSvgElement.remove();
}
Object.assign(svgElement.style, {
fill: color === 'custom' ? customColor : brandColor,
});
svgReference.current?.append(svgElement);
}
}, [svgElement]);
useEffect(() => {
if (svgElement) {
Object.assign(svgElement.style, {
fill: color === 'custom' ? customColor : brandColor,
});
}
}, [color, customColor]);
return <div ref={svgReference} />;
}
addPropertyControls(SimpleIcons, {
icon: {
type: ControlType.Enum,
defaultValue: 'framer',
description:
'Find every icon name on the [Simple Icons site](https://simpleicons.org/)',
options: iconSlugs,
optionTitles: iconNames,
},
color: {
type: ControlType.Enum,
defaultValue: 'brand',
options: ['brand', 'custom'],
optionTitles: ['Brand', 'Custom'],
displaySegmentedControl: true,
},
customColor: {
type: ControlType.Color,
defaultValue: '#757575',
title: 'Custom',
hidden({color}) {
return color !== 'custom';
},
},
});