aboutsummaryrefslogtreecommitdiff
path: root/apps/website/src/components/icons/Icon.astro
blob: b186a768ef639c077f703b500f30a10a7e4769a4 (plain)
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
---
import type { HTMLAttributes } from 'astro/types';
import { parse } from 'node-html-parser';

type _ModIcons =
	| 'chatting'
	| 'polysprint'
	| 'vanillahud'
	| 'overflowanimations'
	| 'crashpatch'
	| 'polytime'
	| 'polyweather'
	| 'keystrokes';
export type ModIcons = _ModIcons; // bypass for Astro compiler issue https://github.com/withastro/compiler/issues/554#issuecomment-1741702411

type _External =
	| 'discord'
	| 'github'
	| 'youtube'
	| 'twitter';

export type External = _External;

type _Icons =
	| 'chevron-down'
	| 'download'
	| 'book-open'
	| 'link-external'
	| External
	| ModIcons;
export type Icons = _Icons; // bypass for Astro compiler issue https://github.com/withastro/compiler/issues/554#issuecomment-1741702411

interface Props extends HTMLAttributes<'svg'> {
	icon: Icons
	path?: string
	size?: number | [number, number]
}

async function getSVG(name: string, path = 'impl') {
	const file = await import(`./${path}/${name}.svg?raw`);

	if (!file)
		throw new Error(`${name} not found`);

	const content = parse(file.default);

	const svg = content.querySelector('svg');

	if (!svg)
		throw new Error(`${name} is not a valid SVG`);

	const { attributes, innerHTML } = svg;

	return {
		attributes,
		innerHTML,
	};
}

const {
	icon,
	size,
	path = 'impl',
	...attributes
} = Astro.props as Props;

let svgAttributes = {};
let html = '';

try {
	const sizeAttributes = () => {
		if (!size)
			return {};

		if (Array.isArray(size)) {
			return {
				width: size[0],
				height: size[1],
			};
		}

		return {
			width: size,
			height: size,
		};
	};

	const { attributes: baseAttributes, innerHTML } = await getSVG(icon, path);
	svgAttributes = {
		...baseAttributes,
		...attributes,
		...sizeAttributes(),
	};

	const colorRegex = /(fill|stroke)=\"([^"]*)\"/g;
	html = innerHTML.replaceAll(colorRegex, '$1="currentColor"');
}
catch (err) {
	// ignored
}
---

	<svg {...svgAttributes} set:html={html}></svg>