mirror of
https://github.com/lucide-icons/lucide.git
synced 2025-12-17 16:37:42 +01:00
Compare commits
578 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ba77aa6a76 | ||
|
|
42f36a9da3 | ||
|
|
9abed5ee16 | ||
|
|
e6246ed5c6 | ||
|
|
877b467d96 | ||
|
|
781620d669 | ||
|
|
3ad1f07ffc | ||
|
|
47880403d3 | ||
|
|
89d204a35d | ||
|
|
bdcd417c1c | ||
|
|
4c7738fea1 | ||
|
|
12e7cfd7f7 | ||
|
|
09841dd721 | ||
|
|
8ae65a8fb1 | ||
|
|
fda32bee52 | ||
|
|
e913eab8bb | ||
|
|
2408b8bb8f | ||
|
|
8b257abaf6 | ||
|
|
c00ef3a835 | ||
|
|
0d3c8f4ea2 | ||
|
|
771cb0bbd6 | ||
|
|
3f34f4e7b6 | ||
|
|
e4f411ce9c | ||
|
|
0f47888a17 | ||
|
|
81ce8fed07 | ||
|
|
03b3a4f179 | ||
|
|
24178ca1bc | ||
|
|
e91dd659f0 | ||
|
|
6277ceb274 | ||
|
|
45b22c9f2d | ||
|
|
3a375e1a17 | ||
|
|
ac09719ba6 | ||
|
|
8d8c41c371 | ||
|
|
951c142e96 | ||
|
|
dcdc0b8bb3 | ||
|
|
e11e134ce1 | ||
|
|
e149de42ff | ||
|
|
5baa37b85a | ||
|
|
7916c44484 | ||
|
|
922ba5c781 | ||
|
|
c9c1b47e7a | ||
|
|
03eb86287a | ||
|
|
1ab3826607 | ||
|
|
2fde138c46 | ||
|
|
2640a7c585 | ||
|
|
25ce89b191 | ||
|
|
fd3f3eb607 | ||
|
|
b473c10af9 | ||
|
|
a01c15cc8c | ||
|
|
0fccc276c3 | ||
|
|
06c33964cb | ||
|
|
232d7b4557 | ||
|
|
3205e11173 | ||
|
|
0778ec87ad | ||
|
|
85983552ee | ||
|
|
7b954807da | ||
|
|
9105f0e3dd | ||
|
|
fe57bdd291 | ||
|
|
34cb6b12f8 | ||
|
|
6a8591c348 | ||
|
|
547b1846ae | ||
|
|
187ce5cff8 | ||
|
|
40f544433b | ||
|
|
05fa11e073 | ||
|
|
e4988bc1df | ||
|
|
3a24adec64 | ||
|
|
a620a0b08c | ||
|
|
2cc06fa703 | ||
|
|
9aac2e8424 | ||
|
|
2517eb642c | ||
|
|
7acf492f63 | ||
|
|
abe8910247 | ||
|
|
b35b16e96e | ||
|
|
b49c387cfe | ||
|
|
61d6f93023 | ||
|
|
1a3e9f273e | ||
|
|
8023c01f37 | ||
|
|
674a6bf799 | ||
|
|
e3a476a027 | ||
|
|
a021c1dbce | ||
|
|
a5ea7932dc | ||
|
|
6eb67bde5a | ||
|
|
19eb810537 | ||
|
|
6c865ccd9a | ||
|
|
667c80b39f | ||
|
|
dbada2a227 | ||
|
|
849d9c8af2 | ||
|
|
d61d47470f | ||
|
|
8b80cf2cef | ||
|
|
41f6c26228 | ||
|
|
02efe87c5a | ||
|
|
dc39f3d96a | ||
|
|
9879d8f4ed | ||
|
|
f95afd258a | ||
|
|
6ca07ea1bc | ||
|
|
3ff082cfd9 | ||
|
|
f776aaa9bc | ||
|
|
1587bee16d | ||
|
|
c78686ceca | ||
|
|
a11ba9e1cd | ||
|
|
99d992678a | ||
|
|
14822456aa | ||
|
|
64d6b10239 | ||
|
|
0232ce490d | ||
|
|
9d9e2c995a | ||
|
|
c68ee7f9a0 | ||
|
|
5f5e052038 | ||
|
|
aeb376f3a2 | ||
|
|
ed733916f3 | ||
|
|
64a8b7d4d0 | ||
|
|
c138c2e97d | ||
|
|
d82718b222 | ||
|
|
acdcf74faf | ||
|
|
9fa525e8c6 | ||
|
|
20c0012e62 | ||
|
|
70248c0f42 | ||
|
|
f8af6ae309 | ||
|
|
e8f64d8dcc | ||
|
|
4ea41dc329 | ||
|
|
4835ae67a9 | ||
|
|
6d6aa4c4cc | ||
|
|
70dad77b96 | ||
|
|
cc09030f9d | ||
|
|
73a6c8045d | ||
|
|
fccfaa3dd0 | ||
|
|
14fec0e184 | ||
|
|
fcebb5c4db | ||
|
|
1058ea5ae3 | ||
|
|
e08a1f7973 | ||
|
|
07f9d3ea79 | ||
|
|
73a2c9da6c | ||
|
|
afa4176737 | ||
|
|
cb86576661 | ||
|
|
9b738c1cb6 | ||
|
|
aefb710e5c | ||
|
|
df063fa378 | ||
|
|
2c3b6754d5 | ||
|
|
47303ac790 | ||
|
|
3aab3b9b08 | ||
|
|
3d29ab9279 | ||
|
|
e0fbbb6f2d | ||
|
|
c1331798f5 | ||
|
|
ddad14a96d | ||
|
|
a17609b5e4 | ||
|
|
e619963183 | ||
|
|
56948fe7c2 | ||
|
|
68116414d0 | ||
|
|
16a18f7908 | ||
|
|
ae8af191f7 | ||
|
|
1787b82cfe | ||
|
|
0e49b2b88c | ||
|
|
bab52d7333 | ||
|
|
c96260d82a | ||
|
|
3c23331e9e | ||
|
|
5a7c49dc55 | ||
|
|
6ae047557e | ||
|
|
fa064306fa | ||
|
|
4f46f43379 | ||
|
|
fc87643aae | ||
|
|
6f4f47684f | ||
|
|
c6632ce8d7 | ||
|
|
a59c5de61a | ||
|
|
2bd0ae55fd | ||
|
|
3f2ad5b2a6 | ||
|
|
1250fc276d | ||
|
|
97f214934d | ||
|
|
34dfc63ce2 | ||
|
|
b46927e510 | ||
|
|
1828a392c8 | ||
|
|
3ab6c373a0 | ||
|
|
ba2c4b526f | ||
|
|
bde3f01e0b | ||
|
|
50630b3aaf | ||
|
|
e28426a871 | ||
|
|
eb158561d3 | ||
|
|
410ae434fa | ||
|
|
0801b89e4d | ||
|
|
a1d17eedc9 | ||
|
|
7481dd0a3f | ||
|
|
f9e93824f1 | ||
|
|
4ba4cf2f35 | ||
|
|
6b29716aa9 | ||
|
|
97bbe1d6b2 | ||
|
|
608da04bdf | ||
|
|
961404d5cc | ||
|
|
f3100b8af1 | ||
|
|
0df4e2991c | ||
|
|
2b8242fa14 | ||
|
|
27c667556b | ||
|
|
31c3fefc17 | ||
|
|
389fed8770 | ||
|
|
58c2e108c3 | ||
|
|
d5fe5a0ef4 | ||
|
|
db30ab89f4 | ||
|
|
fa7120cbe0 | ||
|
|
419d47019c | ||
|
|
655111e4aa | ||
|
|
ea0ac2f92b | ||
|
|
1a5ee439ef | ||
|
|
5947ca82d5 | ||
|
|
edf46adc9e | ||
|
|
94782f53c1 | ||
|
|
79bbfa958e | ||
|
|
970fc3d4be | ||
|
|
f12b0de177 | ||
|
|
67cbce66e9 | ||
|
|
b927275150 | ||
|
|
ea89735f67 | ||
|
|
53c61c0f48 | ||
|
|
4213367a37 | ||
|
|
bc22d17fa9 | ||
|
|
7773135308 | ||
|
|
4f740348cd | ||
|
|
ca50dd8bc8 | ||
|
|
6b19d52ab0 | ||
|
|
7fc3467761 | ||
|
|
ee575f6ae9 | ||
|
|
212b488dae | ||
|
|
4f038d5fe8 | ||
|
|
5ca6bc3385 | ||
|
|
15e4b6b69d | ||
|
|
407b55f57c | ||
|
|
6fc7297199 | ||
|
|
c21df35283 | ||
|
|
775359260c | ||
|
|
eaeef9ae37 | ||
|
|
636f966a98 | ||
|
|
1d5c725b58 | ||
|
|
d9a011994a | ||
|
|
c6c645ca7f | ||
|
|
91391eea7b | ||
|
|
49070b4d1f | ||
|
|
ae43473aa6 | ||
|
|
392bc961aa | ||
|
|
f238fe1b18 | ||
|
|
4d91fbb588 | ||
|
|
d939a7005d | ||
|
|
2c55c2ab93 | ||
|
|
cb60e31162 | ||
|
|
09cebe178d | ||
|
|
0f3fd12f16 | ||
|
|
4b0d17ad24 | ||
|
|
30fe706dd6 | ||
|
|
d6178fa471 | ||
|
|
855cb4985d | ||
|
|
9f99ea510f | ||
|
|
e2ee0c77e7 | ||
|
|
d041d5c2d2 | ||
|
|
8700418260 | ||
|
|
30077f913f | ||
|
|
bc09d5f283 | ||
|
|
88c757f540 | ||
|
|
f93beca595 | ||
|
|
b1777430b9 | ||
|
|
d30698cb38 | ||
|
|
d2f7a0931d | ||
|
|
98bbcc4b06 | ||
|
|
c253cb821b | ||
|
|
484dc38b0a | ||
|
|
11b95f883a | ||
|
|
b8cd54f1b2 | ||
|
|
98b3b6fae7 | ||
|
|
3ca465ee11 | ||
|
|
dcd19cedc9 | ||
|
|
8cea9feecc | ||
|
|
e80d98040f | ||
|
|
a1641a372b | ||
|
|
757bf0fb85 | ||
|
|
dd3aed1ecd | ||
|
|
4d98681f05 | ||
|
|
bde9e1cb6b | ||
|
|
a5e07c28bd | ||
|
|
2a68b12cbe | ||
|
|
493382b4fd | ||
|
|
6588971ead | ||
|
|
13cea45e8b | ||
|
|
5dfcfc8d1a | ||
|
|
db24b1d517 | ||
|
|
e1202b545e | ||
|
|
2e1a5cf6ea | ||
|
|
f49ecd73a5 | ||
|
|
a72cbc2d49 | ||
|
|
d4976890e5 | ||
|
|
8c8d1d3338 | ||
|
|
542507f835 | ||
|
|
c6a4908ed0 | ||
|
|
b6e71c6c7a | ||
|
|
7de43440ee | ||
|
|
c8d5260d54 | ||
|
|
0c912bd7ff | ||
|
|
3f24597a65 | ||
|
|
590d59ac5f | ||
|
|
85d427d846 | ||
|
|
478a624162 | ||
|
|
f0afdd4614 | ||
|
|
38e7431189 | ||
|
|
19dd912381 | ||
|
|
f70d5f5169 | ||
|
|
30e0d55b4a | ||
|
|
36a5a8b9ac | ||
|
|
e20e7a43ba | ||
|
|
e8ab1bc15b | ||
|
|
ef090c7dd4 | ||
|
|
65e49e2684 | ||
|
|
0ca2099113 | ||
|
|
9c99fd809c | ||
|
|
cd0d4e1f8a | ||
|
|
e1668804c9 | ||
|
|
efcede62e7 | ||
|
|
3c3f548ec1 | ||
|
|
0160bbe539 | ||
|
|
7837a04438 | ||
|
|
944e428630 | ||
|
|
aa4b1f06b4 | ||
|
|
b1087d3da0 | ||
|
|
fd8d69a129 | ||
|
|
379df75eda | ||
|
|
25707c7c47 | ||
|
|
cbb4ed985c | ||
|
|
d7d1074a60 | ||
|
|
79c2333b7f | ||
|
|
e3f78d73d8 | ||
|
|
e391973a70 | ||
|
|
5a2e3a20ee | ||
|
|
6e65118cd3 | ||
|
|
10c3662ff1 | ||
|
|
c7c6b479fc | ||
|
|
442e477a9a | ||
|
|
777166c06d | ||
|
|
8be94e7f86 | ||
|
|
07dd0bfdb1 | ||
|
|
3271972d97 | ||
|
|
915e8b5b6d | ||
|
|
6c32e47bea | ||
|
|
d4d90f0d4e | ||
|
|
3cf67355b4 | ||
|
|
66bc180c84 | ||
|
|
3c6a8c5118 | ||
|
|
8a088af570 | ||
|
|
cf5d6fc887 | ||
|
|
6052c88831 | ||
|
|
6272f4fd1f | ||
|
|
89070bfa44 | ||
|
|
4cae01a2f5 | ||
|
|
c2cc325f40 | ||
|
|
3143b24dff | ||
|
|
f0625d085e | ||
|
|
beddaa7cbb | ||
|
|
158212c130 | ||
|
|
1d5edc507d | ||
|
|
6f44a5d624 | ||
|
|
1c12bae0f5 | ||
|
|
fdcb73cb7a | ||
|
|
f2f685bd65 | ||
|
|
18d18361e8 | ||
|
|
45c3c00d1d | ||
|
|
45bc8c08da | ||
|
|
6676cdd513 | ||
|
|
eb93f112bd | ||
|
|
54a58881da | ||
|
|
568d0b2fa3 | ||
|
|
2d1be858c8 | ||
|
|
fa6ddf923f | ||
|
|
658b94e65a | ||
|
|
137ab5c885 | ||
|
|
83284d842a | ||
|
|
8993b0b174 | ||
|
|
1b2b66f1f3 | ||
|
|
0186afc0e6 | ||
|
|
36c68bd901 | ||
|
|
e8abed3fa7 | ||
|
|
b4af645560 | ||
|
|
8f65b7e6f4 | ||
|
|
3c3e3508ec | ||
|
|
01e5fd74e6 | ||
|
|
7c62c7c662 | ||
|
|
e92d5e2d40 | ||
|
|
3975020fd2 | ||
|
|
43dfe362b6 | ||
|
|
58524b25ee | ||
|
|
34805df73f | ||
|
|
7cb867782d | ||
|
|
63deb3e4f9 | ||
|
|
4dcc340301 | ||
|
|
8bd401fa8c | ||
|
|
338fc70f6d | ||
|
|
7ca1fabc12 | ||
|
|
0d2c6c457e | ||
|
|
2539470978 | ||
|
|
12b412aa87 | ||
|
|
c8b00be37e | ||
|
|
291b11fbd1 | ||
|
|
4635141dfa | ||
|
|
c761ec7b5e | ||
|
|
bbd877a3ba | ||
|
|
e830fb16e0 | ||
|
|
7625cab264 | ||
|
|
7726b7e7ff | ||
|
|
bca0eeaf09 | ||
|
|
8125a21a7e | ||
|
|
077242cfa0 | ||
|
|
ce79418c66 | ||
|
|
80350b2cb1 | ||
|
|
172f397019 | ||
|
|
a463d8a5c7 | ||
|
|
fbd5225aad | ||
|
|
acd4a879f2 | ||
|
|
e11fa135a0 | ||
|
|
f980863f6c | ||
|
|
07230a442f | ||
|
|
a34919f0af | ||
|
|
f4d451de80 | ||
|
|
1e887bc30f | ||
|
|
1442b9a35b | ||
|
|
41fd856578 | ||
|
|
621b60b19d | ||
|
|
b77e372f3e | ||
|
|
d4891a7307 | ||
|
|
199987276b | ||
|
|
5647b34594 | ||
|
|
439e463430 | ||
|
|
22921304a7 | ||
|
|
220abb1510 | ||
|
|
91ce9221e8 | ||
|
|
904d74fe4a | ||
|
|
f507644488 | ||
|
|
501b65a7a1 | ||
|
|
14862fb0dc | ||
|
|
2963369c8d | ||
|
|
1e20d5087a | ||
|
|
4b312b369f | ||
|
|
afbef743de | ||
|
|
864fdeca84 | ||
|
|
541add925c | ||
|
|
2e7df30267 | ||
|
|
0a578c8803 | ||
|
|
b227caee98 | ||
|
|
72b74fbdb4 | ||
|
|
01d36ad363 | ||
|
|
548cb9cdf5 | ||
|
|
79430da42e | ||
|
|
0620843f4c | ||
|
|
34d063302a | ||
|
|
0abc3389db | ||
|
|
ebb8ec66af | ||
|
|
f55ced97a5 | ||
|
|
8458345535 | ||
|
|
66d6c2fe4b | ||
|
|
053808685c | ||
|
|
4f2a6b70d8 | ||
|
|
d8004e471a | ||
|
|
e2b46eac8e | ||
|
|
1b3173b17b | ||
|
|
d5f4275055 | ||
|
|
6abae7cc14 | ||
|
|
f32ffcd2a2 | ||
|
|
824bb897cf | ||
|
|
2843a76e28 | ||
|
|
155ff3319a | ||
|
|
34dddb811b | ||
|
|
5fead67bf3 | ||
|
|
48dc9372db | ||
|
|
747446fc76 | ||
|
|
5862ea735e | ||
|
|
3a8a349771 | ||
|
|
70bc2245c7 | ||
|
|
89f6b6357d | ||
|
|
354af456d3 | ||
|
|
e50582e93e | ||
|
|
65deefa53c | ||
|
|
54ef137b49 | ||
|
|
d4df542117 | ||
|
|
8c1e56a7bf | ||
|
|
dff2172173 | ||
|
|
e8ccd3df7e | ||
|
|
b593355537 | ||
|
|
09420cbca5 | ||
|
|
45e82a51b8 | ||
|
|
305e282e19 | ||
|
|
ad7ae84987 | ||
|
|
df100bde73 | ||
|
|
0724851934 | ||
|
|
34cf88d209 | ||
|
|
6322d1df66 | ||
|
|
8a414b3249 | ||
|
|
58f614acca | ||
|
|
d598ad7190 | ||
|
|
439ee3f707 | ||
|
|
c2c85fbd5c | ||
|
|
59aa7bc824 | ||
|
|
0beb50ebca | ||
|
|
649b440d9d | ||
|
|
a74e8f3863 | ||
|
|
46318b1605 | ||
|
|
4bf91a3c51 | ||
|
|
3cde4f2a41 | ||
|
|
d75c7613b2 | ||
|
|
d17e81d712 | ||
|
|
3b4a19efcf | ||
|
|
94bbdb4e06 | ||
|
|
4b87cdb55f | ||
|
|
52de557ec1 | ||
|
|
642fa718f6 | ||
|
|
215f0767d7 | ||
|
|
a0befaf186 | ||
|
|
167f563f6d | ||
|
|
0ee6b84a06 | ||
|
|
9a65837e45 | ||
|
|
4c6587612a | ||
|
|
4aa36db1cb | ||
|
|
01401a3c97 | ||
|
|
d1e528fd95 | ||
|
|
5f5be9ec1e | ||
|
|
c66cda28da | ||
|
|
e565116a4a | ||
|
|
cf50c9f849 | ||
|
|
9fa47227a7 | ||
|
|
547111ed5b | ||
|
|
0d6aa9feaa | ||
|
|
3a0f2b3fa8 | ||
|
|
712e6bf6e4 | ||
|
|
58319dd447 | ||
|
|
cf89b8eeac | ||
|
|
a8c6add82b | ||
|
|
d000e4904d | ||
|
|
c99d6cbf4a | ||
|
|
0b1fb8ff1f | ||
|
|
dcde43e97e | ||
|
|
96da23cc88 | ||
|
|
78182c3573 | ||
|
|
02f8f5a1c1 | ||
|
|
16ee591f49 | ||
|
|
5378156833 | ||
|
|
7b76078792 | ||
|
|
e2af1af4f9 | ||
|
|
c9513d0bf4 | ||
|
|
6fbd5ee06a | ||
|
|
d8773827fb | ||
|
|
bc1843f767 | ||
|
|
07aefe3b88 | ||
|
|
76d449a974 | ||
|
|
dd39fa328c | ||
|
|
0cf568c38b | ||
|
|
a8b8dfc58e | ||
|
|
41dde6b574 | ||
|
|
ae35ca256c | ||
|
|
38142f24a5 | ||
|
|
b16f70993a | ||
|
|
ad1accb2e3 | ||
|
|
d255c6ac4e | ||
|
|
d67ef7b0ca | ||
|
|
198ccb8430 | ||
|
|
ce1b5bdefa | ||
|
|
45aa928369 | ||
|
|
93dc356fa1 | ||
|
|
a0aa132682 | ||
|
|
1a4dd64862 | ||
|
|
3481f70ad7 | ||
|
|
024f21e896 | ||
|
|
c30ccd472e | ||
|
|
28ec03ebc8 | ||
|
|
ab3a31367a | ||
|
|
148bae88d8 | ||
|
|
ca4a38ba85 | ||
|
|
f297765a13 | ||
|
|
4657ccbfff | ||
|
|
db222d4591 | ||
|
|
bafad1c625 | ||
|
|
7f1e95c6e7 | ||
|
|
ca7a87112c | ||
|
|
d542da0a1c | ||
|
|
6fa51d2a22 | ||
|
|
ca53b06af2 | ||
|
|
b5dc96d2c2 | ||
|
|
5e5fe0085f | ||
|
|
0c2a8d774f | ||
|
|
804906dcd8 | ||
|
|
d575743d3a |
17
.cspell/custom-words.txt
Normal file
17
.cspell/custom-words.txt
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
# Custom words
|
||||||
|
fullscreen
|
||||||
|
gamepad
|
||||||
|
gantt
|
||||||
|
kanban
|
||||||
|
pilcrow
|
||||||
|
squircle
|
||||||
|
strikethrough
|
||||||
|
touchpad
|
||||||
|
ungroup
|
||||||
|
toc
|
||||||
|
|
||||||
|
# Brands
|
||||||
|
codepen
|
||||||
|
codesandbox
|
||||||
|
dribbble
|
||||||
|
x.com
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
const DEFAULT_ATTRS = require('./scripts/render/default-attrs.json');
|
const DEFAULT_ATTRS = require('./tools/build-icons/render/default-attrs.json');
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
root: true,
|
root: true,
|
||||||
@@ -15,7 +15,9 @@ module.exports = {
|
|||||||
'no-use-before-define': 'off',
|
'no-use-before-define': 'off',
|
||||||
'import/no-extraneous-dependencies': [
|
'import/no-extraneous-dependencies': [
|
||||||
'error',
|
'error',
|
||||||
{ devDependencies: ['**/*.test.js', '**/*.spec.js', './scripts/**'] },
|
{
|
||||||
|
devDependencies: ['**/*.test.js', '**/*.spec.js', '**/scripts/**'],
|
||||||
|
},
|
||||||
],
|
],
|
||||||
'import/extensions': [
|
'import/extensions': [
|
||||||
'error',
|
'error',
|
||||||
|
|||||||
14
.github/ISSUE_TEMPLATE/02_bug_report.yml
vendored
14
.github/ISSUE_TEMPLATE/02_bug_report.yml
vendored
@@ -22,6 +22,7 @@ body:
|
|||||||
- label: lucide-svelte
|
- label: lucide-svelte
|
||||||
- label: lucide-vue
|
- label: lucide-vue
|
||||||
- label: lucide-vue-next
|
- label: lucide-vue-next
|
||||||
|
- label: lucide-astro
|
||||||
- label: Figma plugin
|
- label: Figma plugin
|
||||||
- label: source/main
|
- label: source/main
|
||||||
- label: other/not relevant
|
- label: other/not relevant
|
||||||
@@ -35,6 +36,16 @@ body:
|
|||||||
placeholder: e.g. 0.289.1
|
placeholder: e.g. 0.289.1
|
||||||
validations:
|
validations:
|
||||||
required: true
|
required: true
|
||||||
|
- type: checkboxes
|
||||||
|
id: can-reproduce-in-latest-version
|
||||||
|
attributes:
|
||||||
|
label: Can you reproduce this in the latest version?
|
||||||
|
description: i.e. after running `npm install lucide-react@latest`
|
||||||
|
options:
|
||||||
|
- label: 'Yes'
|
||||||
|
- label: 'No'
|
||||||
|
validations:
|
||||||
|
required: false
|
||||||
- type: checkboxes
|
- type: checkboxes
|
||||||
id: browsers
|
id: browsers
|
||||||
attributes:
|
attributes:
|
||||||
@@ -59,6 +70,9 @@ body:
|
|||||||
- label: Windows
|
- label: Windows
|
||||||
- label: Linux
|
- label: Linux
|
||||||
- label: macOS
|
- label: macOS
|
||||||
|
- label: ChromeOS
|
||||||
|
- label: iOS
|
||||||
|
- label: Android
|
||||||
- label: Other/not relevant
|
- label: Other/not relevant
|
||||||
- type: textarea
|
- type: textarea
|
||||||
id: description
|
id: description
|
||||||
|
|||||||
@@ -30,6 +30,9 @@ body:
|
|||||||
- label: Windows
|
- label: Windows
|
||||||
- label: Linux
|
- label: Linux
|
||||||
- label: macOS
|
- label: macOS
|
||||||
|
- label: ChromeOS
|
||||||
|
- label: iOS
|
||||||
|
- label: Android
|
||||||
- label: Other/not relevant
|
- label: Other/not relevant
|
||||||
- type: textarea
|
- type: textarea
|
||||||
id: description
|
id: description
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ body:
|
|||||||
- label: lucide-svelte
|
- label: lucide-svelte
|
||||||
- label: lucide-vue
|
- label: lucide-vue
|
||||||
- label: lucide-vue-next
|
- label: lucide-vue-next
|
||||||
|
- label: lucide-astro
|
||||||
- label: Figma plugin
|
- label: Figma plugin
|
||||||
- label: all JS packages
|
- label: all JS packages
|
||||||
- label: site
|
- label: site
|
||||||
|
|||||||
44
.github/actions/build-and-test.yml
vendored
44
.github/actions/build-and-test.yml
vendored
@@ -1,44 +0,0 @@
|
|||||||
name: 'Build and Test'
|
|
||||||
description: 'Builds and test a package'
|
|
||||||
|
|
||||||
inputs:
|
|
||||||
name:
|
|
||||||
description: “Name of the package”
|
|
||||||
required: true
|
|
||||||
|
|
||||||
runs:
|
|
||||||
using: 'composite'
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- uses: actions/setup-node@v4
|
|
||||||
with:
|
|
||||||
node-version: 16
|
|
||||||
|
|
||||||
- uses: pnpm/action-setup@v2
|
|
||||||
name: Install pnpm
|
|
||||||
id: pnpm-install
|
|
||||||
with:
|
|
||||||
version: 8
|
|
||||||
run_install: false
|
|
||||||
|
|
||||||
- name: Get pnpm store directory
|
|
||||||
id: pnpm-cache
|
|
||||||
run: |
|
|
||||||
echo "STORE_PATH=$(pnpm store path)" >> $GITHUB_OUTPUT
|
|
||||||
|
|
||||||
- uses: actions/cache@v3
|
|
||||||
name: Setup pnpm cache
|
|
||||||
with:
|
|
||||||
path: ${{ steps.pnpm-cache.outputs.STORE_PATH }}
|
|
||||||
key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}
|
|
||||||
restore-keys: |
|
|
||||||
${{ runner.os }}-pnpm-store-
|
|
||||||
|
|
||||||
- name: Install dependencies
|
|
||||||
run: pnpm install --filter lucide-preact
|
|
||||||
|
|
||||||
- name: Build
|
|
||||||
run: pnpm --filter lucide-preact build
|
|
||||||
|
|
||||||
- name: Test
|
|
||||||
run: pnpm --filter lucide-preact test
|
|
||||||
41
.github/actions/check-icons.yml
vendored
41
.github/actions/check-icons.yml
vendored
@@ -1,41 +0,0 @@
|
|||||||
name: 'Check icons'
|
|
||||||
description: 'Cross-checks icon and category references in JSON descriptors'
|
|
||||||
|
|
||||||
inputs:
|
|
||||||
name:
|
|
||||||
description: “Name of the package”
|
|
||||||
required: true
|
|
||||||
|
|
||||||
runs:
|
|
||||||
using: 'composite'
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- uses: actions/setup-node@v4
|
|
||||||
with:
|
|
||||||
node-version: 16
|
|
||||||
|
|
||||||
- uses: pnpm/action-setup@v2
|
|
||||||
name: Install pnpm
|
|
||||||
id: pnpm-install
|
|
||||||
with:
|
|
||||||
version: 8
|
|
||||||
run_install: false
|
|
||||||
|
|
||||||
- name: Get pnpm store directory
|
|
||||||
id: pnpm-cache
|
|
||||||
run: |
|
|
||||||
echo "STORE_PATH=$(pnpm store path)" >> $GITHUB_OUTPUT
|
|
||||||
|
|
||||||
- uses: actions/cache@v3
|
|
||||||
name: Setup pnpm cache
|
|
||||||
with:
|
|
||||||
path: ${{ steps.pnpm-cache.outputs.STORE_PATH }}
|
|
||||||
key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}
|
|
||||||
restore-keys: |
|
|
||||||
${{ runner.os }}-pnpm-store-
|
|
||||||
|
|
||||||
- name: Install dependencies
|
|
||||||
run: pnpm install --filter .
|
|
||||||
|
|
||||||
- name: Check icons and categories
|
|
||||||
run: pnpm checkIcons
|
|
||||||
6
.github/labeler.yml
vendored
6
.github/labeler.yml
vendored
@@ -79,6 +79,12 @@
|
|||||||
- any-glob-to-any-file:
|
- any-glob-to-any-file:
|
||||||
- 'packages/lucide-solid/*'
|
- 'packages/lucide-solid/*'
|
||||||
|
|
||||||
|
# For changes in the lucide astro package
|
||||||
|
🚀 astro package:
|
||||||
|
- changed-files:
|
||||||
|
- any-glob-to-any-file:
|
||||||
|
- 'packages/astro/*'
|
||||||
|
|
||||||
# For changes in the lucide static package
|
# For changes in the lucide static package
|
||||||
🪨 static package:
|
🪨 static package:
|
||||||
- changed-files:
|
- changed-files:
|
||||||
|
|||||||
24
.github/pull_request_template.md
vendored
24
.github/pull_request_template.md
vendored
@@ -1,16 +1,18 @@
|
|||||||
<!-- Thank you for contributing! -->
|
<!-- Thank you for contributing! -->
|
||||||
|
|
||||||
|
<!--
|
||||||
|
PR Title Guidelines:
|
||||||
|
|
||||||
|
Please use the format: <type>(<scope>): <short description>
|
||||||
|
|
||||||
|
Example: feat(icons): added `camera` icon
|
||||||
|
|
||||||
|
Available types: fix, feat, perf, docs, style, refactor, test, chore, ci, build
|
||||||
|
Common scopes: icons, docs, studio, site, dev
|
||||||
|
-->
|
||||||
|
|
||||||
<!-- Insert `closes #issueNumber` here if merging this PR will resolve an existing issue -->
|
<!-- Insert `closes #issueNumber` here if merging this PR will resolve an existing issue -->
|
||||||
|
## Description
|
||||||
## What is the purpose of this pull request?
|
|
||||||
<!-- Please choose one of the following, and put an "x" next to it. -->
|
|
||||||
- [ ] New Icon
|
|
||||||
- [ ] Bug fix
|
|
||||||
- [ ] New Feature
|
|
||||||
- [ ] Documentation update
|
|
||||||
- [ ] Other:
|
|
||||||
|
|
||||||
### Description
|
|
||||||
<!-- Please insert your description here and provide info about the "what" this PR is contribution -->
|
<!-- Please insert your description here and provide info about the "what" this PR is contribution -->
|
||||||
|
|
||||||
### Icon use case <!-- ONLY for new icons, remove this part if not icon PR -->
|
### Icon use case <!-- ONLY for new icons, remove this part if not icon PR -->
|
||||||
@@ -47,7 +49,7 @@
|
|||||||
- [ ] I've made sure that the icons look sharp on low DPI displays.
|
- [ ] I've made sure that the icons look sharp on low DPI displays.
|
||||||
- [ ] I've made sure that the icons look consistent with the icon set in size, optical volume and density.
|
- [ ] I've made sure that the icons look consistent with the icon set in size, optical volume and density.
|
||||||
- [ ] I've made sure that the icons are visually centered.
|
- [ ] I've made sure that the icons are visually centered.
|
||||||
- [ ] I've correctly optimized all icons to two points of precision.
|
- [ ] I've correctly optimized all icons to three points of precision.
|
||||||
|
|
||||||
## Before Submitting <!-- For every PR! -->
|
## Before Submitting <!-- For every PR! -->
|
||||||
<!-- All of these requirements must be fulfilled. -->
|
<!-- All of these requirements must be fulfilled. -->
|
||||||
|
|||||||
44
.github/workflows/ci.yml
vendored
44
.github/workflows/ci.yml
vendored
@@ -9,20 +9,18 @@ on:
|
|||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
create-release:
|
create-release:
|
||||||
if: github.repository == 'lucide-icons/lucide'
|
if: github.repository == 'lucide-icons/lucide' && startsWith(github.event.head_commit.message, 'feat(icons)')
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
outputs:
|
outputs:
|
||||||
VERSION: ${{ steps.new-version.outputs.NEW_VERSION }}
|
VERSION: ${{ steps.new-version.outputs.NEW_VERSION }}
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
- uses: pnpm/action-setup@v2
|
- uses: pnpm/action-setup@v4
|
||||||
with:
|
|
||||||
version: 8
|
|
||||||
- uses: actions/setup-node@v4
|
- uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
node-version: 18
|
|
||||||
cache: 'pnpm'
|
cache: 'pnpm'
|
||||||
|
node-version-file: 'package.json'
|
||||||
|
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: pnpm install --frozen-lockfile
|
run: pnpm install --frozen-lockfile
|
||||||
@@ -63,8 +61,40 @@ jobs:
|
|||||||
uses: softprops/action-gh-release@v1
|
uses: softprops/action-gh-release@v1
|
||||||
with:
|
with:
|
||||||
tag_name: ${{ steps.new-version.outputs.NEW_VERSION }}
|
tag_name: ${{ steps.new-version.outputs.NEW_VERSION }}
|
||||||
name: New icons ${{ steps.new-version.outputs.NEW_VERSION }}
|
name: Version ${{ steps.new-version.outputs.NEW_VERSION }}
|
||||||
body: ${{ steps.change-log.outputs.CHANGE_LOG }}
|
generate_release_notes: true
|
||||||
|
|
||||||
|
test-semantic-release:
|
||||||
|
if: github.repository == 'lucide-icons/lucide'
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Semantic Release
|
||||||
|
id: semantic
|
||||||
|
uses: cycjimmy/semantic-release-action@v4
|
||||||
|
with:
|
||||||
|
tag_format: ${version}
|
||||||
|
branches: |
|
||||||
|
['new-release-workflow']
|
||||||
|
extends: |
|
||||||
|
semantic-release-monorepo
|
||||||
|
extra_plugins: |
|
||||||
|
@semantic-release/github
|
||||||
|
@semantic-release/git
|
||||||
|
@semantic-release/release-notes-generator
|
||||||
|
conventional-changelog-conventionalcommits
|
||||||
|
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
|
- name: Log output
|
||||||
|
if: steps.semantic.outputs.new_release_published == 'true'
|
||||||
|
run: |
|
||||||
|
echo ${{ steps.semantic.outputs.new_release_version }}
|
||||||
|
echo ${{ steps.semantic.outputs.new_release_major_version }}
|
||||||
|
echo ${{ steps.semantic.outputs.new_release_minor_version }}
|
||||||
|
echo ${{ steps.semantic.outputs.new_release_patch_version }}
|
||||||
|
|
||||||
start-release:
|
start-release:
|
||||||
if: github.repository == 'lucide-icons/lucide'
|
if: github.repository == 'lucide-icons/lucide'
|
||||||
|
|||||||
35
.github/workflows/close-issue-with-banned-phrases.yml
vendored
Normal file
35
.github/workflows/close-issue-with-banned-phrases.yml
vendored
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
name: Close Issue with Banned Phrases
|
||||||
|
|
||||||
|
on:
|
||||||
|
issues:
|
||||||
|
types: [opened]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
block_phrases:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
permissions:
|
||||||
|
issues: write
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Check for blocked phrases in issue title
|
||||||
|
run: |
|
||||||
|
ISSUE_TITLE=$(jq -r '.issue.title' "$GITHUB_EVENT_PATH")
|
||||||
|
BLOCKED_PHRASES=("twitter" "whatsapp" "logo" "google" "tiktok" "facebook" "slack" "discord" "bluesky" "spotify" "behance" "pix" "x.com")
|
||||||
|
|
||||||
|
# Check title and body for blocked phrases
|
||||||
|
for PHRASE in "${BLOCKED_PHRASES[@]}"
|
||||||
|
do
|
||||||
|
if echo "$ISSUE_TITLE" | grep -i "$PHRASE"; then
|
||||||
|
gh issue close ${{ github.event.issue.number }} --reason "not planned" --comment "This looks like a duplicate, use the [search](https://github.com/lucide-icons/lucide/issues?q=is%3Aissue+$PHRASE) to find similar issues.
|
||||||
|
|
||||||
|
Read more about brand guideline rules at [We're not accepting new Brand icons #670](https://github.com/lucide-icons/lucide/issues/670).
|
||||||
|
|
||||||
|
Always happy to help on [Discord](https://discord.gg/EH6nSts)."
|
||||||
|
gh issue lock ${{ github.event.issue.number }} --reason spam
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
env:
|
||||||
|
GH_TOKEN: ${{ github.token }}
|
||||||
3
.github/workflows/close-stale-prs.yml
vendored
3
.github/workflows/close-stale-prs.yml
vendored
@@ -6,6 +6,8 @@ on:
|
|||||||
jobs:
|
jobs:
|
||||||
stale:
|
stale:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
permissions:
|
||||||
|
pull-requests: write
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/stale@v9
|
- uses: actions/stale@v9
|
||||||
with:
|
with:
|
||||||
@@ -14,4 +16,5 @@ jobs:
|
|||||||
close-pr-message: This PR was closed because it has been stalled for 5 days with no activity.
|
close-pr-message: This PR was closed because it has been stalled for 5 days with no activity.
|
||||||
close-pr-label: 🧶 stale
|
close-pr-label: 🧶 stale
|
||||||
days-before-stale: 30
|
days-before-stale: 30
|
||||||
|
days-before-issue-stale: -1
|
||||||
days-before-close: -1
|
days-before-close: -1
|
||||||
|
|||||||
58
.github/workflows/comment-icon-preview.yml
vendored
Normal file
58
.github/workflows/comment-icon-preview.yml
vendored
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
name: Icon preview comment
|
||||||
|
|
||||||
|
on:
|
||||||
|
workflow_run:
|
||||||
|
workflows: ['Pull request icon preview']
|
||||||
|
types:
|
||||||
|
- completed
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
upload:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
if: >
|
||||||
|
github.event.workflow_run.event == 'pull_request' &&
|
||||||
|
github.event.workflow_run.conclusion == 'success'
|
||||||
|
steps:
|
||||||
|
- name: 'Download artifact'
|
||||||
|
uses: actions/github-script@v7
|
||||||
|
with:
|
||||||
|
script: |
|
||||||
|
let allArtifacts = await github.rest.actions.listWorkflowRunArtifacts({
|
||||||
|
owner: context.repo.owner,
|
||||||
|
repo: context.repo.repo,
|
||||||
|
run_id: context.payload.workflow_run.id,
|
||||||
|
});
|
||||||
|
let matchArtifact = allArtifacts.data.artifacts.filter((artifact) => {
|
||||||
|
return artifact.name == "pr_number"
|
||||||
|
})[0];
|
||||||
|
let download = await github.rest.actions.downloadArtifact({
|
||||||
|
owner: context.repo.owner,
|
||||||
|
repo: context.repo.repo,
|
||||||
|
artifact_id: matchArtifact.id,
|
||||||
|
archive_format: 'zip',
|
||||||
|
});
|
||||||
|
const fs = require('fs');
|
||||||
|
fs.writeFileSync('${{github.workspace}}/pr_number.zip', Buffer.from(download.data));
|
||||||
|
|
||||||
|
- name: 'Unzip artifact'
|
||||||
|
run: unzip pr_number.zip
|
||||||
|
|
||||||
|
- name: 'Get PR number'
|
||||||
|
run: echo "number=$(cat NR)" >> $GITHUB_OUTPUT
|
||||||
|
id: pr-number
|
||||||
|
|
||||||
|
- name: Find Comment
|
||||||
|
uses: peter-evans/find-comment@v2
|
||||||
|
id: pr-comment
|
||||||
|
with:
|
||||||
|
issue-number: ${{ steps.pr-number.outputs.number }}
|
||||||
|
comment-author: 'github-actions[bot]'
|
||||||
|
body-includes: Added or changed icons
|
||||||
|
|
||||||
|
- name: Create or update comment
|
||||||
|
uses: peter-evans/create-or-update-comment@v3
|
||||||
|
with:
|
||||||
|
comment-id: ${{ steps.pr-comment.outputs.comment-id }}
|
||||||
|
issue-number: ${{ steps.pr-number.outputs.number }}
|
||||||
|
body-path: comment-markup.md
|
||||||
|
edit-mode: replace
|
||||||
@@ -1,22 +1,20 @@
|
|||||||
name: Linting
|
name: Linting PR
|
||||||
|
|
||||||
on:
|
on:
|
||||||
pull_request:
|
pull_request:
|
||||||
branches:
|
paths-ignore:
|
||||||
- '**'
|
- icons/*.svg
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
linting:
|
lint-code:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
- uses: pnpm/action-setup@v2
|
- uses: pnpm/action-setup@v4
|
||||||
with:
|
|
||||||
version: 8
|
|
||||||
- uses: actions/setup-node@v4
|
- uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
node-version: 18
|
|
||||||
cache: 'pnpm'
|
cache: 'pnpm'
|
||||||
|
node-version-file: 'package.json'
|
||||||
|
|
||||||
- name: Install Dependencies
|
- name: Install Dependencies
|
||||||
run: pnpm install --frozen-lockfile
|
run: pnpm install --frozen-lockfile
|
||||||
32
.github/workflows/lint-pr-title.yml
vendored
Normal file
32
.github/workflows/lint-pr-title.yml
vendored
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
name: Linting PR
|
||||||
|
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
types:
|
||||||
|
- opened
|
||||||
|
- edited
|
||||||
|
- reopened
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
lint-pr-title:
|
||||||
|
name: PR Title Lint
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: amannn/action-semantic-pull-request@v5
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
with:
|
||||||
|
types: |
|
||||||
|
fix
|
||||||
|
feat
|
||||||
|
perf
|
||||||
|
refactor
|
||||||
|
test
|
||||||
|
style
|
||||||
|
docs
|
||||||
|
ci
|
||||||
|
build
|
||||||
|
chore
|
||||||
|
requireScope: true
|
||||||
|
ignoreLabels: |
|
||||||
|
bot
|
||||||
36
.github/workflows/linting-icons.yml
vendored
Normal file
36
.github/workflows/linting-icons.yml
vendored
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
name: Linting Icons
|
||||||
|
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
paths:
|
||||||
|
- 'icons/*'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
lint-filenames:
|
||||||
|
name: Lint Filenames
|
||||||
|
if: github.repository == 'lucide-icons/lucide'
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- name: Get changed files
|
||||||
|
id: changed-files
|
||||||
|
uses: tj-actions/changed-files@v46
|
||||||
|
with:
|
||||||
|
files: icons/*
|
||||||
|
|
||||||
|
- name: Generate annotations
|
||||||
|
run: node ./scripts/lintFilenames.mjs
|
||||||
|
env:
|
||||||
|
CHANGED_FILES: ${{ steps.changed-files.outputs.all_changed_files }}
|
||||||
|
|
||||||
|
lint-aliases:
|
||||||
|
name: Check Uniqueness of Aliases
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- name: Check Uniqueness of Aliases
|
||||||
|
run: "! cat <(printf \"%s\\n\" icons/*.json | while read -r name; do basename \"$name\" .json; done) <(jq -cr 'select(.aliases) | .aliases[] | if type==\"string\" then . else .name end' icons/*.json) | sort | uniq -c | grep -ve '^\\s*1 '"
|
||||||
21
.github/workflows/lucide-angular.yml
vendored
21
.github/workflows/lucide-angular.yml
vendored
@@ -8,17 +8,15 @@ on:
|
|||||||
- pnpm-lock.yaml
|
- pnpm-lock.yaml
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
lucide-angular:
|
build:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
- uses: pnpm/action-setup@v2
|
- uses: pnpm/action-setup@v4
|
||||||
with:
|
|
||||||
version: 8
|
|
||||||
- uses: actions/setup-node@v4
|
- uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
node-version: 18
|
|
||||||
cache: 'pnpm'
|
cache: 'pnpm'
|
||||||
|
node-version-file: 'package.json'
|
||||||
|
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: pnpm install --frozen-lockfile
|
run: pnpm install --frozen-lockfile
|
||||||
@@ -26,5 +24,18 @@ jobs:
|
|||||||
- name: Build
|
- name: Build
|
||||||
run: pnpm --filter lucide-angular build
|
run: pnpm --filter lucide-angular build
|
||||||
|
|
||||||
|
test:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- uses: pnpm/action-setup@v4
|
||||||
|
- uses: actions/setup-node@v4
|
||||||
|
with:
|
||||||
|
cache: 'pnpm'
|
||||||
|
node-version-file: 'package.json'
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
run: pnpm install --frozen-lockfile
|
||||||
|
|
||||||
- name: Test
|
- name: Test
|
||||||
run: pnpm --filter lucide-angular test
|
run: pnpm --filter lucide-angular test
|
||||||
|
|||||||
42
.github/workflows/lucide-astro.yml
vendored
Normal file
42
.github/workflows/lucide-astro.yml
vendored
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
name: Lucide Astro Checks
|
||||||
|
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
paths:
|
||||||
|
- packages/astro/**
|
||||||
|
- packages/shared/**
|
||||||
|
- tools/build-icons/**
|
||||||
|
- pnpm-lock.yaml
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- uses: pnpm/action-setup@v2
|
||||||
|
- uses: actions/setup-node@v4
|
||||||
|
with:
|
||||||
|
node-version: 18
|
||||||
|
cache: 'pnpm'
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
run: pnpm install --frozen-lockfile
|
||||||
|
|
||||||
|
- name: Build
|
||||||
|
run: pnpm --filter @lucide/astro build
|
||||||
|
|
||||||
|
test:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
- uses: pnpm/action-setup@v2
|
||||||
|
- uses: actions/setup-node@v3.8.1
|
||||||
|
with:
|
||||||
|
node-version: 18
|
||||||
|
cache: 'pnpm'
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
run: pnpm install --frozen-lockfile
|
||||||
|
|
||||||
|
- name: Test
|
||||||
|
run: pnpm --filter @lucide/astro test
|
||||||
9
.github/workflows/lucide-font.yml
vendored
9
.github/workflows/lucide-font.yml
vendored
@@ -3,7 +3,6 @@ name: Lucide font checks
|
|||||||
on:
|
on:
|
||||||
pull_request:
|
pull_request:
|
||||||
paths:
|
paths:
|
||||||
- icons/**
|
|
||||||
- tools/build-font/**
|
- tools/build-font/**
|
||||||
- pnpm-lock.yaml
|
- pnpm-lock.yaml
|
||||||
|
|
||||||
@@ -12,13 +11,11 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
- uses: pnpm/action-setup@v2
|
- uses: pnpm/action-setup@v4
|
||||||
with:
|
|
||||||
version: 8
|
|
||||||
- uses: actions/setup-node@v4
|
- uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
node-version: 18
|
|
||||||
cache: 'pnpm'
|
cache: 'pnpm'
|
||||||
|
node-version-file: 'package.json'
|
||||||
|
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: pnpm install --frozen-lockfile
|
run: pnpm install --frozen-lockfile
|
||||||
@@ -30,7 +27,7 @@ jobs:
|
|||||||
run: pnpm build:font
|
run: pnpm build:font
|
||||||
|
|
||||||
- name: 'Upload to Artifacts'
|
- name: 'Upload to Artifacts'
|
||||||
uses: actions/upload-artifact@v3
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: lucide-font
|
name: lucide-font
|
||||||
path: lucide-font
|
path: lucide-font
|
||||||
|
|||||||
10
.github/workflows/lucide-preact.yml
vendored
10
.github/workflows/lucide-preact.yml
vendored
@@ -4,6 +4,7 @@ on:
|
|||||||
pull_request:
|
pull_request:
|
||||||
paths:
|
paths:
|
||||||
- packages/lucide-preact/**
|
- packages/lucide-preact/**
|
||||||
|
- packages/shared/**
|
||||||
- tools/build-icons/**
|
- tools/build-icons/**
|
||||||
- tools/rollup-plugins/**
|
- tools/rollup-plugins/**
|
||||||
- pnpm-lock.yaml
|
- pnpm-lock.yaml
|
||||||
@@ -13,19 +14,14 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
- uses: pnpm/action-setup@v2
|
- uses: pnpm/action-setup@v4
|
||||||
with:
|
|
||||||
version: 8
|
|
||||||
- uses: actions/setup-node@v4
|
- uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
node-version: 18
|
|
||||||
cache: 'pnpm'
|
cache: 'pnpm'
|
||||||
|
node-version-file: 'package.json'
|
||||||
|
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: pnpm install --frozen-lockfile
|
run: pnpm install --frozen-lockfile
|
||||||
|
|
||||||
- name: Build
|
|
||||||
run: pnpm --filter lucide-preact build
|
|
||||||
|
|
||||||
- name: Test
|
- name: Test
|
||||||
run: pnpm --filter lucide-preact test
|
run: pnpm --filter lucide-preact test
|
||||||
|
|||||||
22
.github/workflows/lucide-react-native.yml
vendored
22
.github/workflows/lucide-react-native.yml
vendored
@@ -4,22 +4,21 @@ on:
|
|||||||
pull_request:
|
pull_request:
|
||||||
paths:
|
paths:
|
||||||
- packages/lucide-react-native/**
|
- packages/lucide-react-native/**
|
||||||
|
- packages/shared/**
|
||||||
- tools/build-icons/**
|
- tools/build-icons/**
|
||||||
- tools/rollup-plugins/**
|
- tools/rollup-plugins/**
|
||||||
- pnpm-lock.yaml
|
- pnpm-lock.yaml
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
lucide-react-native:
|
build:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
- uses: pnpm/action-setup@v2
|
- uses: pnpm/action-setup@v4
|
||||||
with:
|
|
||||||
version: 8
|
|
||||||
- uses: actions/setup-node@v4
|
- uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
node-version: 18
|
|
||||||
cache: 'pnpm'
|
cache: 'pnpm'
|
||||||
|
node-version-file: 'package.json'
|
||||||
|
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: pnpm install --frozen-lockfile
|
run: pnpm install --frozen-lockfile
|
||||||
@@ -27,5 +26,18 @@ jobs:
|
|||||||
- name: Build
|
- name: Build
|
||||||
run: pnpm --filter lucide-react-native build
|
run: pnpm --filter lucide-react-native build
|
||||||
|
|
||||||
|
test:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- uses: pnpm/action-setup@v4
|
||||||
|
- uses: actions/setup-node@v4
|
||||||
|
with:
|
||||||
|
cache: 'pnpm'
|
||||||
|
node-version-file: 'package.json'
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
run: pnpm install --frozen-lockfile
|
||||||
|
|
||||||
- name: Test
|
- name: Test
|
||||||
run: pnpm --filter lucide-react-native test
|
run: pnpm --filter lucide-react-native test
|
||||||
|
|||||||
22
.github/workflows/lucide-react.yml
vendored
22
.github/workflows/lucide-react.yml
vendored
@@ -4,23 +4,22 @@ on:
|
|||||||
pull_request:
|
pull_request:
|
||||||
paths:
|
paths:
|
||||||
- packages/lucide-react/**
|
- packages/lucide-react/**
|
||||||
|
- packages/shared/**
|
||||||
- tools/build-icons/**
|
- tools/build-icons/**
|
||||||
- tools/rollup-plugins/**
|
- tools/rollup-plugins/**
|
||||||
- scripts/generateNextJSAliases.mjs
|
- scripts/generateNextJSAliases.mjs
|
||||||
- pnpm-lock.yaml
|
- pnpm-lock.yaml
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
lucide-react:
|
build:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
- uses: pnpm/action-setup@v2
|
- uses: pnpm/action-setup@v4
|
||||||
with:
|
|
||||||
version: 8
|
|
||||||
- uses: actions/setup-node@v4
|
- uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
node-version: 18
|
|
||||||
cache: 'pnpm'
|
cache: 'pnpm'
|
||||||
|
node-version-file: 'package.json'
|
||||||
|
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: pnpm install --frozen-lockfile
|
run: pnpm install --frozen-lockfile
|
||||||
@@ -28,5 +27,18 @@ jobs:
|
|||||||
- name: Build
|
- name: Build
|
||||||
run: pnpm --filter lucide-react build
|
run: pnpm --filter lucide-react build
|
||||||
|
|
||||||
|
test:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- uses: pnpm/action-setup@v4
|
||||||
|
- uses: actions/setup-node@v4
|
||||||
|
with:
|
||||||
|
cache: 'pnpm'
|
||||||
|
node-version-file: 'package.json'
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
run: pnpm install --frozen-lockfile
|
||||||
|
|
||||||
- name: Test
|
- name: Test
|
||||||
run: pnpm --filter lucide-react test
|
run: pnpm --filter lucide-react test
|
||||||
|
|||||||
24
.github/workflows/lucide-shared.yml
vendored
Normal file
24
.github/workflows/lucide-shared.yml
vendored
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
name: Lucide Shared Checks
|
||||||
|
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
paths:
|
||||||
|
- packages/shared/**
|
||||||
|
- pnpm-lock.yaml
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
test:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- uses: pnpm/action-setup@v4
|
||||||
|
- uses: actions/setup-node@v4
|
||||||
|
with:
|
||||||
|
cache: 'pnpm'
|
||||||
|
node-version-file: 'package.json'
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
run: pnpm install --frozen-lockfile
|
||||||
|
|
||||||
|
- name: Test
|
||||||
|
run: pnpm --filter lucide-react test
|
||||||
22
.github/workflows/lucide-solid.yml
vendored
22
.github/workflows/lucide-solid.yml
vendored
@@ -4,22 +4,21 @@ on:
|
|||||||
pull_request:
|
pull_request:
|
||||||
paths:
|
paths:
|
||||||
- packages/lucide-solid/**
|
- packages/lucide-solid/**
|
||||||
|
- packages/shared/**
|
||||||
- tools/build-icons/**
|
- tools/build-icons/**
|
||||||
- tools/rollup-plugins/**
|
- tools/rollup-plugins/**
|
||||||
- pnpm-lock.yaml
|
- pnpm-lock.yaml
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
lucide-solid:
|
build:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
- uses: pnpm/action-setup@v2
|
- uses: pnpm/action-setup@v4
|
||||||
with:
|
|
||||||
version: 8
|
|
||||||
- uses: actions/setup-node@v4
|
- uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
node-version: 18
|
|
||||||
cache: 'pnpm'
|
cache: 'pnpm'
|
||||||
|
node-version-file: 'package.json'
|
||||||
|
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: pnpm install --frozen-lockfile
|
run: pnpm install --frozen-lockfile
|
||||||
@@ -27,5 +26,18 @@ jobs:
|
|||||||
- name: Build
|
- name: Build
|
||||||
run: pnpm --filter lucide-solid build
|
run: pnpm --filter lucide-solid build
|
||||||
|
|
||||||
|
test:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- uses: pnpm/action-setup@v4
|
||||||
|
- uses: actions/setup-node@v4
|
||||||
|
with:
|
||||||
|
cache: 'pnpm'
|
||||||
|
node-version-file: 'package.json'
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
run: pnpm install --frozen-lockfile
|
||||||
|
|
||||||
- name: Test
|
- name: Test
|
||||||
run: pnpm --filter lucide-solid test
|
run: pnpm --filter lucide-solid test
|
||||||
|
|||||||
6
.github/workflows/lucide-static.yml
vendored
6
.github/workflows/lucide-static.yml
vendored
@@ -12,13 +12,11 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
- uses: pnpm/action-setup@v2
|
- uses: pnpm/action-setup@v4
|
||||||
with:
|
|
||||||
version: 8
|
|
||||||
- uses: actions/setup-node@v4
|
- uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
node-version: 18
|
|
||||||
cache: 'pnpm'
|
cache: 'pnpm'
|
||||||
|
node-version-file: 'package.json'
|
||||||
|
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: pnpm install --frozen-lockfile
|
run: pnpm install --frozen-lockfile
|
||||||
|
|||||||
43
.github/workflows/lucide-svelte-5.yml
vendored
Normal file
43
.github/workflows/lucide-svelte-5.yml
vendored
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
name: Lucide Svelte 5 checks
|
||||||
|
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
paths:
|
||||||
|
- packages/svelte/**
|
||||||
|
- packages/shared/**
|
||||||
|
- tools/build-icons/**
|
||||||
|
- tools/rollup-plugins/**
|
||||||
|
- pnpm-lock.yaml
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- uses: pnpm/action-setup@v4
|
||||||
|
- uses: actions/setup-node@v4
|
||||||
|
with:
|
||||||
|
cache: 'pnpm'
|
||||||
|
node-version-file: 'package.json'
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
run: pnpm install --frozen-lockfile
|
||||||
|
|
||||||
|
- name: Build
|
||||||
|
run: pnpm --filter @lucide/svelte build
|
||||||
|
|
||||||
|
test:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- uses: pnpm/action-setup@v4
|
||||||
|
- uses: actions/setup-node@v4
|
||||||
|
with:
|
||||||
|
cache: 'pnpm'
|
||||||
|
node-version-file: 'package.json'
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
run: pnpm install --frozen-lockfile
|
||||||
|
|
||||||
|
- name: Test
|
||||||
|
run: pnpm --filter @lucide/svelte test
|
||||||
22
.github/workflows/lucide-svelte.yml
vendored
22
.github/workflows/lucide-svelte.yml
vendored
@@ -4,22 +4,21 @@ on:
|
|||||||
pull_request:
|
pull_request:
|
||||||
paths:
|
paths:
|
||||||
- packages/lucide-svelte/**
|
- packages/lucide-svelte/**
|
||||||
|
- packages/shared/**
|
||||||
- tools/build-icons/**
|
- tools/build-icons/**
|
||||||
- tools/rollup-plugins/**
|
- tools/rollup-plugins/**
|
||||||
- pnpm-lock.yaml
|
- pnpm-lock.yaml
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
lucide-svelte:
|
build:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
- uses: pnpm/action-setup@v2
|
- uses: pnpm/action-setup@v4
|
||||||
with:
|
|
||||||
version: 8
|
|
||||||
- uses: actions/setup-node@v4
|
- uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
node-version: 18
|
|
||||||
cache: 'pnpm'
|
cache: 'pnpm'
|
||||||
|
node-version-file: 'package.json'
|
||||||
|
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: pnpm install --frozen-lockfile
|
run: pnpm install --frozen-lockfile
|
||||||
@@ -27,5 +26,18 @@ jobs:
|
|||||||
- name: Build
|
- name: Build
|
||||||
run: pnpm --filter lucide-svelte build
|
run: pnpm --filter lucide-svelte build
|
||||||
|
|
||||||
|
test:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- uses: pnpm/action-setup@v4
|
||||||
|
- uses: actions/setup-node@v4
|
||||||
|
with:
|
||||||
|
cache: 'pnpm'
|
||||||
|
node-version-file: 'package.json'
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
run: pnpm install --frozen-lockfile
|
||||||
|
|
||||||
- name: Test
|
- name: Test
|
||||||
run: pnpm --filter lucide-svelte test
|
run: pnpm --filter lucide-svelte test
|
||||||
|
|||||||
22
.github/workflows/lucide-vue-next.yml
vendored
22
.github/workflows/lucide-vue-next.yml
vendored
@@ -4,22 +4,21 @@ on:
|
|||||||
pull_request:
|
pull_request:
|
||||||
paths:
|
paths:
|
||||||
- packages/lucide-vue-next/**
|
- packages/lucide-vue-next/**
|
||||||
|
- packages/shared/**
|
||||||
- tools/build-icons/**
|
- tools/build-icons/**
|
||||||
- tools/rollup-plugins/**
|
- tools/rollup-plugins/**
|
||||||
- pnpm-lock.yaml
|
- pnpm-lock.yaml
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
lucide-vue-next:
|
build:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
- uses: pnpm/action-setup@v2
|
- uses: pnpm/action-setup@v4
|
||||||
with:
|
|
||||||
version: 8
|
|
||||||
- uses: actions/setup-node@v4
|
- uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
node-version: 18
|
|
||||||
cache: 'pnpm'
|
cache: 'pnpm'
|
||||||
|
node-version-file: 'package.json'
|
||||||
|
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: pnpm install --frozen-lockfile
|
run: pnpm install --frozen-lockfile
|
||||||
@@ -27,5 +26,18 @@ jobs:
|
|||||||
- name: Build
|
- name: Build
|
||||||
run: pnpm --filter lucide-vue-next build
|
run: pnpm --filter lucide-vue-next build
|
||||||
|
|
||||||
|
test:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- uses: pnpm/action-setup@v4
|
||||||
|
- uses: actions/setup-node@v4
|
||||||
|
with:
|
||||||
|
cache: 'pnpm'
|
||||||
|
node-version-file: 'package.json'
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
run: pnpm install --frozen-lockfile
|
||||||
|
|
||||||
- name: Test
|
- name: Test
|
||||||
run: pnpm --filter lucide-vue-next test
|
run: pnpm --filter lucide-vue-next test
|
||||||
|
|||||||
31
.github/workflows/lucide-vue.yml
vendored
31
.github/workflows/lucide-vue.yml
vendored
@@ -1,31 +0,0 @@
|
|||||||
name: Lucide Vue checks
|
|
||||||
|
|
||||||
on:
|
|
||||||
pull_request:
|
|
||||||
paths:
|
|
||||||
- packages/lucide-vue/**
|
|
||||||
- tools/build-icons/**
|
|
||||||
- tools/rollup-plugins/**
|
|
||||||
- pnpm-lock.yaml
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
lucide-vue:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- uses: pnpm/action-setup@v2
|
|
||||||
with:
|
|
||||||
version: 8
|
|
||||||
- uses: actions/setup-node@v4
|
|
||||||
with:
|
|
||||||
node-version: 18
|
|
||||||
cache: 'pnpm'
|
|
||||||
|
|
||||||
- name: Install dependencies
|
|
||||||
run: pnpm install --frozen-lockfile
|
|
||||||
|
|
||||||
- name: Build
|
|
||||||
run: pnpm --filter lucide-vue build
|
|
||||||
|
|
||||||
- name: Test
|
|
||||||
run: pnpm --filter lucide-vue test
|
|
||||||
21
.github/workflows/lucide.yml
vendored
21
.github/workflows/lucide.yml
vendored
@@ -9,17 +9,15 @@ on:
|
|||||||
- pnpm-lock.yaml
|
- pnpm-lock.yaml
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
lucide:
|
build:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
- uses: pnpm/action-setup@v2
|
- uses: pnpm/action-setup@v4
|
||||||
with:
|
|
||||||
version: 8
|
|
||||||
- uses: actions/setup-node@v4
|
- uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
node-version: 18
|
|
||||||
cache: 'pnpm'
|
cache: 'pnpm'
|
||||||
|
node-version-file: 'package.json'
|
||||||
|
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: pnpm install --frozen-lockfile
|
run: pnpm install --frozen-lockfile
|
||||||
@@ -27,5 +25,18 @@ jobs:
|
|||||||
- name: Build
|
- name: Build
|
||||||
run: pnpm --filter lucide build
|
run: pnpm --filter lucide build
|
||||||
|
|
||||||
|
test:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- uses: pnpm/action-setup@v4
|
||||||
|
- uses: actions/setup-node@v4
|
||||||
|
with:
|
||||||
|
cache: 'pnpm'
|
||||||
|
node-version-file: 'package.json'
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
run: pnpm install --frozen-lockfile
|
||||||
|
|
||||||
- name: Test
|
- name: Test
|
||||||
run: pnpm --filter lucide test
|
run: pnpm --filter lucide test
|
||||||
|
|||||||
43
.github/workflows/pull-request-icon-preview.yml
vendored
Normal file
43
.github/workflows/pull-request-icon-preview.yml
vendored
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
name: Pull request icon preview
|
||||||
|
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
paths:
|
||||||
|
- 'icons/*.svg'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
generate-changed-icons-comment:
|
||||||
|
name: Generate Changed Icons Comment
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
pull-requests: write
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Get changed files
|
||||||
|
id: changed-files
|
||||||
|
uses: tj-actions/changed-files@v46
|
||||||
|
with:
|
||||||
|
files: icons/*.svg
|
||||||
|
|
||||||
|
- uses: actions/setup-node@v4
|
||||||
|
- name: Install svgson for code preview (safer and faster than installing all deps)
|
||||||
|
run: npm install svgson
|
||||||
|
|
||||||
|
- name: Save PR number
|
||||||
|
run: |
|
||||||
|
mkdir -p ./pr
|
||||||
|
echo ${{ github.event.number }} > ./pr/NR
|
||||||
|
|
||||||
|
- name: Generate comment markup
|
||||||
|
run: node ./scripts/generateChangedIconsCommentMarkup.mjs >> ./pr/comment-markup.md
|
||||||
|
id: comment-markup
|
||||||
|
env:
|
||||||
|
CHANGED_FILES: ${{ steps.changed-files.outputs.all_changed_files }}
|
||||||
|
|
||||||
|
- uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: pr_number
|
||||||
|
path: pr/
|
||||||
109
.github/workflows/pull-request.yml
vendored
109
.github/workflows/pull-request.yml
vendored
@@ -1,109 +0,0 @@
|
|||||||
name: Add Changed Icons comment
|
|
||||||
|
|
||||||
on:
|
|
||||||
pull_request_target:
|
|
||||||
paths:
|
|
||||||
- 'icons/*.svg'
|
|
||||||
branches:
|
|
||||||
- main
|
|
||||||
- fix-icon-preview
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
lint-filenames:
|
|
||||||
if: github.repository == 'lucide-icons/lucide'
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
permissions:
|
|
||||||
contents: read
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
with:
|
|
||||||
fetch-depth: 0
|
|
||||||
ref: refs/pull/${{ github.event.pull_request.number }}/merge
|
|
||||||
- name: Get changed files
|
|
||||||
id: changed-files
|
|
||||||
uses: tj-actions/changed-files@v41
|
|
||||||
with:
|
|
||||||
files: icons/*
|
|
||||||
- name: Generate annotations
|
|
||||||
run: node ./scripts/lintFilenames.mjs
|
|
||||||
env:
|
|
||||||
CHANGED_FILES: ${{ steps.changed-files.outputs.all_changed_files }}
|
|
||||||
|
|
||||||
lint-contributors:
|
|
||||||
if: github.repository == 'lucide-icons/lucide'
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
permissions:
|
|
||||||
contents: read
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
with:
|
|
||||||
fetch-depth: 0
|
|
||||||
ref: refs/pull/${{ github.event.pull_request.number }}/merge
|
|
||||||
- name: Get changed files
|
|
||||||
id: changed-files
|
|
||||||
uses: tj-actions/changed-files@v41
|
|
||||||
with:
|
|
||||||
files: icons/*
|
|
||||||
- uses: actions/setup-node@v4
|
|
||||||
- name: Install simple-git (safer and faster than installing all deps)
|
|
||||||
run: npm install simple-git
|
|
||||||
- name: Generate annotations
|
|
||||||
run: node ./scripts/updateContributors.mjs
|
|
||||||
env:
|
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
FETCH_DEPTH: ${{ github.event.pull_request.commits }}
|
|
||||||
CHANGED_FILES: ${{ steps.changed-files.outputs.all_changed_files }}
|
|
||||||
- name: Generate annotations
|
|
||||||
env:
|
|
||||||
ANNOTATION_SEVERITY: notice
|
|
||||||
ANNOTATION_TITLE: Contributors have changed!
|
|
||||||
ANNOTATION_DESCRIPTION: Don't add people who have only performed automatic optimizations.
|
|
||||||
run: |
|
|
||||||
git diff --unified=0 -- icons/*.json | # diff icon metadata (unified=0 gives the correct chunk line number)
|
|
||||||
perl -ne '/^(\+|- |@)/ && print' | # get chunks (lines that start with "+++", "@@", "+ ", "- ")
|
|
||||||
perl -pe 's/\n/%0A/' | # url encode line breaks (\n -> %0A)
|
|
||||||
perl -pe 's/%0A(\+\+\+ b\/)/\n\1/g' | # split chunks(one chunk per line)
|
|
||||||
perl -pe "s/\+\+\+ b\/([^@]*)%0A@@ -(\d+)[^\s]* \+(\d+)[^@]*@@(.*)/::$ANNOTATION_SEVERITY file=\1,line=\2,endLine=\3,title=$ANNOTATION_TITLE::$ANNOTATION_DESCRIPTION%0A\4/"
|
|
||||||
# Example for the previous substitution
|
|
||||||
# input: +++ b/icons/accessibility.json%0A@@ -2,0 +3 @@%0A+ "contributors": ["hi"],%0A@@ -13 +14 @@%0A+}%0A
|
|
||||||
# output: ::$ANNOTATION_SEVERITY file=icons/accessibility.json,line=2,endLine=3,title=$ANNOTATION_TITLE::$ANNOTATION_DESCRIPTION%0A%0A+ "contributors": ["hi"],%0A@@ -13 +14 @@%0A+}%0A
|
|
||||||
|
|
||||||
generate-changed-icons-comment:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
permissions:
|
|
||||||
contents: read
|
|
||||||
pull-requests: write
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
with:
|
|
||||||
fetch-depth: 0
|
|
||||||
ref: refs/pull/${{ github.event.pull_request.number }}/merge
|
|
||||||
|
|
||||||
- name: Get changed files
|
|
||||||
id: changed-files
|
|
||||||
uses: tj-actions/changed-files@v41
|
|
||||||
with:
|
|
||||||
files: icons/*.svg
|
|
||||||
|
|
||||||
- name: Find Comment
|
|
||||||
uses: peter-evans/find-comment@v2
|
|
||||||
id: pr-comment
|
|
||||||
with:
|
|
||||||
issue-number: ${{ github.event.pull_request.number }}
|
|
||||||
comment-author: 'github-actions[bot]'
|
|
||||||
body-includes: Added or changed icons
|
|
||||||
|
|
||||||
- name: Generate comment markup
|
|
||||||
run: node ./scripts/generateChangedIconsCommentMarkup.mjs >> comment-markup.md
|
|
||||||
id: comment-markup
|
|
||||||
env:
|
|
||||||
CHANGED_FILES: ${{ steps.changed-files.outputs.all_changed_files }}
|
|
||||||
|
|
||||||
- name: Create or update comment
|
|
||||||
uses: peter-evans/create-or-update-comment@v3
|
|
||||||
with:
|
|
||||||
comment-id: ${{ steps.pr-comment.outputs.comment-id }}
|
|
||||||
issue-number: ${{ github.event.pull_request.number }}
|
|
||||||
body-path: ./comment-markup.md
|
|
||||||
edit-mode: replace
|
|
||||||
38
.github/workflows/release.yml
vendored
38
.github/workflows/release.yml
vendored
@@ -38,6 +38,8 @@ jobs:
|
|||||||
if: github.repository == 'lucide-icons/lucide'
|
if: github.repository == 'lucide-icons/lucide'
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
needs: pre-release
|
needs: pre-release
|
||||||
|
permissions:
|
||||||
|
id-token: write
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
@@ -52,16 +54,16 @@ jobs:
|
|||||||
'lucide-preact',
|
'lucide-preact',
|
||||||
'lucide-solid',
|
'lucide-solid',
|
||||||
'lucide-svelte',
|
'lucide-svelte',
|
||||||
|
'@lucide/astro',
|
||||||
|
'@lucide/svelte',
|
||||||
]
|
]
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
- uses: pnpm/action-setup@v2
|
- uses: pnpm/action-setup@v4
|
||||||
with:
|
|
||||||
version: 8
|
|
||||||
- uses: actions/setup-node@v4
|
- uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
node-version: 18
|
|
||||||
cache: 'pnpm'
|
cache: 'pnpm'
|
||||||
|
node-version-file: 'package.json'
|
||||||
|
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: pnpm install --frozen-lockfile
|
run: pnpm install --frozen-lockfile
|
||||||
@@ -79,22 +81,24 @@ jobs:
|
|||||||
run: pnpm --filter ${{ matrix.package }} test
|
run: pnpm --filter ${{ matrix.package }} test
|
||||||
|
|
||||||
- name: Publish
|
- name: Publish
|
||||||
run: pnpm --filter ${{ matrix.package }} publish --no-git-checks --ignore-scripts
|
run: pnpm --filter ${{ matrix.package }} publish --access public --no-git-checks --ignore-scripts
|
||||||
|
env:
|
||||||
|
NPM_CONFIG_PROVENANCE: true
|
||||||
|
|
||||||
lucide-static:
|
lucide-static:
|
||||||
if: github.repository == 'lucide-icons/lucide'
|
if: github.repository == 'lucide-icons/lucide'
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
needs: [pre-release, lucide-font]
|
needs: [pre-release, lucide-font]
|
||||||
|
permissions:
|
||||||
|
id-token: write
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
- uses: actions/download-artifact@v3
|
- uses: actions/download-artifact@v4
|
||||||
- uses: pnpm/action-setup@v2
|
- uses: pnpm/action-setup@v4
|
||||||
with:
|
|
||||||
version: 8
|
|
||||||
- uses: actions/setup-node@v4
|
- uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
node-version: 18
|
|
||||||
cache: 'pnpm'
|
cache: 'pnpm'
|
||||||
|
node-version-file: 'package.json'
|
||||||
|
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: pnpm install --frozen-lockfile
|
run: pnpm install --frozen-lockfile
|
||||||
@@ -113,6 +117,8 @@ jobs:
|
|||||||
|
|
||||||
- name: Publish
|
- name: Publish
|
||||||
run: pnpm --filter lucide-static publish --no-git-checks
|
run: pnpm --filter lucide-static publish --no-git-checks
|
||||||
|
env:
|
||||||
|
NPM_CONFIG_PROVENANCE: true
|
||||||
|
|
||||||
lucide-font:
|
lucide-font:
|
||||||
if: github.repository == 'lucide-icons/lucide'
|
if: github.repository == 'lucide-icons/lucide'
|
||||||
@@ -120,13 +126,11 @@ jobs:
|
|||||||
needs: pre-release
|
needs: pre-release
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
- uses: pnpm/action-setup@v2
|
- uses: pnpm/action-setup@v4
|
||||||
with:
|
|
||||||
version: 8
|
|
||||||
- uses: actions/setup-node@v4
|
- uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
node-version: 18
|
|
||||||
cache: 'pnpm'
|
cache: 'pnpm'
|
||||||
|
node-version-file: 'package.json'
|
||||||
|
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: pnpm install --frozen-lockfile
|
run: pnpm install --frozen-lockfile
|
||||||
@@ -138,7 +142,7 @@ jobs:
|
|||||||
run: pnpm build:font
|
run: pnpm build:font
|
||||||
|
|
||||||
- name: 'Upload to Artifacts'
|
- name: 'Upload to Artifacts'
|
||||||
uses: actions/upload-artifact@v3
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: lucide-font
|
name: lucide-font
|
||||||
path: lucide-font
|
path: lucide-font
|
||||||
@@ -150,14 +154,14 @@ jobs:
|
|||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
- uses: actions/download-artifact@v3
|
- uses: actions/download-artifact@v4
|
||||||
- name: Zip font and icons
|
- name: Zip font and icons
|
||||||
run: |
|
run: |
|
||||||
zip -r lucide-font-${{ needs.pre-release.outputs.VERSION }}.zip lucide-font
|
zip -r lucide-font-${{ needs.pre-release.outputs.VERSION }}.zip lucide-font
|
||||||
zip -r lucide-icons-${{ needs.pre-release.outputs.VERSION }}.zip icons
|
zip -r lucide-icons-${{ needs.pre-release.outputs.VERSION }}.zip icons
|
||||||
|
|
||||||
- name: Release zip and fonts
|
- name: Release zip and fonts
|
||||||
uses: softprops/action-gh-release@v1
|
uses: softprops/action-gh-release@v2
|
||||||
with:
|
with:
|
||||||
tag_name: ${{ needs.pre-release.outputs.VERSION }}
|
tag_name: ${{ needs.pre-release.outputs.VERSION }}
|
||||||
files: |
|
files: |
|
||||||
|
|||||||
32
.github/workflows/request-review.yml
vendored
Normal file
32
.github/workflows/request-review.yml
vendored
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
name: 'Request Review'
|
||||||
|
on:
|
||||||
|
pull_request_target:
|
||||||
|
types: [opened]
|
||||||
|
paths: icons/*.svg
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
request-review:
|
||||||
|
if: github.event.pull_request.draft == false
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
pull-requests: write
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
fetch-depth: 0
|
||||||
|
ref: refs/pull/${{ github.event.pull_request.number }}/merge
|
||||||
|
- name: Get changed files
|
||||||
|
id: changed-files
|
||||||
|
uses: tj-actions/changed-files@v41
|
||||||
|
with:
|
||||||
|
files: icons/*.svg
|
||||||
|
- run: |
|
||||||
|
while IFS= read -r file; do
|
||||||
|
jq -r '.contributors[]' "${file%.svg}.json"
|
||||||
|
done <<< "$CHANGED_FILES" | while read -r contributor; do
|
||||||
|
gh pr edit "${{ github.event.pull_request.number }}" --add-reviewer "$contributor" || true
|
||||||
|
done
|
||||||
|
env:
|
||||||
|
GH_TOKEN: ${{ github.token }}
|
||||||
|
CHANGED_FILES: ${{ steps.changed-files.outputs.all_changed_files }}
|
||||||
9
.gitignore
vendored
9
.gitignore
vendored
@@ -16,11 +16,17 @@ outlined
|
|||||||
packages/**/src/icons/*.js
|
packages/**/src/icons/*.js
|
||||||
packages/**/src/icons/*.ts
|
packages/**/src/icons/*.ts
|
||||||
packages/**/src/icons/*.tsx
|
packages/**/src/icons/*.tsx
|
||||||
|
packages/**/src/aliases/*.ts
|
||||||
packages/**/src/aliases.ts
|
packages/**/src/aliases.ts
|
||||||
|
!packages/**/src/aliases/index.ts
|
||||||
packages/**/src/dynamicIconImports.ts
|
packages/**/src/dynamicIconImports.ts
|
||||||
|
packages/**/DynamicIcon.d.ts
|
||||||
packages/**/dynamicIconImports.js
|
packages/**/dynamicIconImports.js
|
||||||
packages/**/dynamicIconImports.d.ts
|
packages/**/dynamicIconImports.d.ts
|
||||||
packages/**/dynamicIconImports.js.map
|
packages/**/dynamicIconImports.js.map
|
||||||
|
packages/**/dynamic.d.ts
|
||||||
|
packages/**/dynamic.mjs.map
|
||||||
|
packages/**/dynamic.mjs
|
||||||
packages/**/LICENSE
|
packages/**/LICENSE
|
||||||
categories.json
|
categories.json
|
||||||
tags.json
|
tags.json
|
||||||
@@ -34,7 +40,10 @@ docs/.vitepress/data/iconNodes
|
|||||||
docs/.vitepress/data/iconMetaData.ts
|
docs/.vitepress/data/iconMetaData.ts
|
||||||
docs/.vitepress/data/releaseMetaData.json
|
docs/.vitepress/data/releaseMetaData.json
|
||||||
docs/.vitepress/data/releaseMetaData
|
docs/.vitepress/data/releaseMetaData
|
||||||
|
docs/.vitepress/data/categoriesData.json
|
||||||
docs/.vitepress/data/iconDetails
|
docs/.vitepress/data/iconDetails
|
||||||
docs/.vitepress/data/relatedIcons.json
|
docs/.vitepress/data/relatedIcons.json
|
||||||
docs/.vercel
|
docs/.vercel
|
||||||
docs/.nitro
|
docs/.nitro
|
||||||
|
.gitignore
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,10 @@ pnpm-lock.yaml
|
|||||||
|
|
||||||
# docs examples
|
# docs examples
|
||||||
docs/**/examples/
|
docs/**/examples/
|
||||||
|
docs/.vitepress/.temp
|
||||||
|
docs/.vitepress/cache
|
||||||
|
docs/.vitepress/data
|
||||||
|
docs/.nitro
|
||||||
|
|
||||||
# lucide-angular
|
# lucide-angular
|
||||||
packages/lucide-angular/.angular/cache
|
packages/lucide-angular/.angular/cache
|
||||||
|
|||||||
@@ -16,10 +16,10 @@ Guidelines for pull requests:
|
|||||||
|
|
||||||
- __Make your commit messages as descriptive as possible.__ Include as much information as you can. Explain anything that the file diffs themselves won’t make apparent.
|
- __Make your commit messages as descriptive as possible.__ Include as much information as you can. Explain anything that the file diffs themselves won’t make apparent.
|
||||||
- __Document your pull request__. Explain your fix, link to the relevant issue, add screenshots when adding new icons.
|
- __Document your pull request__. Explain your fix, link to the relevant issue, add screenshots when adding new icons.
|
||||||
- __Make sure the target of your pull request is the relevant branch__. Most of bugfix or new feature should go to the `main` branch.
|
- __Make sure the target of your pull request is the relevant branch__. Most of bug fixes or new feature should go to the `main` branch.
|
||||||
- __Include only related work__. If your pull request has unrelated commit, it won't be accepted.
|
- __Include only related work__. If your pull request has unrelated commits, it won't be accepted.
|
||||||
|
|
||||||
### Pull Requests Including Icons
|
### Icon Pull Requests
|
||||||
|
|
||||||
#### Guidelines
|
#### Guidelines
|
||||||
|
|
||||||
@@ -27,24 +27,30 @@ Please make sure you follow the icon guidelines, that should be followed to keep
|
|||||||
|
|
||||||
Read it here: [ICON_GUIDELINES](https://lucide.dev/docs/icon-design-guide).
|
Read it here: [ICON_GUIDELINES](https://lucide.dev/docs/icon-design-guide).
|
||||||
|
|
||||||
### Editor guides
|
#### Lucide Studio
|
||||||
|
|
||||||
|
For formatting and adjusting SVG icons, [@jguddas](https://github.com/jguddas) made a great tool called [Lucide Studio](https://studio.lucide.dev/). It is a web-based SVG editor that allows you to edit and adjust icons in the Lucide style. You can use it to create new icons or modify existing ones.
|
||||||
|
|
||||||
|
#### Editor guides
|
||||||
|
|
||||||
Here you can find instructions on how to implement the guidelines with different vector graphics editors:
|
Here you can find instructions on how to implement the guidelines with different vector graphics editors:
|
||||||
|
|
||||||
#### [Adobe Illustrator Guide](https://lucide.dev/docs/illustrator-guide)
|
##### [Adobe Illustrator Guide](https://lucide.dev/docs/illustrator-guide)
|
||||||
|
|
||||||
You can also [download an Adobe Illustrator template](https://github.com/lucide-icons/lucide/blob/main/docs/public/templates/illustrator_template.ai).
|
You can also [download an Adobe Illustrator template](https://github.com/lucide-icons/lucide/blob/main/docs/public/templates/illustrator_template.ai).
|
||||||
|
|
||||||
#### [Inkscape Guide](https://lucide.dev/docs/inkscape-guide)
|
##### [Inkscape Guide](https://lucide.dev/docs/inkscape-guide)
|
||||||
|
|
||||||
#### [Figma Guide](https://lucide.dev/docs/figma-guide)
|
##### [Figma Guide](https://lucide.dev/docs/figma-guide)
|
||||||
|
|
||||||
### Submitting Multiple Icons
|
##### [Affinity Designer Guide](https://lucide.dev/guide/design/affinity-designer-guide)
|
||||||
|
|
||||||
If you want submit multiple icons, please separate the icons and group them. That makes reviewing the icons easier and keep the thread clean and scoped.
|
#### Submitting Multiple Icons
|
||||||
So don't submit multiple icons in one PR that have noting to do with each other.
|
|
||||||
|
If you want to submit multiple icons, please separate the icons and group them. That makes reviewing the icons easier and keeps the thread clean and scoped.
|
||||||
|
So don't submit multiple icons in one PR that have nothing to do with each other.
|
||||||
So for example don't create one PR with icons: `arrow-up`, `bicycle`, `arrow-down`.
|
So for example don't create one PR with icons: `arrow-up`, `bicycle`, `arrow-down`.
|
||||||
Seperate them by two PRs; 'pr-01' `arrow`, `arrow-down` and 'pr-02' `bicycle`.
|
Separate them into two PRs; 'pr-01' `arrow`, `arrow-down` and 'pr-02' `bicycle`.
|
||||||
|
|
||||||
## Icon Requests
|
## Icon Requests
|
||||||
|
|
||||||
@@ -70,12 +76,12 @@ pnpm install # Install dependencies, including the workspace packages
|
|||||||
|
|
||||||
### Packages -> PNPM Workspaces
|
### Packages -> PNPM Workspaces
|
||||||
|
|
||||||
To distribute different packages we use PNPM workspaces. Before you start make sure you are familiar with this concept. The concept of working in workspaces is created by Yarn, they have a well written introduction: [yarn workspaces](https://classic.yarnpkg.com/lang/enhttps://lucide.dev/docs/workspaces).
|
To distribute different packages we use [PNPM workspaces](https://pnpm.io/workspaces). Before you start make sure you are familiar with this concept. The concept of working in workspaces is created by Yarn, they have a well written introduction: [yarn workspaces](https://classic.yarnpkg.com/en/docs/workspaces).
|
||||||
|
|
||||||
The configured directory for workspaces is the [packages](https://github.com/lucide-icons/lucide/tree/main/packages) directory, located in the root directory. There you will find all the current packages from lucide.
|
The configured directory for workspaces is the [packages](https://github.com/lucide-icons/lucide/tree/main/packages) directory, located in the root directory. There you will find all the current packages from lucide.
|
||||||
There are more workspaces defined, see [`pnpm-workspace.yaml`](https://github.com/lucide-icons/lucide/blob/main/pnpm-workspace.yaml).
|
There are more workspaces defined, see [`pnpm-workspace.yaml`](https://github.com/lucide-icons/lucide/blob/main/pnpm-workspace.yaml).
|
||||||
|
|
||||||
> Note: One package is not managed by pnpm: **lucide-flutter**, this package is written in Dart and used pub for publishing.
|
> Note: One package is not managed by pnpm: **lucide-flutter**, this package is written in Dart and uses pub for publishing.
|
||||||
|
|
||||||
### Generated Code
|
### Generated Code
|
||||||
|
|
||||||
@@ -125,7 +131,7 @@ When adding new features to for example the icon component for a framework. It i
|
|||||||
|
|
||||||
### Local Testing
|
### Local Testing
|
||||||
|
|
||||||
To test changes in a local project, you can use `yarn link`, `npm link` or `pnpm link` to link the package. Before you do this make sure you builded the package first.
|
To test changes in a local project, you can use `yarn link`, `npm link`, `bun link` or `pnpm link` to link the package. Before you do this make sure you've built the package first.
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
# in packages/lucide-react
|
# in packages/lucide-react
|
||||||
@@ -163,15 +169,15 @@ Detailed documentation about: installation, guides, packages, design guides etc.
|
|||||||
|
|
||||||
All the icons of lucide in SVG format. These will be used as source for all the packages and other distributions for the lucide icons.
|
All the icons of lucide in SVG format. These will be used as source for all the packages and other distributions for the lucide icons.
|
||||||
|
|
||||||
### packages
|
### Packages
|
||||||
|
|
||||||
Includes all the (npm) packages of lucide.
|
Includes all the (npm) packages of lucide.
|
||||||
|
|
||||||
> Note: One package is not managed by pnpm: **lucide-flutter**, this package is written in Dart and used pub for publishing.
|
> Note: One package is not managed by pnpm: **lucide-flutter**, this package is written in Dart and uses pub for publishing.
|
||||||
|
|
||||||
### scripts
|
### Scripts
|
||||||
|
|
||||||
Includes usefully scripts to automate certain jobs. Big part of the scripts is the template generation, for example it generates icon components for all the packages. These scripts are usually executed from the "scripts" section in the package.json.
|
Includes useful scripts to automate certain jobs. Big part of the scripts is the template generation, for example it generates icon components for all the packages. These scripts are usually executed from the "scripts" section in the package.json.
|
||||||
|
|
||||||
## Documentation
|
## Documentation
|
||||||
|
|
||||||
@@ -188,4 +194,4 @@ If you need any help or have problems with you contribution. Please don't hesita
|
|||||||
Thank you to all the people who already contributed to Lucide!
|
Thank you to all the people who already contributed to Lucide!
|
||||||
|
|
||||||
<a href="https://github.com/lucide-icons/lucide/graphs/contributors">
|
<a href="https://github.com/lucide-icons/lucide/graphs/contributors">
|
||||||
<img src="https://opencollective.com/lucide-icons/contributors.svg?width=890" /></a>
|
<img src="https://opencollective.com/lucide-icons/contributors.svg?width=800" /></a>
|
||||||
|
|||||||
280
README.md
280
README.md
@@ -1,185 +1,47 @@
|
|||||||
<p align=center><img width="480" src="https://lucide.dev/lucide-logo-repo.svg" alt="Lucide Logo"></p>
|
<p align="center">
|
||||||
|
<a href="https://github.com/lucide-icons/lucide#gh-light-mode-only">
|
||||||
|
<img src="https://lucide.dev/lucide-logo-repo.svg#gh-light-mode-only" alt="Lucide - Beautiful & consistent icon toolkit made by the community. Open-source project and a fork of Feather Icons." width="480">
|
||||||
|
</a>
|
||||||
|
<a href="https://github.com/lucide-icons/lucide#gh-dark-mode-only">
|
||||||
|
<img src="https://lucide.dev/lucide-logo-repo-dark.svg#gh-dark-mode-only" alt="Lucide - Beautiful & consistent icon toolkit made by the community. Open-source project and a fork of Feather Icons." width="480">
|
||||||
|
</a>
|
||||||
|
</p>
|
||||||
<p align="center">
|
<p align="center">
|
||||||
<a href="https://github.com/lucide-icons/lucide/blob/main/LICENSE"><img src="https://img.shields.io/npm/l/lucide" alt="license"></a>
|
<a href="https://github.com/lucide-icons/lucide/blob/main/LICENSE"><img src="https://img.shields.io/npm/l/lucide" alt="license"></a>
|
||||||
<a href="https://www.npmjs.com/package/lucide"><img src="https://img.shields.io/npm/v/lucide" alt="npm package"></a>
|
<a href="https://www.figma.com/community/plugin/939567362549682242/Lucide-Icons"><img src="https://img.shields.io/badge/Figma-F24E1E?logo=figma&logoColor=white" alt="figma installs"></a>
|
||||||
<a href="https://www.figma.com/community/plugin/939567362549682242/Lucide-Icons"><img src="https://img.shields.io/endpoint?logo=figma&label=installs&url=https://yuanqing.github.io/figma-plugins-stats/plugin/939567362549682242/installs.json" alt="figma installs"></a>
|
|
||||||
<a href="https://github.com/lucide-icons/lucide/actions/workflows/release.yml"><img src="https://github.com/lucide-icons/lucide/actions/workflows/release.yml/badge.svg" alt="build status"></a>
|
<a href="https://github.com/lucide-icons/lucide/actions/workflows/release.yml"><img src="https://github.com/lucide-icons/lucide/actions/workflows/release.yml/badge.svg" alt="build status"></a>
|
||||||
<a href="https://discord.gg/EH6nSts"><img src="https://img.shields.io/discord/723074157486800936?label=chat&logo=discord&logoColor=%23ffffff&colorB=%237289DA" alt="discord chat"></a>
|
<a href="https://discord.gg/EH6nSts"><img src="https://img.shields.io/discord/723074157486800936?label=chat&logo=discord&logoColor=%23ffffff&colorB=%237289DA" alt="discord chat"></a>
|
||||||
</p>
|
</p>
|
||||||
|
<p align="center">
|
||||||
|
<a href="https://lucide.dev/icons/">Icons</a>
|
||||||
|
·
|
||||||
|
<a href="https://lucide.dev/guide/">Guide</a>
|
||||||
|
·
|
||||||
|
<a href="https://lucide.dev/packages">Packages</a>
|
||||||
|
·
|
||||||
|
<a href="https://lucide.dev/license">License</a>
|
||||||
|
·
|
||||||
|
<a href="https://lucide.dev/showcase">Showcase</a>
|
||||||
|
</p>
|
||||||
|
|
||||||
# Lucide
|
# Lucide
|
||||||
|
|
||||||
Community-run fork of [Feather Icons](https://github.com/feathericons/feather), open for anyone to contribute icons.
|
Lucide is an open-source icon library that provides 1000+ vector (svg) files for displaying icons and symbols in digital and non-digital projects. The library aims to make it easier for designers and developers to incorporate icons into their projects by providing several official [packages](https://lucide.dev/packages) to make it easier to use these icons in your project.
|
||||||
|
|
||||||
It began after growing dissatisfaction with the [Feather Icons](https://github.com/feathericons/feather) project moderation. With over 300+ open issues and over 100+ open PRs, the Feather Icons project has been abandoned. This unfortunately means that hundreds of developers and designers wasted their time contributing to Feather Icons with no chance of PRs being accepted.
|
## Packages
|
||||||
|
|
||||||
Lucide is trying to expand the icon set as much as possible while staying faithful to the original simplistic design language. We do this as a community of devs and designers and hope that you'll join us!
|
| Logo | Package | Version | Downloads | Links |
|
||||||
|
| ---- | ------- | ------- | --------- | ----- |
|
||||||
### Why choose Lucide over Feather Icons
|
| <img src="https://lucide.dev/framework-logos/js.svg" alt="JS logo" width="48"> | **`lucide`** | [](https://www.npmjs.com/package/lucide) |  | [Docs](https://lucide.dev/guide/packages/lucide) · [Source](./packages/lucide) |
|
||||||
|
| <img src="https://lucide.dev/framework-logos/react.svg" alt="React logo" width="48"> | **`lucide-react`** | [](https://www.npmjs.com/package/lucide-react) |  | [Docs](https://lucide.dev/guide/packages/lucide-react) · [Source](./packages/lucide-react) |
|
||||||
- More icons to work with: Lucide already has hundreds of icons more than Feather does.
|
| <img src="https://lucide.dev/framework-logos/vue.svg" alt="Vue logo" width="48"> | **`lucide-vue-next`** | [](https://www.npmjs.com/package/lucide-vue-next) |  | [Docs](https://lucide.dev/guide/packages/lucide-vue-next) · [Source](./packages/lucide-vue-next) |
|
||||||
- Official libraries and integrations with popular frameworks and design tools.
|
| <img src="https://lucide.dev/framework-logos/svelte.svg" alt="Svelte logo" width="48"> | **`lucide-svelte`** | [](https://www.npmjs.com/package/lucide-svelte) |  | [Docs](https://lucide.dev/guide/packages/lucide-svelte) · [Source](./packages/lucide-svelte) |
|
||||||
- Well maintained code base.
|
| <img src="https://lucide.dev/framework-logos/solid.svg" alt="Solid logo" width="48"> | **`lucide-solid`** | [](https://www.npmjs.com/package/lucide-solid) |  | [Docs](https://lucide.dev/guide/packages/lucide-solid) · [Source](./packages/lucide-solid) |
|
||||||
- Active community, regularly growing and improving the set.
|
| <img src="https://lucide.dev/framework-logos/preact.svg" alt="Preact logo" width="48"> | **`lucide-preact`** | [](https://www.npmjs.com/package/lucide-preact) |  | [Docs](https://lucide.dev/guide/packages/lucide-preact) · [Source](./packages/lucide-preact) |
|
||||||
|
| <img src="https://lucide.dev/framework-logos/react-native.svg" alt="React Native logo" width="48"> | **`lucide-react-native`** | [](https://www.npmjs.com/package/lucide-react-native) |  | [Docs](https://lucide.dev/guide/packages/lucide-react-native) · [Source](./packages/lucide-react-native) |
|
||||||
## Table of Contents
|
| <img src="https://lucide.dev/framework-logos/angular.svg" alt="Angular logo" width="48"> | **`lucide-angular`** | [](https://www.npmjs.com/package/lucide-angular) |  | [Docs](https://lucide.dev/guide/packages/lucide-angular) · [Source](./packages/lucide-angular) |
|
||||||
|
| <img src="https://lucide.dev/framework-logos/astro.svg" alt="Astro logo" width="48"> | **`@lucide/astro`** | [](https://www.npmjs.com/package/@lucide/astro) |  | [Docs](https://lucide.dev/guide/packages/lucide-astro) · [Source](./packages/astro) |
|
||||||
- [Usage](#usage)
|
| <img src="https://lucide.dev/framework-logos/svg.svg" alt="SVG logo" width="48"> | **`lucide-static`** | [](https://www.npmjs.com/package/lucide-static) |  | [Docs](https://lucide.dev/guide/packages/lucide-static) · [Source](./packages/lucide-static) |
|
||||||
- [Web](#web)
|
|
||||||
- [React](#react)
|
|
||||||
- [React Native](#react-native)
|
|
||||||
- [Vue 2](#vue-2)
|
|
||||||
- [Vue 3](#vue-3)
|
|
||||||
- [Angular](#angular)
|
|
||||||
- [Preact](#preact)
|
|
||||||
- [Static (svg sprite, font, icons ..)](#static-svg-sprite-font-icons-)
|
|
||||||
- [Figma](#figma)
|
|
||||||
- [Laravel](#laravel)
|
|
||||||
- [Svelte](#svelte)
|
|
||||||
- [Solid](#solid)
|
|
||||||
- [Hyva](#hyva)
|
|
||||||
- [Eleventy](#eleventy)
|
|
||||||
- [Contributing](#contributing)
|
|
||||||
- [Community](#community)
|
|
||||||
- [License](#license)
|
|
||||||
- [Credits](#credits)
|
|
||||||
- [Sponsors](#sponsors)
|
|
||||||
|
|
||||||
## Usage
|
|
||||||
|
|
||||||
At its core, Lucide is a collection of [SVG](https://svgontheweb.com/#svg) files. This means that you can use Lucide icons in all the same ways you can use SVGs (e.g. `img`, `background-image`, `inline`, `object`, `embed`, `iframe`). Here's a helpful article detailing the many ways SVGs can be used on the web: [SVG on the Web – Implementation Options](https://svgontheweb.com/#implementation)
|
|
||||||
|
|
||||||
The following are additional ways you can use Lucide.
|
|
||||||
With the Javascript library you can easily incorporate the icon you want in your webpage.
|
|
||||||
|
|
||||||
### Web
|
|
||||||
|
|
||||||
Implementation of the lucide icon library for web applications.
|
|
||||||
|
|
||||||
```sh
|
|
||||||
npm install lucide
|
|
||||||
```
|
|
||||||
|
|
||||||
or
|
|
||||||
|
|
||||||
```sh
|
|
||||||
yarn add lucide
|
|
||||||
```
|
|
||||||
|
|
||||||
For more details, see the [documentation](https://github.com/lucide-icons/lucide/tree/main/packages/lucide#lucide).
|
|
||||||
|
|
||||||
### React
|
|
||||||
|
|
||||||
Implementation of the lucide icon library for react applications.
|
|
||||||
|
|
||||||
```sh
|
|
||||||
yarn add lucide-react
|
|
||||||
```
|
|
||||||
|
|
||||||
or
|
|
||||||
|
|
||||||
```sh
|
|
||||||
npm install lucide-react
|
|
||||||
```
|
|
||||||
|
|
||||||
For more details, see the [documentation](https://github.com/lucide-icons/lucide/tree/main/packages/lucide-react#lucide-react).
|
|
||||||
|
|
||||||
### React Native
|
|
||||||
|
|
||||||
Implementation of the lucide icon library for React Native applications.
|
|
||||||
|
|
||||||
```sh
|
|
||||||
yarn add lucide-react-native
|
|
||||||
```
|
|
||||||
|
|
||||||
or
|
|
||||||
|
|
||||||
```sh
|
|
||||||
npm install lucide-react-native
|
|
||||||
```
|
|
||||||
|
|
||||||
For more details, see the [documentation](https://github.com/lucide-icons/lucide/tree/main/packages/lucide-react-native#lucide-react-native).
|
|
||||||
|
|
||||||
### Vue 2
|
|
||||||
|
|
||||||
Implementation of the lucide icon library for vue applications.
|
|
||||||
|
|
||||||
```sh
|
|
||||||
yarn add lucide-vue
|
|
||||||
```
|
|
||||||
|
|
||||||
or
|
|
||||||
|
|
||||||
```sh
|
|
||||||
npm install lucide-vue
|
|
||||||
```
|
|
||||||
|
|
||||||
For more details, see the [documentation](https://github.com/lucide-icons/lucide/tree/main/packages/lucide-vue#lucide-vue).
|
|
||||||
|
|
||||||
### Vue 3
|
|
||||||
|
|
||||||
Implementation of the lucide icon library for vue applications.
|
|
||||||
|
|
||||||
```sh
|
|
||||||
yarn add lucide-vue-next
|
|
||||||
```
|
|
||||||
|
|
||||||
or
|
|
||||||
|
|
||||||
```sh
|
|
||||||
npm install lucide-vue-next
|
|
||||||
```
|
|
||||||
|
|
||||||
For more details, see the [documentation](https://github.com/lucide-icons/lucide/tree/main/packages/lucide-vue-next#lucide-vue-next).
|
|
||||||
|
|
||||||
### Angular
|
|
||||||
|
|
||||||
```sh
|
|
||||||
yarn add lucide-angular
|
|
||||||
```
|
|
||||||
|
|
||||||
or
|
|
||||||
|
|
||||||
```sh
|
|
||||||
npm install lucide-angular
|
|
||||||
```
|
|
||||||
|
|
||||||
For more details, see the [documentation](https://github.com/lucide-icons/lucide/tree/main/packages/lucide-angular#lucide-angular).
|
|
||||||
|
|
||||||
### Preact
|
|
||||||
|
|
||||||
Implementation of the lucide icon library for preact applications.
|
|
||||||
|
|
||||||
```sh
|
|
||||||
yarn add lucide-preact
|
|
||||||
```
|
|
||||||
|
|
||||||
or
|
|
||||||
|
|
||||||
```sh
|
|
||||||
npm install lucide-preact
|
|
||||||
```
|
|
||||||
|
|
||||||
For more details, see the [documentation](https://github.com/lucide-icons/lucide/tree/main/packages/lucide-preact#lucide-preact).
|
|
||||||
|
|
||||||
### Static (svg sprite, font, icons ..)
|
|
||||||
|
|
||||||
Assets:
|
|
||||||
[Font Files](https://github.com/lucide-icons/lucide/releases/latest)
|
|
||||||
[SVG Files](https://github.com/lucide-icons/lucide/releases/latest)
|
|
||||||
[SVG Sprite](https://cdn.jsdelivr.net/npm/lucide-static@latest/sprite.svg)
|
|
||||||
|
|
||||||
NPM package
|
|
||||||
|
|
||||||
```sh
|
|
||||||
yarn add lucide-static
|
|
||||||
```
|
|
||||||
|
|
||||||
or
|
|
||||||
|
|
||||||
```sh
|
|
||||||
npm install lucide-static
|
|
||||||
```
|
|
||||||
|
|
||||||
### Figma
|
### Figma
|
||||||
|
|
||||||
@@ -189,68 +51,6 @@ Visit [Figma community page](https://www.figma.com/community/plugin/939567362549
|
|||||||
|
|
||||||
<img width="420" src="https://www.figma.com/community/plugin/939567362549682242/thumbnail" alt="Figma Lucide Cover">
|
<img width="420" src="https://www.figma.com/community/plugin/939567362549682242/thumbnail" alt="Figma Lucide Cover">
|
||||||
|
|
||||||
### Laravel
|
|
||||||
|
|
||||||
Implementation of Lucide icon's using `blade-icons` for Laravel based projects.
|
|
||||||
|
|
||||||
```sh
|
|
||||||
composer require mallardduck/blade-lucide-icons
|
|
||||||
```
|
|
||||||
|
|
||||||
For more details, see the [documentation](https://github.com/mallardduck/blade-lucide-icons/blob/main/README.md).
|
|
||||||
|
|
||||||
### Svelte
|
|
||||||
|
|
||||||
Implementation of the lucide icon library for Svelte applications.
|
|
||||||
|
|
||||||
```sh
|
|
||||||
yarn add lucide-svelte
|
|
||||||
```
|
|
||||||
|
|
||||||
or
|
|
||||||
|
|
||||||
```sh
|
|
||||||
npm install lucide-svelte
|
|
||||||
```
|
|
||||||
|
|
||||||
For more details, see the [documentation](https://github.com/lucide-icons/lucide/tree/main/packages/lucide-svelte#lucide-svelte).
|
|
||||||
|
|
||||||
### Solid
|
|
||||||
|
|
||||||
Implementation of the lucide icon library for solid applications.
|
|
||||||
|
|
||||||
```sh
|
|
||||||
yarn add lucide-solid
|
|
||||||
```
|
|
||||||
|
|
||||||
or
|
|
||||||
|
|
||||||
```sh
|
|
||||||
npm install lucide-solid
|
|
||||||
```
|
|
||||||
|
|
||||||
For more details, see the [documentation](https://github.com/lucide-icons/lucide/tree/main/packages/lucide-solid#lucide-solid).
|
|
||||||
|
|
||||||
### Hyva
|
|
||||||
|
|
||||||
Implementation of Lucide icon's using Hyvä's svg php viewmodal to render icons for Magento 2 Hyva theme based projects.
|
|
||||||
|
|
||||||
```sh
|
|
||||||
composer require siteation/magento2-hyva-icons-lucide
|
|
||||||
```
|
|
||||||
|
|
||||||
For more details, see the [documentation](https://github.com/Siteation/magento2-hyva-icons-lucide/blob/main/README.md).
|
|
||||||
|
|
||||||
### Eleventy
|
|
||||||
|
|
||||||
Using this plugin, Eleventy projects can incorporate Lucide icons. it makes it simple to use Lucide icons into your themes via shortcodes, improving your website's overall usability and visual appeal.
|
|
||||||
|
|
||||||
```sh
|
|
||||||
npm install @grimlink/eleventy-plugin-lucide-icons
|
|
||||||
```
|
|
||||||
|
|
||||||
For more details, see the [documentation](https://github.com/GrimLink/eleventy-plugin-lucide-icons/blob/main/README.md).
|
|
||||||
|
|
||||||
## Contributing
|
## Contributing
|
||||||
|
|
||||||
For more info on how to contribute please see the [contribution guidelines](https://github.com/lucide-icons/lucide/blob/main/CONTRIBUTING.md).
|
For more info on how to contribute please see the [contribution guidelines](https://github.com/lucide-icons/lucide/blob/main/CONTRIBUTING.md).
|
||||||
@@ -263,20 +63,26 @@ Join the community on our [Discord](https://discord.gg/EH6nSts) server!
|
|||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
Lucide is totally free for commercial use and personally use, this software is licensed under the [ISC License](https://github.com/lucide-icons/lucide/blob/main/LICENSE).
|
Lucide is totally free for commercial use and personal use, this software is licensed under the [ISC License](https://github.com/lucide-icons/lucide/blob/main/LICENSE).
|
||||||
|
|
||||||
## Credits
|
## Credits
|
||||||
|
|
||||||
Thank you to all the people who contributed to Lucide!
|
Thank you to all the people who contributed to Lucide!
|
||||||
|
|
||||||
<a href="https://github.com/lucide-icons/lucide/graphs/contributors">
|
<a href="https://github.com/lucide-icons/lucide/graphs/contributors">
|
||||||
<img src="https://opencollective.com/lucide-icons/contributors.svg?width=890" /></a>
|
|
||||||
|
<img src="https://opencollective.com/lucide-icons/contributors.svg?width=800" />
|
||||||
|
</a>
|
||||||
|
|
||||||
## Sponsors
|
## Sponsors
|
||||||
|
|
||||||
|
|
||||||
<a href="https://vercel.com?utm_source=lucide&utm_campaign=oss">
|
<a href="https://vercel.com?utm_source=lucide&utm_campaign=oss">
|
||||||
<img src="docs/public/vercel.svg" alt="Powered by Vercel" width="200" />
|
<img src="docs/public/vercel.svg" alt="Powered by Vercel" width="200" />
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
<a href="https://www.digitalocean.com/?refcode=b0877a2caebd&utm_campaign=Referral_Invite&utm_medium=Referral_Program&utm_source=badge"><img src="docs/public/digitalocean.svg" width="200" alt="DigitalOcean Referral Badge" /></a>
|
<a href="https://www.digitalocean.com/?refcode=b0877a2caebd&utm_campaign=Referral_Invite&utm_medium=Referral_Program&utm_source=badge"><img src="docs/public/digitalocean.svg" width="200" alt="DigitalOcean Referral Badge" /></a>
|
||||||
|
|
||||||
|
### Awesome backers 🍺
|
||||||
|
|
||||||
|
<a href="https://www.scipress.io?utm_source=lucide"><img src="docs/public/sponsors/scipress.svg" width="180" alt="Scipress sponsor badge" /></a>
|
||||||
|
<a href="https://github.com/pdfme/pdfme"><img src="docs/public/sponsors/pdfme.svg" width="180" alt="pdfme sponsor badge" /></a>
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"$schema": "../category.schema.json",
|
"$schema": "../category.schema.json",
|
||||||
"title": "Charts",
|
"title": "Charts",
|
||||||
"icon": "pie-chart"
|
"icon": "chart-pie"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +0,0 @@
|
|||||||
{
|
|
||||||
"$schema": "../category.schema.json",
|
|
||||||
"title": "Currency",
|
|
||||||
"icon": "dollar-sign"
|
|
||||||
}
|
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"$schema": "../category.schema.json",
|
"$schema": "../category.schema.json",
|
||||||
"title": "Coding & development",
|
"title": "Coding & development",
|
||||||
"icon": "code-2"
|
"icon": "code-xml"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"$schema": "../category.schema.json",
|
"$schema": "../category.schema.json",
|
||||||
"title": "Money",
|
"title": "Finance",
|
||||||
"icon": "piggy-bank"
|
"icon": "piggy-bank"
|
||||||
}
|
}
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
{
|
|
||||||
"$schema": "../category.schema.json",
|
|
||||||
"title": "Furniture",
|
|
||||||
"icon": "rocking-chair"
|
|
||||||
}
|
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"$schema": "../category.schema.json",
|
"$schema": "../category.schema.json",
|
||||||
"title": "Home",
|
"title": "Home",
|
||||||
"icon": "home"
|
"icon": "house"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +0,0 @@
|
|||||||
{
|
|
||||||
"$schema": "../category.schema.json",
|
|
||||||
"title": "Maps",
|
|
||||||
"icon": "map"
|
|
||||||
}
|
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"$schema": "../category.schema.json",
|
"$schema": "../category.schema.json",
|
||||||
"title": "Maths",
|
"title": "Mathematics",
|
||||||
"icon": "divide"
|
"icon": "divide"
|
||||||
}
|
}
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"$schema": "../category.schema.json",
|
"$schema": "../category.schema.json",
|
||||||
"title": "Multimedia",
|
"title": "Multimedia",
|
||||||
"icon": "play-circle"
|
"icon": "circle-play"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"$schema": "../category.schema.json",
|
"$schema": "../category.schema.json",
|
||||||
"title": "Notifications",
|
"title": "Notification",
|
||||||
"icon": "alert-triangle"
|
"icon": "triangle-alert"
|
||||||
}
|
}
|
||||||
|
|||||||
10
cspell.json
Normal file
10
cspell.json
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
{
|
||||||
|
"dictionaries": ["en-us", "custom-words"],
|
||||||
|
"dictionaryDefinitions": [
|
||||||
|
{
|
||||||
|
"name": "custom-words",
|
||||||
|
"path": "./.cspell/custom-words.txt",
|
||||||
|
"addWords": true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -1,4 +1,3 @@
|
|||||||
import { eventHandler, setResponseHeader } from 'h3';
|
|
||||||
import iconMetaData from '../../data/iconMetaData';
|
import iconMetaData from '../../data/iconMetaData';
|
||||||
|
|
||||||
export default eventHandler((event) => {
|
export default eventHandler((event) => {
|
||||||
|
|||||||
40
docs/.vitepress/api/figma/data.ts
Normal file
40
docs/.vitepress/api/figma/data.ts
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
import iconNodes from '../../data/iconNodes/index.ts';
|
||||||
|
import { IconNodeWithKeys } from '../../theme/types';
|
||||||
|
import iconMetaData from '../../data/iconMetaData';
|
||||||
|
import releaseMeta from '../../data/releaseMetaData.json';
|
||||||
|
import categories from '../../data/categoriesData.json';
|
||||||
|
|
||||||
|
const dataResponse = {
|
||||||
|
icons: Object.entries(iconNodes).reduce((acc, [name, iconNode]) => {
|
||||||
|
const newIconNode = (iconNode as IconNodeWithKeys).map(([name, { key, ...attrs }]) => {
|
||||||
|
return [name, attrs];
|
||||||
|
});
|
||||||
|
|
||||||
|
acc[name] = {
|
||||||
|
iconNode: newIconNode,
|
||||||
|
aliases: (iconMetaData[name]?.aliases ?? []).map((alias) =>
|
||||||
|
typeof alias === 'string' ? alias : alias.name,
|
||||||
|
),
|
||||||
|
tags: iconMetaData[name].tags ?? [],
|
||||||
|
categories: iconMetaData[name].categories ?? [],
|
||||||
|
...releaseMeta[name],
|
||||||
|
};
|
||||||
|
|
||||||
|
return acc;
|
||||||
|
}, {}),
|
||||||
|
aliases: Object.entries(iconNodes).reduce((acc, [name]) => {
|
||||||
|
for (const alias of iconMetaData[name]?.aliases ?? []) {
|
||||||
|
acc[typeof alias === 'string' ? alias : alias.name] = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
return acc;
|
||||||
|
}, {}),
|
||||||
|
categories,
|
||||||
|
};
|
||||||
|
|
||||||
|
export default eventHandler((event) => {
|
||||||
|
setResponseHeader(event, 'Cache-Control', 'public, max-age=86400');
|
||||||
|
setResponseHeader(event, 'Access-Control-Allow-Origin', '*');
|
||||||
|
|
||||||
|
return dataResponse;
|
||||||
|
});
|
||||||
@@ -13,7 +13,10 @@ export default eventHandler((event) => {
|
|||||||
const data = pathData.at(-1).slice(0, -4);
|
const data = pathData.at(-1).slice(0, -4);
|
||||||
const [name] = pathData;
|
const [name] = pathData;
|
||||||
|
|
||||||
const src = Buffer.from(data, 'base64').toString('utf8');
|
const src = Buffer.from(data, 'base64')
|
||||||
|
.toString('utf8')
|
||||||
|
.replaceAll('\n', '')
|
||||||
|
.replace(/<svg[^>]*>|<\/svg>/g, '');
|
||||||
|
|
||||||
const children = [];
|
const children = [];
|
||||||
|
|
||||||
@@ -25,18 +28,18 @@ export default eventHandler((event) => {
|
|||||||
.map((_, idx, arr) => arr.slice(0, idx + 1).join('-'))
|
.map((_, idx, arr) => arr.slice(0, idx + 1).join('-'))
|
||||||
.reverse()
|
.reverse()
|
||||||
.find((groupName) => groupName in iconNodes);
|
.find((groupName) => groupName in iconNodes);
|
||||||
if (backdropName) {
|
if (!(name in iconNodes) && backdropName) {
|
||||||
const iconNode = iconNodes[backdropName];
|
const iconNode = iconNodes[backdropName];
|
||||||
|
|
||||||
const LucideIcon = createLucideIcon(backdropName, iconNode);
|
const LucideIcon = createLucideIcon(backdropName, iconNode);
|
||||||
const svg = renderToStaticMarkup(createElement(LucideIcon));
|
const svg = renderToStaticMarkup(createElement(LucideIcon));
|
||||||
const backdropString = svg.replace(/<svg[^>]*>|<\/svg>/g, '');
|
const backdropString = svg.replaceAll('\n', '').replace(/<svg[^>]*>|<\/svg>/g, '');
|
||||||
|
|
||||||
children.push(
|
children.push(
|
||||||
createElement(Backdrop, {
|
createElement(Backdrop, {
|
||||||
backdropString,
|
backdropString,
|
||||||
src,
|
src,
|
||||||
color: name in iconNodes ? 'red' : '#777',
|
color: '#777',
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
37
docs/.vitepress/api/gh-icon/diff/[...data].get.ts
Normal file
37
docs/.vitepress/api/gh-icon/diff/[...data].get.ts
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
import { eventHandler, setResponseHeader, defaultContentType } from 'h3';
|
||||||
|
import { renderToString, renderToStaticMarkup } from 'react-dom/server';
|
||||||
|
import { createElement } from 'react';
|
||||||
|
import Diff from '../../../lib/SvgPreview/Diff.tsx';
|
||||||
|
import iconNodes from '../../../data/iconNodes';
|
||||||
|
import createLucideIcon from 'lucide-react/src/createLucideIcon';
|
||||||
|
|
||||||
|
export default eventHandler((event) => {
|
||||||
|
const { params } = event.context;
|
||||||
|
|
||||||
|
const pathData = params.data.split('/');
|
||||||
|
const data = pathData.at(-1).slice(0, -4);
|
||||||
|
const [name] = pathData;
|
||||||
|
|
||||||
|
const newSrc = Buffer.from(data, 'base64')
|
||||||
|
.toString('utf8')
|
||||||
|
.replaceAll('\n', '')
|
||||||
|
.replace(/<svg[^>]*>|<\/svg>/g, '');
|
||||||
|
|
||||||
|
const children = [];
|
||||||
|
|
||||||
|
const oldSrc = iconNodes[name]
|
||||||
|
? renderToStaticMarkup(createElement(createLucideIcon(name, iconNodes[name])))
|
||||||
|
.replaceAll('\n', '')
|
||||||
|
.replace(/<svg[^>]*>|<\/svg>/g, '')
|
||||||
|
: '';
|
||||||
|
|
||||||
|
const svg = Buffer.from(
|
||||||
|
// We can't use jsx here, is not supported here by nitro.
|
||||||
|
renderToString(createElement(Diff, { oldSrc, newSrc, showGrid: true }, children)),
|
||||||
|
).toString('utf8');
|
||||||
|
|
||||||
|
defaultContentType(event, 'image/svg+xml');
|
||||||
|
setResponseHeader(event, 'Cache-Control', 'public,max-age=31536000');
|
||||||
|
|
||||||
|
return svg;
|
||||||
|
});
|
||||||
@@ -1,4 +1,3 @@
|
|||||||
import { eventHandler, setResponseHeader } from 'h3';
|
|
||||||
import iconMetaData from '../../data/iconMetaData';
|
import iconMetaData from '../../data/iconMetaData';
|
||||||
|
|
||||||
export default eventHandler((event) => {
|
export default eventHandler((event) => {
|
||||||
|
|||||||
@@ -28,6 +28,10 @@ export default defineConfig({
|
|||||||
new URL('./theme/components/overrides/VPFooter.vue', import.meta.url),
|
new URL('./theme/components/overrides/VPFooter.vue', import.meta.url),
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
find: '~/.vitepress',
|
||||||
|
replacement: fileURLToPath(new URL('./', import.meta.url)),
|
||||||
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
174
docs/.vitepress/data/categoriesData.json
Normal file
174
docs/.vitepress/data/categoriesData.json
Normal file
@@ -0,0 +1,174 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"name": "accessibility",
|
||||||
|
"title": "Accessibility"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "account",
|
||||||
|
"title": "Accounts & access"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "animals",
|
||||||
|
"title": "Animals"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "arrows",
|
||||||
|
"title": "Arrows"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "brands",
|
||||||
|
"title": "Brands"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "buildings",
|
||||||
|
"title": "Buildings"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "charts",
|
||||||
|
"title": "Charts"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "communication",
|
||||||
|
"title": "Communication"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "connectivity",
|
||||||
|
"title": "Connectivity"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "cursors",
|
||||||
|
"title": "Cursors"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "design",
|
||||||
|
"title": "Design"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "development",
|
||||||
|
"title": "Coding & development"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "devices",
|
||||||
|
"title": "Devices"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "emoji",
|
||||||
|
"title": "Emoji"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "files",
|
||||||
|
"title": "File icons"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "finance",
|
||||||
|
"title": "Finance"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "food-beverage",
|
||||||
|
"title": "Food & beverage"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "gaming",
|
||||||
|
"title": "Gaming"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "home",
|
||||||
|
"title": "Home"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "layout",
|
||||||
|
"title": "Layout"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "mail",
|
||||||
|
"title": "Mail"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "math",
|
||||||
|
"title": "Mathematics"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "medical",
|
||||||
|
"title": "Medical"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "multimedia",
|
||||||
|
"title": "Multimedia"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "nature",
|
||||||
|
"title": "Nature"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "navigation",
|
||||||
|
"title": "Navigation"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "notifications",
|
||||||
|
"title": "Notification"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "people",
|
||||||
|
"title": "People"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "photography",
|
||||||
|
"title": "Photography"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "science",
|
||||||
|
"title": "Science"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "seasons",
|
||||||
|
"title": "Seasons"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "security",
|
||||||
|
"title": "Security"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "shapes",
|
||||||
|
"title": "Shapes"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "shopping",
|
||||||
|
"title": "Shopping"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "social",
|
||||||
|
"title": "Social"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "sports",
|
||||||
|
"title": "Sports"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "sustainability",
|
||||||
|
"title": "Sustainability"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "text",
|
||||||
|
"title": "Text formatting"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "time",
|
||||||
|
"title": "Time & calendar"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "tools",
|
||||||
|
"title": "Tools"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "transportation",
|
||||||
|
"title": "Transportation"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "travel",
|
||||||
|
"title": "Travel"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "weather",
|
||||||
|
"title": "Weather"
|
||||||
|
}
|
||||||
|
]
|
||||||
@@ -14,5 +14,13 @@
|
|||||||
"light": "/library-logos/tamagui.svg",
|
"light": "/library-logos/tamagui.svg",
|
||||||
"dark": "/library-logos/tamagui.svg"
|
"dark": "/library-logos/tamagui.svg"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Reflex",
|
||||||
|
"url": "https://reflex.dev",
|
||||||
|
"image": {
|
||||||
|
"light": "/library-logos/reflex-light.svg",
|
||||||
|
"dark": "/library-logos/reflex-dark.svg"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -31,24 +31,8 @@
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"lucide-vue": {
|
|
||||||
"order": 2,
|
|
||||||
"icon": "vue",
|
|
||||||
"shields": [
|
|
||||||
{
|
|
||||||
"alt": "npm",
|
|
||||||
"src": "https://img.shields.io/npm/v/lucide-vue",
|
|
||||||
"href": "https://www.npmjs.com/package/lucide-vue"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"alt": "npm",
|
|
||||||
"src": "https://img.shields.io/npm/dw/lucide-vue",
|
|
||||||
"href": "https://www.npmjs.com/package/lucide-vue"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"lucide-vue-next": {
|
"lucide-vue-next": {
|
||||||
"order": 3,
|
"order": 2,
|
||||||
"icon": "vue-next",
|
"icon": "vue-next",
|
||||||
"shields": [
|
"shields": [
|
||||||
{
|
{
|
||||||
@@ -64,7 +48,7 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"lucide-svelte": {
|
"lucide-svelte": {
|
||||||
"order": 4,
|
"order": 3,
|
||||||
"icon": "svelte",
|
"icon": "svelte",
|
||||||
"shields": [
|
"shields": [
|
||||||
{
|
{
|
||||||
@@ -95,24 +79,8 @@
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"lucide-preact": {
|
|
||||||
"order": 5,
|
|
||||||
"icon": "preact",
|
|
||||||
"shields": [
|
|
||||||
{
|
|
||||||
"alt": "npm",
|
|
||||||
"src": "https://img.shields.io/npm/v/lucide-preact",
|
|
||||||
"href": "https://www.npmjs.com/package/lucide-preact"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"alt": "npm",
|
|
||||||
"src": "https://img.shields.io/npm/dw/lucide-preact",
|
|
||||||
"href": "https://www.npmjs.com/package/lucide-preact"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"lucide-react-native": {
|
"lucide-react-native": {
|
||||||
"order": 6,
|
"order": 5,
|
||||||
"icon": "react-native",
|
"icon": "react-native",
|
||||||
"shields": [
|
"shields": [
|
||||||
{
|
{
|
||||||
@@ -128,7 +96,7 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"lucide-angular": {
|
"lucide-angular": {
|
||||||
"order": 7,
|
"order": 6,
|
||||||
"icon": "angular",
|
"icon": "angular",
|
||||||
"shields": [
|
"shields": [
|
||||||
{
|
{
|
||||||
@@ -143,8 +111,43 @@
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"lucide-static": {
|
"lucide-preact": {
|
||||||
|
"order": 7,
|
||||||
|
"icon": "preact",
|
||||||
|
"shields": [
|
||||||
|
{
|
||||||
|
"alt": "npm",
|
||||||
|
"src": "https://img.shields.io/npm/v/lucide-preact",
|
||||||
|
"href": "https://www.npmjs.com/package/lucide-preact"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"alt": "npm",
|
||||||
|
"src": "https://img.shields.io/npm/dw/lucide-preact",
|
||||||
|
"href": "https://www.npmjs.com/package/lucide-preact"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"@lucide/astro": {
|
||||||
|
"docsAlias": "lucide-astro",
|
||||||
|
"packageDirname": "astro",
|
||||||
"order": 8,
|
"order": 8,
|
||||||
|
"icon": "astro",
|
||||||
|
"iconDark": "astro-dark",
|
||||||
|
"shields": [
|
||||||
|
{
|
||||||
|
"alt": "npm",
|
||||||
|
"src": "https://img.shields.io/npm/v/@lucide/astro",
|
||||||
|
"href": "https://www.npmjs.com/package/@lucide/astro"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"alt": "npm",
|
||||||
|
"src": "https://img.shields.io/npm/dw/@lucide/astro",
|
||||||
|
"href": "https://www.npmjs.com/package/@lucide/astro"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"lucide-static": {
|
||||||
|
"order": 9,
|
||||||
"icon": "svg",
|
"icon": "svg",
|
||||||
"shields": [
|
"shields": [
|
||||||
{
|
{
|
||||||
@@ -158,16 +161,5 @@
|
|||||||
"href": "https://www.npmjs.com/package/lucide-static"
|
"href": "https://www.npmjs.com/package/lucide-static"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
|
||||||
"lucide-flutter": {
|
|
||||||
"order": 9,
|
|
||||||
"icon": "flutter",
|
|
||||||
"shields": [
|
|
||||||
{
|
|
||||||
"alt": "flutter",
|
|
||||||
"src": "https://img.shields.io/pub/v/lucide_icons",
|
|
||||||
"href": "https://img.shields.io/pub/v/lucide_icons"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -76,5 +76,24 @@
|
|||||||
],
|
],
|
||||||
"source": "https://github.com/swisnl/nuxt-lucide-icons",
|
"source": "https://github.com/swisnl/nuxt-lucide-icons",
|
||||||
"documentation": "https://github.com/swisnl/nuxt-lucide-icons/blob/main/README.md"
|
"documentation": "https://github.com/swisnl/nuxt-lucide-icons/blob/main/README.md"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "lucide-lustre",
|
||||||
|
"description": "A library providing https://lucide.dev icons to lustre.",
|
||||||
|
"icon": "/framework-logos/lustre.webp",
|
||||||
|
"shields": [
|
||||||
|
{
|
||||||
|
"alt": "Latest Stable Version",
|
||||||
|
"src": "https://img.shields.io/hexpm/v/lucide_lustre",
|
||||||
|
"href": "https://hex.pm/packages/lucide_lustre"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"alt": "Total Downloads",
|
||||||
|
"src": "https://img.shields.io/hexpm/dw/lucide_lustre",
|
||||||
|
"href": "https://hex.pm/packages/lucide_lustre"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"source": "https://github.com/dinkelspiel/lucide_lustre",
|
||||||
|
"documentation": "https://github.com/dinkelspiel/lucide_lustre/blob/master/README.md"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|||||||
48
docs/.vitepress/data/teamData.json
Normal file
48
docs/.vitepress/data/teamData.json
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"name": "Eric Fennis",
|
||||||
|
"title": "Creator of Lucide & Software engineer @nedap",
|
||||||
|
"image": "https://github.com/ericfennis.png?size=192",
|
||||||
|
"sponsor": "https://github.com/sponsors/ericfennis",
|
||||||
|
"socialLinks": [
|
||||||
|
{
|
||||||
|
"icon": "github",
|
||||||
|
"link": "https://github.com/ericfennis"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon": "x",
|
||||||
|
"link": "https://x.com/ericfennis"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Karsa Rigó",
|
||||||
|
"title": "Maintainer of Lucide & Software engineer @sztaki",
|
||||||
|
"image": "https://github.com/karsa-mistmere.png?size=192",
|
||||||
|
"socialLinks": [
|
||||||
|
{
|
||||||
|
"icon": "github",
|
||||||
|
"link": "https://github.com/karsa-mistmere"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon": "linkedin",
|
||||||
|
"link": "https://www.linkedin.com/in/karsamistmere"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Jakob Guddas",
|
||||||
|
"title": "Maintainer of Lucide & Software engineer @LEGO",
|
||||||
|
"image": "https://github.com/jguddas.png?size=192",
|
||||||
|
"socialLinks": [
|
||||||
|
{
|
||||||
|
"icon": "github",
|
||||||
|
"link": "https://github.com/jguddas"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon": "linkedin",
|
||||||
|
"link": "https://www.linkedin.com/in/jguddas"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
@@ -3,15 +3,22 @@ import React from 'react';
|
|||||||
interface BackdropProps {
|
interface BackdropProps {
|
||||||
src: string;
|
src: string;
|
||||||
color?: string;
|
color?: string;
|
||||||
|
outline?: boolean;
|
||||||
backdropString: string;
|
backdropString: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Backdrop = ({ src, color = 'red', backdropString }: BackdropProps): JSX.Element => {
|
const Backdrop = ({
|
||||||
|
src,
|
||||||
|
color = 'red',
|
||||||
|
outline = true,
|
||||||
|
backdropString,
|
||||||
|
}: BackdropProps): JSX.Element => {
|
||||||
|
const id = React.useId();
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<defs xmlns="http://www.w3.org/2000/svg">
|
<defs xmlns="http://www.w3.org/2000/svg">
|
||||||
<pattern
|
<pattern
|
||||||
id="pattern"
|
id={`pattern-${id}`}
|
||||||
width=".1"
|
width=".1"
|
||||||
height=".1"
|
height=".1"
|
||||||
patternUnits="userSpaceOnUse"
|
patternUnits="userSpaceOnUse"
|
||||||
@@ -30,69 +37,58 @@ const Backdrop = ({ src, color = 'red', backdropString }: BackdropProps): JSX.El
|
|||||||
</pattern>
|
</pattern>
|
||||||
</defs>
|
</defs>
|
||||||
<mask
|
<mask
|
||||||
id="svg-preview-backdrop-mask-outline"
|
id={`svg-preview-backdrop-mask-${id}`}
|
||||||
maskUnits="userSpaceOnUse"
|
maskUnits="userSpaceOnUse"
|
||||||
>
|
>
|
||||||
<g
|
<g
|
||||||
stroke="#fff"
|
stroke="#fff"
|
||||||
dangerouslySetInnerHTML={{ __html: backdropString }}
|
dangerouslySetInnerHTML={{ __html: backdropString }}
|
||||||
/>
|
/>
|
||||||
<g
|
<g dangerouslySetInnerHTML={{ __html: src }} />
|
||||||
dangerouslySetInnerHTML={{ __html: src }}
|
|
||||||
strokeWidth={2.05}
|
|
||||||
/>
|
|
||||||
</mask>
|
</mask>
|
||||||
<mask
|
<mask
|
||||||
id="svg-preview-backdrop-mask-fill"
|
id={`svg-preview-backdrop-mask-outline-${id}`}
|
||||||
maskUnits="userSpaceOnUse"
|
maskUnits="userSpaceOnUse"
|
||||||
>
|
>
|
||||||
<g
|
<rect
|
||||||
stroke="#fff"
|
x="0"
|
||||||
dangerouslySetInnerHTML={{ __html: backdropString }}
|
y="0"
|
||||||
/>
|
width="24"
|
||||||
<g
|
height="24"
|
||||||
dangerouslySetInnerHTML={{ __html: src }}
|
fill="#fff"
|
||||||
strokeWidth={2.05}
|
stroke="none"
|
||||||
/>
|
/>
|
||||||
<g
|
<g
|
||||||
strokeWidth={1.75}
|
strokeWidth={1.75}
|
||||||
dangerouslySetInnerHTML={{ __html: backdropString }}
|
dangerouslySetInnerHTML={{ __html: backdropString }}
|
||||||
/>
|
/>
|
||||||
</mask>
|
</mask>
|
||||||
|
<g mask={`url(#svg-preview-backdrop-mask-${id})`}>
|
||||||
|
<rect
|
||||||
|
x="0"
|
||||||
|
y="0"
|
||||||
|
width="24"
|
||||||
|
height="24"
|
||||||
|
opacity={0.5}
|
||||||
|
fill={`url(#pattern-${id})`}
|
||||||
|
stroke="none"
|
||||||
|
/>
|
||||||
<g
|
<g
|
||||||
|
stroke={color}
|
||||||
strokeWidth={2.25}
|
strokeWidth={2.25}
|
||||||
stroke="url(#pattern)"
|
opacity={0.75}
|
||||||
mask={'url(#svg-preview-backdrop-mask-outline)'}
|
dangerouslySetInnerHTML={{ __html: src }}
|
||||||
>
|
|
||||||
<rect
|
|
||||||
x="0"
|
|
||||||
y="0"
|
|
||||||
width="24"
|
|
||||||
height="24"
|
|
||||||
fill="url(#pattern)"
|
|
||||||
opacity={0.5}
|
|
||||||
stroke="none"
|
|
||||||
/>
|
/>
|
||||||
|
{outline && (
|
||||||
|
<g
|
||||||
|
stroke={color}
|
||||||
|
strokeWidth={2.25}
|
||||||
|
opacity={0.75}
|
||||||
|
mask={`url(#svg-preview-backdrop-mask-outline-${id})`}
|
||||||
|
dangerouslySetInnerHTML={{ __html: backdropString }}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
</g>
|
</g>
|
||||||
<rect
|
|
||||||
x="0"
|
|
||||||
y="0"
|
|
||||||
width="24"
|
|
||||||
height="24"
|
|
||||||
fill="url(#pattern)"
|
|
||||||
stroke="none"
|
|
||||||
mask={'url(#svg-preview-backdrop-mask-fill)'}
|
|
||||||
/>
|
|
||||||
<rect
|
|
||||||
x="0"
|
|
||||||
y="0"
|
|
||||||
width="24"
|
|
||||||
height="24"
|
|
||||||
fill={color}
|
|
||||||
opacity={0.5}
|
|
||||||
stroke="none"
|
|
||||||
mask={'url(#svg-preview-backdrop-mask-fill)'}
|
|
||||||
/>
|
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
71
docs/.vitepress/lib/SvgPreview/Diff.tsx
Normal file
71
docs/.vitepress/lib/SvgPreview/Diff.tsx
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import Backdrop from './Backdrop.tsx';
|
||||||
|
import { darkModeCss, Grid } from './index.tsx';
|
||||||
|
|
||||||
|
const SvgPreview = React.forwardRef<
|
||||||
|
SVGSVGElement,
|
||||||
|
{
|
||||||
|
oldSrc: string;
|
||||||
|
newSrc: string;
|
||||||
|
} & React.SVGProps<SVGSVGElement>
|
||||||
|
>(({ oldSrc, newSrc, children, ...props }, ref) => {
|
||||||
|
return (
|
||||||
|
<svg
|
||||||
|
ref={ref}
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width={24}
|
||||||
|
height={24}
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
fill="none"
|
||||||
|
stroke="currentColor"
|
||||||
|
strokeWidth={2}
|
||||||
|
strokeLinecap="round"
|
||||||
|
strokeLinejoin="round"
|
||||||
|
{...props}
|
||||||
|
>
|
||||||
|
<style>{darkModeCss}</style>
|
||||||
|
<Grid
|
||||||
|
strokeWidth={0.1}
|
||||||
|
stroke="#777"
|
||||||
|
strokeOpacity={0.3}
|
||||||
|
radius={1}
|
||||||
|
/>
|
||||||
|
<mask
|
||||||
|
id="gray"
|
||||||
|
maskUnits="userSpaceOnUse"
|
||||||
|
>
|
||||||
|
<rect
|
||||||
|
x="0"
|
||||||
|
y="0"
|
||||||
|
width="24"
|
||||||
|
height="24"
|
||||||
|
fill="#000"
|
||||||
|
stroke="none"
|
||||||
|
/>
|
||||||
|
<g
|
||||||
|
stroke="#fff"
|
||||||
|
dangerouslySetInnerHTML={{ __html: oldSrc }}
|
||||||
|
/>
|
||||||
|
</mask>
|
||||||
|
<Backdrop
|
||||||
|
src=""
|
||||||
|
outline={false}
|
||||||
|
backdropString={`<g mask="url('#gray')">${newSrc}</g>`}
|
||||||
|
color="#777"
|
||||||
|
/>
|
||||||
|
<Backdrop
|
||||||
|
src={oldSrc}
|
||||||
|
backdropString={newSrc}
|
||||||
|
color="lime"
|
||||||
|
/>
|
||||||
|
<Backdrop
|
||||||
|
src={newSrc}
|
||||||
|
backdropString={oldSrc}
|
||||||
|
color="red"
|
||||||
|
/>
|
||||||
|
{children}
|
||||||
|
</svg>
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
export default SvgPreview;
|
||||||
@@ -2,7 +2,23 @@ import React from 'react';
|
|||||||
import { PathProps, Path } from './types';
|
import { PathProps, Path } from './types';
|
||||||
import { getPaths, assert } from './utils';
|
import { getPaths, assert } from './utils';
|
||||||
|
|
||||||
const Grid = ({
|
export const darkModeCss = `
|
||||||
|
@media screen and (prefers-color-scheme: light) {
|
||||||
|
.svg-preview-grid-rect { fill: none }
|
||||||
|
}
|
||||||
|
@media screen and (prefers-color-scheme: dark) {
|
||||||
|
.svg-preview-grid-rect { fill: none }
|
||||||
|
.svg
|
||||||
|
.svg-preview-grid-group,
|
||||||
|
.svg-preview-radii-group,
|
||||||
|
.svg-preview-shadow-mask-group,
|
||||||
|
.svg-preview-shadow-group {
|
||||||
|
stroke: #fff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const Grid = ({
|
||||||
radius,
|
radius,
|
||||||
fill = '#fff',
|
fill = '#fff',
|
||||||
...props
|
...props
|
||||||
@@ -25,11 +41,29 @@ const Grid = ({
|
|||||||
fill={fill}
|
fill={fill}
|
||||||
/>
|
/>
|
||||||
<path
|
<path
|
||||||
|
strokeDasharray={'0 0.1 ' + '0.1 0.15 '.repeat(11) + '0 0.15'}
|
||||||
|
strokeWidth={0.1}
|
||||||
d={
|
d={
|
||||||
props.d ||
|
props.d ||
|
||||||
new Array(Math.floor(24 - 1))
|
new Array(Math.floor(24 - 1))
|
||||||
.fill(null)
|
.fill(null)
|
||||||
.flatMap((_, i) => [
|
.map((_, i) => i)
|
||||||
|
.filter((i) => i % 3 !== 2)
|
||||||
|
.flatMap((i) => [
|
||||||
|
`M${props.strokeWidth} ${i + 1}h${24 - props.strokeWidth * 2}`,
|
||||||
|
`M${i + 1} ${props.strokeWidth}v${24 - props.strokeWidth * 2}`,
|
||||||
|
])
|
||||||
|
.join('')
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
d={
|
||||||
|
props.d ||
|
||||||
|
new Array(Math.floor(24 - 1))
|
||||||
|
.fill(null)
|
||||||
|
.map((_, i) => i)
|
||||||
|
.filter((i) => i % 3 === 2)
|
||||||
|
.flatMap((i) => [
|
||||||
`M${props.strokeWidth} ${i + 1}h${24 - props.strokeWidth * 2}`,
|
`M${props.strokeWidth} ${i + 1}h${24 - props.strokeWidth * 2}`,
|
||||||
`M${i + 1} ${props.strokeWidth}v${24 - props.strokeWidth * 2}`,
|
`M${i + 1} ${props.strokeWidth}v${24 - props.strokeWidth * 2}`,
|
||||||
])
|
])
|
||||||
@@ -283,7 +317,6 @@ const Handles = ({
|
|||||||
'strokeWidth' | 'stroke' | 'strokeDasharray' | 'strokeOpacity',
|
'strokeWidth' | 'stroke' | 'strokeDasharray' | 'strokeOpacity',
|
||||||
any
|
any
|
||||||
>) => {
|
>) => {
|
||||||
console.log(paths);
|
|
||||||
return (
|
return (
|
||||||
<g
|
<g
|
||||||
className="svg-preview-handles-group"
|
className="svg-preview-handles-group"
|
||||||
@@ -322,19 +355,6 @@ const SvgPreview = React.forwardRef<
|
|||||||
>(({ src, children, showGrid = false, ...props }, ref) => {
|
>(({ src, children, showGrid = false, ...props }, ref) => {
|
||||||
const paths = typeof src === 'string' ? getPaths(src) : src;
|
const paths = typeof src === 'string' ? getPaths(src) : src;
|
||||||
|
|
||||||
const darkModeCss = `@media screen and (prefers-color-scheme: light) {
|
|
||||||
.svg-preview-grid-rect { fill: none }
|
|
||||||
}
|
|
||||||
@media screen and (prefers-color-scheme: dark) {
|
|
||||||
.svg-preview-grid-rect { fill: none }
|
|
||||||
.svg
|
|
||||||
.svg-preview-grid-group,
|
|
||||||
.svg-preview-radii-group,
|
|
||||||
.svg-preview-shadow-mask-group,
|
|
||||||
.svg-preview-shadow-group {
|
|
||||||
stroke: #fff;
|
|
||||||
}
|
|
||||||
}`;
|
|
||||||
return (
|
return (
|
||||||
<svg
|
<svg
|
||||||
ref={ref}
|
ref={ref}
|
||||||
|
|||||||
@@ -10,18 +10,24 @@ type CodeExampleType = {
|
|||||||
const getIconCodes = (): CodeExampleType => {
|
const getIconCodes = (): CodeExampleType => {
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
language: 'html',
|
language: 'js',
|
||||||
title: 'HTML',
|
title: 'Vanilla',
|
||||||
code: `<i data-lucide="Name"></i>`,
|
code: `\
|
||||||
|
import { createIcons, icons } from 'lucide';
|
||||||
|
|
||||||
|
createIcons({ icons });
|
||||||
|
|
||||||
|
document.body.append('<i data-lucide="$Name"></i>');\
|
||||||
|
`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
language: 'tsx',
|
language: 'tsx',
|
||||||
title: 'React',
|
title: 'React',
|
||||||
code: `import { PascalCase } from 'lucide-react';
|
code: `import { $PascalCase } from 'lucide-react';
|
||||||
|
|
||||||
const App = () => {
|
const App = () => {
|
||||||
return (
|
return (
|
||||||
<PascalCase />
|
<$PascalCase />
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -32,11 +38,11 @@ export default App;
|
|||||||
language: 'vue',
|
language: 'vue',
|
||||||
title: 'Vue',
|
title: 'Vue',
|
||||||
code: `<script setup>
|
code: `<script setup>
|
||||||
import { PascalCase } from 'lucide-vue-next';
|
import { $PascalCase } from 'lucide-vue-next';
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<PascalCase />
|
<$PascalCase />
|
||||||
</template>
|
</template>
|
||||||
`,
|
`,
|
||||||
},
|
},
|
||||||
@@ -44,20 +50,20 @@ export default App;
|
|||||||
language: 'svelte',
|
language: 'svelte',
|
||||||
title: 'Svelte',
|
title: 'Svelte',
|
||||||
code: `<script>
|
code: `<script>
|
||||||
import { PascalCase } from 'lucide-svelte';
|
import { $PascalCase } from 'lucide-svelte';
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<PascalCase />
|
<$PascalCase />
|
||||||
`,
|
`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
language: 'tsx',
|
language: 'tsx',
|
||||||
title: 'Preact',
|
title: 'Preact',
|
||||||
code: `import { PascalCase } from 'lucide-preact';
|
code: `import { $PascalCase } from 'lucide-preact';
|
||||||
|
|
||||||
const App = () => {
|
const App = () => {
|
||||||
return (
|
return (
|
||||||
<PascalCase />
|
<$PascalCase />
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -67,11 +73,11 @@ export default App;
|
|||||||
{
|
{
|
||||||
language: 'tsx',
|
language: 'tsx',
|
||||||
title: 'Solid',
|
title: 'Solid',
|
||||||
code: `import { PascalCase } from 'lucide-solid';
|
code: `import { $PascalCase } from 'lucide-solid';
|
||||||
|
|
||||||
const App = () => {
|
const App = () => {
|
||||||
return (
|
return (
|
||||||
<PascalCase />
|
<$PascalCase />
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -82,16 +88,16 @@ export default App;
|
|||||||
language: 'tsx',
|
language: 'tsx',
|
||||||
title: 'Angular',
|
title: 'Angular',
|
||||||
code: `// app.module.ts
|
code: `// app.module.ts
|
||||||
import { LucideAngularModule, PascalCase } from 'lucide-angular';
|
import { LucideAngularModule, $PascalCase } from 'lucide-angular';
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
imports: [
|
imports: [
|
||||||
LucideAngularModule.pick({ PascalCase })
|
LucideAngularModule.pick({ $PascalCase })
|
||||||
],
|
],
|
||||||
})
|
})
|
||||||
|
|
||||||
// app.component.html
|
// app.component.html
|
||||||
<lucide-icon name="Name"></lucide-icon>
|
<lucide-icon name="$Name"></lucide-icon>
|
||||||
`,
|
`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -101,7 +107,7 @@ import { LucideAngularModule, PascalCase } from 'lucide-angular';
|
|||||||
@import ('~lucide-static/font/Lucide.css');
|
@import ('~lucide-static/font/Lucide.css');
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<div class="icon-Name"></div>
|
<div class="icon-$Name"></div>
|
||||||
`,
|
`,
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
161
docs/.vitepress/lib/codeExamples/createLabCodeExamples.ts
Normal file
161
docs/.vitepress/lib/codeExamples/createLabCodeExamples.ts
Normal file
@@ -0,0 +1,161 @@
|
|||||||
|
import { bundledLanguages, type ThemeRegistration } from 'shikiji';
|
||||||
|
import { getHighlighter } from 'shikiji';
|
||||||
|
|
||||||
|
type CodeExampleType = {
|
||||||
|
title: string;
|
||||||
|
language: string;
|
||||||
|
code: string;
|
||||||
|
}[];
|
||||||
|
|
||||||
|
const getIconCodes = (): CodeExampleType => {
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
language: 'js',
|
||||||
|
title: 'Vanilla',
|
||||||
|
code: `\
|
||||||
|
import { createIcons, icons } from 'lucide';
|
||||||
|
import { $CamelCase } from '@lucide/lab';
|
||||||
|
|
||||||
|
createIcons({
|
||||||
|
icons: {
|
||||||
|
$CamelCase
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
document.body.append('<i data-lucide="$Name"></i>');\
|
||||||
|
`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
language: 'tsx',
|
||||||
|
title: 'React',
|
||||||
|
code: `import { Icon } from 'lucide-react';
|
||||||
|
import { $CamelCase } from '@lucide/lab';
|
||||||
|
|
||||||
|
const App = () => {
|
||||||
|
return (
|
||||||
|
<Icon iconNode={$CamelCase} />
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default App;
|
||||||
|
`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
language: 'vue',
|
||||||
|
title: 'Vue',
|
||||||
|
code: `<script setup>
|
||||||
|
import { Icon } from 'lucide-vue-next';
|
||||||
|
import { $CamelCase } from '@lucide/lab';
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<Icon :iconNode="$CamelCase" />
|
||||||
|
</template>
|
||||||
|
`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
language: 'svelte',
|
||||||
|
title: 'Svelte',
|
||||||
|
code: `<script>
|
||||||
|
import { Icon } from 'lucide-svelte';
|
||||||
|
import { $CamelCase } from '@lucide/lab';
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<Icon iconNode={$CamelCase} />
|
||||||
|
`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
language: 'tsx',
|
||||||
|
title: 'Preact',
|
||||||
|
code: `import { Icon } from 'lucide-preact';
|
||||||
|
import { $CamelCase } from '@lucide/lab';
|
||||||
|
|
||||||
|
const App = () => {
|
||||||
|
return (
|
||||||
|
<Icon iconNode={$CamelCase} />
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default App;
|
||||||
|
`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
language: 'tsx',
|
||||||
|
title: 'Solid',
|
||||||
|
code: `import { Icon } from 'lucide-solid';
|
||||||
|
import { $CamelCase } from '@lucide/lab';
|
||||||
|
|
||||||
|
const App = () => {
|
||||||
|
return (
|
||||||
|
<Icon iconNode={$CamelCase} />
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default App;
|
||||||
|
`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
language: 'tsx',
|
||||||
|
title: 'Angular',
|
||||||
|
code: `// app.module.ts
|
||||||
|
import { LucideAngularModule } from 'lucide-angular';
|
||||||
|
import { $CamelCase } from '@lucide/lab';
|
||||||
|
|
||||||
|
@NgModule({
|
||||||
|
imports: [
|
||||||
|
LucideAngularModule.pick({ $CamelCase })
|
||||||
|
],
|
||||||
|
})
|
||||||
|
|
||||||
|
// app.component.html
|
||||||
|
<lucide-icon name="$CamelCase"></lucide-icon>
|
||||||
|
`,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
|
export type ThemeOptions =
|
||||||
|
| ThemeRegistration
|
||||||
|
| { light: ThemeRegistration; dark: ThemeRegistration };
|
||||||
|
|
||||||
|
const highLightCode = async (code: string, lang: string, active?: boolean) => {
|
||||||
|
const highlighter = await getHighlighter({
|
||||||
|
themes: ['github-light', 'github-dark'],
|
||||||
|
langs: Object.keys(bundledLanguages),
|
||||||
|
});
|
||||||
|
|
||||||
|
const highlightedCode = highlighter
|
||||||
|
.codeToHtml(code, {
|
||||||
|
lang,
|
||||||
|
themes: {
|
||||||
|
light: 'github-light',
|
||||||
|
dark: 'github-dark',
|
||||||
|
},
|
||||||
|
defaultColor: false,
|
||||||
|
})
|
||||||
|
.replace('shiki-themes', 'shiki-themes vp-code');
|
||||||
|
|
||||||
|
return `<div class="language-${lang} ${active ? 'active' : ''}">
|
||||||
|
<button title="Copy Code" class="copy"></button>
|
||||||
|
<span class="lang">${lang}</span>
|
||||||
|
${highlightedCode}
|
||||||
|
</div>`;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default async function createCodeExamples() {
|
||||||
|
const codes = getIconCodes();
|
||||||
|
|
||||||
|
const codeExamplePromises = codes.map(async ({ title, language, code }, index) => {
|
||||||
|
const isFirst = index === 0;
|
||||||
|
|
||||||
|
const codeString = await highLightCode(code, language, isFirst);
|
||||||
|
|
||||||
|
return {
|
||||||
|
title,
|
||||||
|
language: language,
|
||||||
|
code: codeString,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
return Promise.all(codeExamplePromises);
|
||||||
|
}
|
||||||
32
docs/.vitepress/lib/codeExamples/highLightCode.ts
Normal file
32
docs/.vitepress/lib/codeExamples/highLightCode.ts
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
import { bundledLanguages, type ThemeRegistration } from 'shikiji';
|
||||||
|
import { getHighlighter } from 'shikiji';
|
||||||
|
|
||||||
|
export type ThemeOptions =
|
||||||
|
| ThemeRegistration
|
||||||
|
| { light: ThemeRegistration; dark: ThemeRegistration };
|
||||||
|
|
||||||
|
const highLightCode = async (code: string, lang: string, active?: boolean) => {
|
||||||
|
const highlighter = await getHighlighter({
|
||||||
|
themes: ['github-light', 'github-dark'],
|
||||||
|
langs: Object.keys(bundledLanguages),
|
||||||
|
});
|
||||||
|
|
||||||
|
const highlightedCode = highlighter
|
||||||
|
.codeToHtml(code, {
|
||||||
|
lang,
|
||||||
|
themes: {
|
||||||
|
light: 'github-light',
|
||||||
|
dark: 'github-dark',
|
||||||
|
},
|
||||||
|
defaultColor: false,
|
||||||
|
})
|
||||||
|
.replace('shiki-themes', 'shiki-themes vp-code');
|
||||||
|
|
||||||
|
return `<div class="language-${lang} ${active ? 'active' : ''}">
|
||||||
|
<button title="Copy Code" class="copy"></button>
|
||||||
|
<span class="lang">${lang}</span>
|
||||||
|
${highlightedCode}
|
||||||
|
</div>`;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default highLightCode;
|
||||||
5
docs/.vitepress/lib/codeExamples/types.ts
Normal file
5
docs/.vitepress/lib/codeExamples/types.ts
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
export type CodeExampleType = {
|
||||||
|
title: string;
|
||||||
|
language: string;
|
||||||
|
code: string;
|
||||||
|
}[];
|
||||||
@@ -1,6 +1,5 @@
|
|||||||
import { promises as fs, constants } from 'fs';
|
import { promises as fs, constants } from 'fs';
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
import yaml from 'js-yaml';
|
|
||||||
import { PackageItem } from '../theme/types';
|
import { PackageItem } from '../theme/types';
|
||||||
|
|
||||||
const fileExist = (filePath) =>
|
const fileExist = (filePath) =>
|
||||||
@@ -27,11 +26,6 @@ const fetchPackages = async (): Promise<PackageItem[]> => {
|
|||||||
return JSON.parse(await fs.readFile(jsonFilePath, 'utf-8'));
|
return JSON.parse(await fs.readFile(jsonFilePath, 'utf-8'));
|
||||||
}
|
}
|
||||||
|
|
||||||
const ymlFilePath = path.resolve(filePath, 'pubspec.yaml');
|
|
||||||
if (await fileExist(ymlFilePath)) {
|
|
||||||
return yaml.load(await fs.readFile(ymlFilePath, 'utf-8'));
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -31,10 +31,10 @@ const sidebar: UserConfig<DefaultTheme.Config>['themeConfig']['sidebar'] = {
|
|||||||
{
|
{
|
||||||
text: 'Advanced',
|
text: 'Advanced',
|
||||||
items: [
|
items: [
|
||||||
// {
|
{
|
||||||
// text: 'Accessibility',
|
text: 'Accessibility',
|
||||||
// link: '/guide/advanced/accessibility'
|
link: '/guide/advanced/accessibility',
|
||||||
// },
|
},
|
||||||
{
|
{
|
||||||
text: 'Global styling',
|
text: 'Global styling',
|
||||||
link: '/guide/advanced/global-styling',
|
link: '/guide/advanced/global-styling',
|
||||||
@@ -46,6 +46,10 @@ const sidebar: UserConfig<DefaultTheme.Config>['themeConfig']['sidebar'] = {
|
|||||||
text: 'Filled icons',
|
text: 'Filled icons',
|
||||||
link: '/guide/advanced/filled-icons',
|
link: '/guide/advanced/filled-icons',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
text: 'Aliased Names',
|
||||||
|
link: '/guide/advanced/aliased-names',
|
||||||
|
},
|
||||||
// {
|
// {
|
||||||
// text: 'Combining icons',
|
// text: 'Combining icons',
|
||||||
// },
|
// },
|
||||||
@@ -68,10 +72,6 @@ const sidebar: UserConfig<DefaultTheme.Config>['themeConfig']['sidebar'] = {
|
|||||||
text: 'Lucide React',
|
text: 'Lucide React',
|
||||||
link: '/guide/packages/lucide-react',
|
link: '/guide/packages/lucide-react',
|
||||||
},
|
},
|
||||||
{
|
|
||||||
text: 'Lucide React Native',
|
|
||||||
link: '/guide/packages/lucide-react-native',
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
text: 'Lucide Vue',
|
text: 'Lucide Vue',
|
||||||
link: '/guide/packages/lucide-vue-next',
|
link: '/guide/packages/lucide-vue-next',
|
||||||
@@ -85,13 +85,21 @@ const sidebar: UserConfig<DefaultTheme.Config>['themeConfig']['sidebar'] = {
|
|||||||
link: '/guide/packages/lucide-solid',
|
link: '/guide/packages/lucide-solid',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
text: 'Lucide Preact',
|
text: 'Lucide React Native',
|
||||||
link: '/guide/packages/lucide-preact',
|
link: '/guide/packages/lucide-react-native',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
text: 'Lucide Angular',
|
text: 'Lucide Angular',
|
||||||
link: '/guide/packages/lucide-angular',
|
link: '/guide/packages/lucide-angular',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
text: 'Lucide Preact',
|
||||||
|
link: '/guide/packages/lucide-preact',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: 'Lucide Astro',
|
||||||
|
link: '/guide/packages/lucide-astro',
|
||||||
|
},
|
||||||
{
|
{
|
||||||
text: 'Lucide Static',
|
text: 'Lucide Static',
|
||||||
link: '/guide/packages/lucide-static',
|
link: '/guide/packages/lucide-static',
|
||||||
@@ -117,6 +125,10 @@ const sidebar: UserConfig<DefaultTheme.Config>['themeConfig']['sidebar'] = {
|
|||||||
text: 'Designing in Figma',
|
text: 'Designing in Figma',
|
||||||
link: '/guide/design/figma-guide',
|
link: '/guide/design/figma-guide',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
text: 'Designing in Affinity Designer',
|
||||||
|
link: '/guide/design/affinity-designer-guide',
|
||||||
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { computed } from 'vue';
|
import { computed } from 'vue';
|
||||||
|
|
||||||
import { useRouter } from 'vitepress';
|
import { useRouter } from 'vitepress';
|
||||||
|
|
||||||
const { go } = useRouter()
|
const { go } = useRouter()
|
||||||
@@ -8,7 +7,16 @@ const props = defineProps<{
|
|||||||
href?: string
|
href?: string
|
||||||
}>()
|
}>()
|
||||||
|
|
||||||
|
const isExternal = computed(() => props.href?.startsWith('http') ?? false)
|
||||||
|
|
||||||
const component = computed(() => props.href ? 'a' : 'div')
|
const component = computed(() => props.href ? 'a' : 'div')
|
||||||
|
const target = computed(() => isExternal.value ? '_blank' : undefined)
|
||||||
|
const rel = computed(() => isExternal.value ? 'noreferrer noopener' : undefined)
|
||||||
|
|
||||||
|
const onClick = computed(() => {
|
||||||
|
if(!props.href || isExternal) return
|
||||||
|
return go(props.href)
|
||||||
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
@@ -16,7 +24,9 @@ const component = computed(() => props.href ? 'a' : 'div')
|
|||||||
:is="component"
|
:is="component"
|
||||||
:href="href"
|
:href="href"
|
||||||
class="badge"
|
class="badge"
|
||||||
@click="props?.href ? go(href) : undefined"
|
:target="target"
|
||||||
|
:rel="rel"
|
||||||
|
@click="onClick"
|
||||||
>
|
>
|
||||||
<slot/>
|
<slot/>
|
||||||
</component>
|
</component>
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="grid">
|
<div class="card-grid-flex">
|
||||||
<slot />
|
<slot />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style scoped>
|
<style>
|
||||||
.grid {
|
.card-grid-flex {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
align-items: stretch;
|
align-items: stretch;
|
||||||
@@ -15,20 +15,20 @@
|
|||||||
margin: -8px;
|
margin: -8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.grid > * {
|
.card-grid-flex > * {
|
||||||
flex-basis: 100%;
|
flex-basis: 100%;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
padding: 8px;
|
padding: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (min-width: 960px) {
|
@media (min-width: 960px) {
|
||||||
.grid > * {
|
.card-grid-flex > * {
|
||||||
flex-basis: 50%;
|
flex-basis: 50%;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (min-width: 1280px) {
|
@media (min-width: 1280px) {
|
||||||
.grid > * {
|
.card-grid-flex > * {
|
||||||
flex-basis: 33.33%;
|
flex-basis: 33.33%;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
90
docs/.vitepress/theme/components/base/Checkbox.vue
Normal file
90
docs/.vitepress/theme/components/base/Checkbox.vue
Normal file
@@ -0,0 +1,90 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { computed } from 'vue';
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
label: string
|
||||||
|
id: string
|
||||||
|
value: string
|
||||||
|
modelValue: string | string[]
|
||||||
|
}>()
|
||||||
|
|
||||||
|
const emit = defineEmits(['change', 'input', 'update:modelValue'])
|
||||||
|
|
||||||
|
const model = computed({
|
||||||
|
get: () => {
|
||||||
|
if (Array.isArray(props.modelValue)) {
|
||||||
|
return props.modelValue.includes(props.value)
|
||||||
|
}
|
||||||
|
return props.modelValue === props.value
|
||||||
|
|
||||||
|
},
|
||||||
|
set: (value: string) => {
|
||||||
|
if (Array.isArray(props.modelValue)) {
|
||||||
|
const newValue = [...props.modelValue]
|
||||||
|
const index = newValue.indexOf(props.value)
|
||||||
|
if (value) {
|
||||||
|
if (index === -1) {
|
||||||
|
newValue.push(props.value)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (index !== -1) {
|
||||||
|
newValue.splice(index, 1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
emit('update:modelValue', newValue)
|
||||||
|
} else {
|
||||||
|
emit('update:modelValue', value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="checkbox-wrapper">
|
||||||
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
class="checkbox"
|
||||||
|
ref="input"
|
||||||
|
:id="id"
|
||||||
|
v-model="model"
|
||||||
|
v-bind="$attrs"
|
||||||
|
/>
|
||||||
|
<label :for="id" class="checkbox-label">
|
||||||
|
{{ label }}
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.checkbox-wrapper {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.checkbox-label {
|
||||||
|
line-height: 20px;
|
||||||
|
font-size: 13px;
|
||||||
|
color: var(--vt-c-text-1);
|
||||||
|
transition: color .5s;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.checkbox {
|
||||||
|
-webkit-appearance: none;
|
||||||
|
appearance: none;
|
||||||
|
width: 16px;
|
||||||
|
height: 16px;
|
||||||
|
cursor: pointer;
|
||||||
|
border: 1px solid var(--vp-input-border-color);
|
||||||
|
background-color: var(--vp-input-switch-bg-color);
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.checkbox:checked {
|
||||||
|
border-color: transparent;
|
||||||
|
background: url("data:image/svg+xml,%3Csvg width='12px' height='12px' viewBox='0 0 24 24' fill='none' stroke='white' stroke-width='4' stroke-linecap='round' stroke-linejoin='round' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M20 6 9 17l-5-5'/%3E%3C/svg%3E")
|
||||||
|
center no-repeat var(--vp-c-brand);;
|
||||||
|
}
|
||||||
|
|
||||||
|
</style>
|
||||||
@@ -24,40 +24,10 @@ const headingElement = computed(() => `h${props.headingLevel}`)
|
|||||||
font-size: 32px;
|
font-size: 32px;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
margin-bottom: 32px;
|
margin-bottom: 36px;
|
||||||
}
|
}
|
||||||
|
|
||||||
section {
|
section {
|
||||||
margin-bottom: 96px;
|
margin-bottom: 96px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.grid {
|
|
||||||
display: flex;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
align-items: stretch;
|
|
||||||
justify-content: center;
|
|
||||||
align-content: space-evenly;
|
|
||||||
box-sizing: border-box;
|
|
||||||
margin: -8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.grid > * {
|
|
||||||
flex-basis: 100%;
|
|
||||||
box-sizing: border-box;
|
|
||||||
padding: 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (min-width: 960px) {
|
|
||||||
.grid > * {
|
|
||||||
flex-basis: 50%;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (min-width: 1280px) {
|
|
||||||
.grid > * {
|
|
||||||
flex-basis: 33.33%;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -38,6 +38,7 @@ const value = computed({
|
|||||||
<Input
|
<Input
|
||||||
ref="input"
|
ref="input"
|
||||||
type="search"
|
type="search"
|
||||||
|
autofocus
|
||||||
v-bind="$attrs"
|
v-bind="$attrs"
|
||||||
v-model="value"
|
v-model="value"
|
||||||
class="input-wrapper"
|
class="input-wrapper"
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ onMounted(() => {
|
|||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
background: var(--vp-c-brand-dark);
|
background: var(--vp-c-brand-dark);
|
||||||
color: white;
|
color: white;
|
||||||
z-index: 10;
|
z-index: 99;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
padding: 2px 8px;
|
padding: 2px 8px;
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ export default {
|
|||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
})
|
})
|
||||||
.then((res) => res.tag_name);
|
.then((res) => res?.tag_name);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
version,
|
version,
|
||||||
|
|||||||
@@ -8,8 +8,6 @@ import { data } from './HomeHeroBefore.data'
|
|||||||
<HomeContainer class="container">
|
<HomeContainer class="container">
|
||||||
<Badge
|
<Badge
|
||||||
:href="`https://github.com/lucide-icons/lucide/releases/tag/${data.version}`"
|
:href="`https://github.com/lucide-icons/lucide/releases/tag/${data.version}`"
|
||||||
target="_blank"
|
|
||||||
rel="noreferrer noopener"
|
|
||||||
>v{{ data.version }}</Badge>
|
>v{{ data.version }}</Badge>
|
||||||
</HomeContainer>
|
</HomeContainer>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -28,8 +28,6 @@ function insert() {
|
|||||||
const replaceIndex = random(0, 48)
|
const replaceIndex = random(0, 48)
|
||||||
const newIcon = getRandomNewIcon()
|
const newIcon = getRandomNewIcon()
|
||||||
|
|
||||||
// items.value.splice(replaceIndex, 0, newIcon);
|
|
||||||
|
|
||||||
items.value[replaceIndex] = newIcon
|
items.value[replaceIndex] = newIcon
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -76,7 +74,6 @@ onBeforeUnmount(() => {
|
|||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.card-wrapper {
|
.card-wrapper {
|
||||||
/* padding: 0 24px; */
|
|
||||||
margin-left: auto;
|
margin-left: auto;
|
||||||
margin-bottom: auto;
|
margin-bottom: auto;
|
||||||
margin-top: 48px;
|
margin-top: 48px;
|
||||||
@@ -87,13 +84,10 @@ onBeforeUnmount(() => {
|
|||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height:100%;
|
height:100%;
|
||||||
/* box-shadow: var(--vp-shadow-2); */
|
|
||||||
max-height: 220px;
|
max-height: 220px;
|
||||||
max-width: 560px;
|
max-width: 560px;
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
position: relative;
|
position: relative;
|
||||||
/* max-height: 240px; */
|
|
||||||
/* margin-top: 96px; */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.card-grid {
|
.card-grid {
|
||||||
@@ -107,7 +101,6 @@ onBeforeUnmount(() => {
|
|||||||
max-width: 512px;
|
max-width: 512px;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
position: relative;
|
position: relative;
|
||||||
/* white-space: nowrap; */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.list-enter-active {
|
.list-enter-active {
|
||||||
|
|||||||
@@ -171,16 +171,14 @@ watch(absoluteStrokeWidth, (enabled) => {
|
|||||||
margin-top: 32px;
|
margin-top: 32px;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
background: none;
|
background: none;
|
||||||
max-width: 280px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (min-width: 640px) {
|
@media (min-width: 640px) {
|
||||||
|
|
||||||
.card {
|
.card {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: 8fr 10fr;
|
grid-template-columns: 8fr 10fr;
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
.card-column {
|
.card-column {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
} */
|
} */
|
||||||
|
|||||||
@@ -37,6 +37,12 @@ export default {
|
|||||||
logo: '/framework-logos/angular.svg',
|
logo: '/framework-logos/angular.svg',
|
||||||
label: 'Lucide documentation for Angular',
|
label: 'Lucide documentation for Angular',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: 'lucide-astro',
|
||||||
|
logo: '/framework-logos/astro.svg',
|
||||||
|
logoDark: '/framework-logos/astro-dark.svg',
|
||||||
|
label: 'Lucide documentation for Astro',
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: 'lucide-react-native',
|
name: 'lucide-react-native',
|
||||||
logo: '/framework-logos/react-native.svg',
|
logo: '/framework-logos/react-native.svg',
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import HomeContainer from './HomeContainer.vue'
|
import HomeContainer from './HomeContainer.vue'
|
||||||
|
import HomeSectionTitle from './HomeSectionTitle.vue'
|
||||||
import { useRouter } from 'vitepress';
|
import { useRouter } from 'vitepress';
|
||||||
import { data } from './HomePackagesSection.data'
|
import { data } from './HomePackagesSection.data'
|
||||||
import VPButton from 'vitepress/dist/client/theme-default/components/VPButton.vue';
|
import VPButton from 'vitepress/dist/client/theme-default/components/VPButton.vue';
|
||||||
@@ -9,10 +10,10 @@ const { go } = useRouter()
|
|||||||
|
|
||||||
<template>
|
<template>
|
||||||
<HomeContainer>
|
<HomeContainer>
|
||||||
<h2 class="section-title">Available For:</h2>
|
<HomeSectionTitle>Available For:</HomeSectionTitle>
|
||||||
<div class="packages-list">
|
<div class="packages-list">
|
||||||
<a
|
<a
|
||||||
v-for="{ name, logo } in data.packages"
|
v-for="{ name, logo, logoDark } in data.packages"
|
||||||
:href="`/guide/packages/${name}`"
|
:href="`/guide/packages/${name}`"
|
||||||
class="package-logo"
|
class="package-logo"
|
||||||
:aria-label="`Read more about: ${name} package`"
|
:aria-label="`Read more about: ${name} package`"
|
||||||
@@ -20,10 +21,17 @@ const { go } = useRouter()
|
|||||||
>
|
>
|
||||||
<img
|
<img
|
||||||
:src="logo"
|
:src="logo"
|
||||||
height="36"
|
:class="{ light: logoDark, 'image-logo': true }"
|
||||||
width="36"
|
|
||||||
loading="lazy"
|
|
||||||
:alt="`${name} logo`"
|
:alt="`${name} logo`"
|
||||||
|
loading="lazy"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<img
|
||||||
|
v-if="logoDark"
|
||||||
|
:src="logoDark"
|
||||||
|
:alt="`${name} logo`"
|
||||||
|
class="image-logo dark"
|
||||||
|
loading="lazy"
|
||||||
/>
|
/>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
@@ -34,14 +42,13 @@ const { go } = useRouter()
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.section-title {
|
|
||||||
color: var(--vp-c-text-2);
|
.image-logo {
|
||||||
font-weight: 500;
|
object-fit: contain;
|
||||||
line-height: 32px;
|
width: 36px;
|
||||||
font-size: 16px;
|
height: 36px;
|
||||||
text-align: center;
|
|
||||||
margin-bottom: 16px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.packages-list {
|
.packages-list {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
@@ -64,4 +71,11 @@ const { go } = useRouter()
|
|||||||
.package-logo:hover {
|
.package-logo:hover {
|
||||||
opacity: .6;
|
opacity: .6;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
html.dark .image-logo.light {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
html:not(.dark) .image-logo.dark {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
26
docs/.vitepress/theme/components/home/HomeSectionTitle.vue
Normal file
26
docs/.vitepress/theme/components/home/HomeSectionTitle.vue
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { computed } from 'vue';
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
headingLevel: 1 | 2 | 3 | 4 | 5 | 6,
|
||||||
|
}>()
|
||||||
|
|
||||||
|
const headingElement = computed(() => `h${props.headingLevel ?? 2}`)
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<component :is="headingElement" class="section-title">
|
||||||
|
<slot />
|
||||||
|
</component>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.section-title {
|
||||||
|
color: var(--vp-c-text-2);
|
||||||
|
font-weight: 500;
|
||||||
|
line-height: 32px;
|
||||||
|
font-size: 16px;
|
||||||
|
text-align: center;
|
||||||
|
margin-bottom: 16px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
59
docs/.vitepress/theme/components/home/HomeSponsorCard.vue
Normal file
59
docs/.vitepress/theme/components/home/HomeSponsorCard.vue
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import Card from '../base/Card.vue';
|
||||||
|
import HomeSectionTitle from './HomeSectionTitle.vue';
|
||||||
|
import VPButton from 'vitepress/dist/client/theme-default/components/VPButton.vue';
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<HomeSectionTitle :headingLevel="3"> Sponsor the Lucide maintainers </HomeSectionTitle>
|
||||||
|
<Card class="sponsor-card">
|
||||||
|
<img
|
||||||
|
src="/company-logos/open-collective-light.svg"
|
||||||
|
alt="Open Collective logo"
|
||||||
|
class="logo light"
|
||||||
|
width="242"
|
||||||
|
height="42"
|
||||||
|
/>
|
||||||
|
<img
|
||||||
|
src="/company-logos/open-collective-dark.svg"
|
||||||
|
alt="Open Collective logo"
|
||||||
|
class="logo dark"
|
||||||
|
width="242"
|
||||||
|
height="42"
|
||||||
|
/>
|
||||||
|
<VPButton
|
||||||
|
href="https://opencollective.com/lucide-icons"
|
||||||
|
class="sponsor-button"
|
||||||
|
text="Become a sponsor"
|
||||||
|
/>
|
||||||
|
</Card>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.sponsor-card {
|
||||||
|
margin: 0 auto;
|
||||||
|
max-width: 500px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
gap: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sponsor-button {
|
||||||
|
margin: auto 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
html.dark .logo.dark {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
html:not(.dark) .logo.light {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 640px) {
|
||||||
|
.sponsor-card {
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
91
docs/.vitepress/theme/components/home/HomeTeamSection.vue
Normal file
91
docs/.vitepress/theme/components/home/HomeTeamSection.vue
Normal file
@@ -0,0 +1,91 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { useData } from 'vitepress';
|
||||||
|
import HomeContainer from './HomeContainer.vue'
|
||||||
|
import GridSection from '../base/GridSection.vue'
|
||||||
|
import TeamMemberCard, { TeamMember } from './TeamMemberCard.vue'
|
||||||
|
import teamData from '../../../data/teamData.json'
|
||||||
|
import HomeSponsorCard from './HomeSponsorCard.vue';
|
||||||
|
import VPDocAsideCarbonAds from 'vitepress/dist/client/theme-default/components/VPDocAsideCarbonAds.vue'
|
||||||
|
|
||||||
|
|
||||||
|
const { theme } = useData()
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<HomeContainer>
|
||||||
|
<GridSection
|
||||||
|
title="Meet the team"
|
||||||
|
:headingLevel="2"
|
||||||
|
class="team-members"
|
||||||
|
>
|
||||||
|
<TeamMemberCard
|
||||||
|
v-for="teamMember in (teamData as TeamMember[])"
|
||||||
|
v-bind="teamMember"
|
||||||
|
/>
|
||||||
|
</GridSection>
|
||||||
|
<HomeSponsorCard />
|
||||||
|
<VPDocAsideCarbonAds
|
||||||
|
:carbon-ads="theme.carbonAds"
|
||||||
|
class="ad-card"
|
||||||
|
/>
|
||||||
|
</HomeContainer>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.team-members {
|
||||||
|
gap: 24px;
|
||||||
|
margin-top: 48px;
|
||||||
|
margin-bottom: 48px;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 640px) {
|
||||||
|
.team-members :deep(.card-grid > *) {
|
||||||
|
flex-basis: 50%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 768px) {
|
||||||
|
.team-members :deep(.card-grid > *) {
|
||||||
|
flex-basis: 33.33%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.ad-card {
|
||||||
|
margin: 32px auto 0;
|
||||||
|
width: 100%;;
|
||||||
|
max-width: 500px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: space-between;
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 960px) {
|
||||||
|
.ad-card {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.ad-card :deep(.VPCarbonAds) {
|
||||||
|
width: 100%;
|
||||||
|
text-align: left;
|
||||||
|
min-height: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ad-card :deep(.VPCarbonAds .carbon-wrap) {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: space-between;
|
||||||
|
gap: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ad-card :deep(.VPCarbonAds .carbon-text) {
|
||||||
|
padding-top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ad-card :deep(.VPCarbonAds .carbon-poweredby) {
|
||||||
|
text-align: right;
|
||||||
|
margin-top: -24px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
92
docs/.vitepress/theme/components/home/TeamMemberCard.vue
Normal file
92
docs/.vitepress/theme/components/home/TeamMemberCard.vue
Normal file
@@ -0,0 +1,92 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
export interface TeamMember {
|
||||||
|
name: string
|
||||||
|
title: string
|
||||||
|
image: string
|
||||||
|
sponsor?: string
|
||||||
|
socialLinks: DefaultTheme.SocialLink[]
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { DefaultTheme } from 'vitepress';
|
||||||
|
import Card from '../base/Card.vue'
|
||||||
|
import VPButton from 'vitepress/dist/client/theme-default/components/VPButton.vue'
|
||||||
|
import VPSocialLinks from 'vitepress/dist/client/theme-default/components/VPSocialLinks.vue'
|
||||||
|
|
||||||
|
defineProps<TeamMember>()
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<Card class="member-card">
|
||||||
|
<img :src="image" :alt="name" class="member-image"/>
|
||||||
|
<h3 class="member-name">
|
||||||
|
{{name}}
|
||||||
|
</h3>
|
||||||
|
<p class="member-title">
|
||||||
|
{{title}}
|
||||||
|
</p>
|
||||||
|
<div class="member-links">
|
||||||
|
<VPButton
|
||||||
|
v-if="sponsor"
|
||||||
|
:href="sponsor"
|
||||||
|
text="Sponsor"
|
||||||
|
theme="sponsor"
|
||||||
|
class="sponsor-button"
|
||||||
|
size="medium"
|
||||||
|
/>
|
||||||
|
<VPSocialLinks
|
||||||
|
:links="socialLinks"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</Card>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.member-card {
|
||||||
|
flex-basis: 100%;
|
||||||
|
height:100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.member-image {
|
||||||
|
width: 64px;
|
||||||
|
height: 64px;
|
||||||
|
border-radius: 32px;
|
||||||
|
margin: 0 auto;
|
||||||
|
background-color: var(--vp-c-bg);
|
||||||
|
}
|
||||||
|
|
||||||
|
.member-name {
|
||||||
|
text-align: center;
|
||||||
|
margin-top: 16px;
|
||||||
|
font-size: 21px;
|
||||||
|
font-weight: 500;
|
||||||
|
color: var(--textColor);
|
||||||
|
}
|
||||||
|
|
||||||
|
.member-title {
|
||||||
|
flex-grow: 1;
|
||||||
|
padding-top: 8px;
|
||||||
|
line-height: 24px;
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 500;
|
||||||
|
color: var(--vp-c-text-2);
|
||||||
|
text-align: center;
|
||||||
|
text-wrap: balance;
|
||||||
|
margin-bottom: 16px;;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sponsor-button {
|
||||||
|
width: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.member-links {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
93
docs/.vitepress/theme/components/icons/CarbonAdOverlay.vue
Normal file
93
docs/.vitepress/theme/components/icons/CarbonAdOverlay.vue
Normal file
@@ -0,0 +1,93 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { useData } from 'vitepress';
|
||||||
|
import { useSessionStorage } from '@vueuse/core';
|
||||||
|
import IconButton from '../base/IconButton.vue';
|
||||||
|
import VPDocAsideCarbonAds from 'vitepress/dist/client/theme-default/components/VPDocAsideCarbonAds.vue'
|
||||||
|
import { x } from '../../../data/iconNodes'
|
||||||
|
import createLucideIcon from 'lucide-vue-next/src/createLucideIcon';
|
||||||
|
import { onMounted, ref } from 'vue';
|
||||||
|
|
||||||
|
const { theme } = useData()
|
||||||
|
const showAd = useSessionStorage('show-carbon-ads', true)
|
||||||
|
const carbonLoaded = ref(true)
|
||||||
|
|
||||||
|
defineProps<{
|
||||||
|
drawerOpen: boolean
|
||||||
|
}>()
|
||||||
|
|
||||||
|
const CloseIcon = createLucideIcon('Close', x)
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
setTimeout(() => {
|
||||||
|
if (window?._carbonads == null) {
|
||||||
|
carbonLoaded.value = false
|
||||||
|
}
|
||||||
|
}, 5000)
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div
|
||||||
|
:class="{
|
||||||
|
'drawer-open': drawerOpen,
|
||||||
|
'hide-ad': !(showAd && carbonLoaded)
|
||||||
|
}"
|
||||||
|
class="floating-ad"
|
||||||
|
v-if="theme.carbonAds"
|
||||||
|
>
|
||||||
|
<IconButton @click="showAd = false" class="hide-button">
|
||||||
|
<component :is="CloseIcon" :size="20" absoluteStrokeWidth />
|
||||||
|
</IconButton>
|
||||||
|
<VPDocAsideCarbonAds
|
||||||
|
:carbon-ads="theme.carbonAds"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.floating-ad {
|
||||||
|
display: none;
|
||||||
|
position: fixed;
|
||||||
|
bottom: 32px;
|
||||||
|
width: 224px;
|
||||||
|
right: 32px;
|
||||||
|
transition: opacity 0.5s, transform 0.25s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.floating-ad.drawer-open {
|
||||||
|
transform: translateY(-288px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.floating-ad.hide-ad {
|
||||||
|
transform: translateX(224px);
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.floating-ad.drawer-open.hide-ad {
|
||||||
|
transform: translateY(-288px) translateX(224px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.floating-ad.drawer-open, .floating-ad.hide-ad {
|
||||||
|
transition: opacity 0.25s, transform 0.5s cubic-bezier(0.19, 1, 0.22, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 1280px) {
|
||||||
|
.floating-ad {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 1440px) {
|
||||||
|
.floating-ad {
|
||||||
|
right: calc(((100% - (var(--vp-layout-max-width) - var(--vp-sidebar-width))) - 272px) / 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.hide-button {
|
||||||
|
padding: 4px;
|
||||||
|
position: absolute;
|
||||||
|
top: 8px;
|
||||||
|
right: 8px;
|
||||||
|
background-color: transparent;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -1,13 +1,16 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref, computed } from 'vue'
|
import { ref, computed, watch } from 'vue'
|
||||||
import { useData } from 'vitepress'
|
import { useData } from 'vitepress'
|
||||||
import VPLink from 'vitepress/dist/client/theme-default/components/VPLink.vue'
|
import VPLink from 'vitepress/dist/client/theme-default/components/VPLink.vue'
|
||||||
import { isActive } from 'vitepress/dist/client/shared'
|
import { isActive } from 'vitepress/dist/client/shared'
|
||||||
import { useActiveAnchor } from '../../composables/useActiveAnchor'
|
import { useActiveAnchor } from '../../composables/useActiveAnchor'
|
||||||
import { data } from './CategoryList.data'
|
import { data } from './CategoryList.data'
|
||||||
import CategoryListItem from './CategoryListItem.vue'
|
import CategoryListItem from './CategoryListItem.vue'
|
||||||
|
import SidebarTitle from './SidebarTitle.vue'
|
||||||
|
import { useCategoryView } from '../../composables/useCategoryView'
|
||||||
|
|
||||||
const { page } = useData()
|
const { page } = useData()
|
||||||
|
const { categoryCounts } = useCategoryView();
|
||||||
|
|
||||||
const categoriesIsActive = computed(() => {
|
const categoriesIsActive = computed(() => {
|
||||||
return isActive(page.value.relativePath, '/icons/categories');
|
return isActive(page.value.relativePath, '/icons/categories');
|
||||||
@@ -25,22 +28,32 @@ const headers = computed(() => {
|
|||||||
level: 2,
|
level: 2,
|
||||||
link: `${linkPrefix}#${name}`,
|
link: `${linkPrefix}#${name}`,
|
||||||
title,
|
title,
|
||||||
iconCount
|
iconCount: categoryCounts.value[name] ?? iconCount,
|
||||||
|
name
|
||||||
}))
|
}))
|
||||||
})
|
})
|
||||||
|
|
||||||
const container = ref()
|
const container = ref()
|
||||||
const marker = ref()
|
const marker = ref()
|
||||||
|
|
||||||
useActiveAnchor(container, marker)
|
const { setActiveLinkDebounced } = useActiveAnchor(container, marker)
|
||||||
|
|
||||||
|
watch(headers, () => {
|
||||||
|
setTimeout(() => {
|
||||||
|
setActiveLinkDebounced()
|
||||||
|
}, 200)
|
||||||
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="category-list" ref="container">
|
<div class="category-list" ref="container">
|
||||||
<VPLink class="sidebar-title" href="/icons/" :class="{ 'active': overviewIsActive } ">
|
<SidebarTitle>
|
||||||
|
View
|
||||||
|
</SidebarTitle>
|
||||||
|
<VPLink class="sidebar-link sidebar-text" href="/icons/" :class="{ 'active': overviewIsActive } ">
|
||||||
All
|
All
|
||||||
</VPLink>
|
</VPLink>
|
||||||
<VPLink class="sidebar-title" href="/icons/categories" :class="{ 'active': categoriesIsActive } ">
|
<VPLink class="sidebar-link sidebar-text" href="/icons/categories" :class="{ 'active': categoriesIsActive } ">
|
||||||
Categories
|
Categories
|
||||||
</VPLink>
|
</VPLink>
|
||||||
<div class="content">
|
<div class="content">
|
||||||
@@ -53,17 +66,20 @@ useActiveAnchor(container, marker)
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.sidebar-title {
|
.sidebar-text {
|
||||||
font-weight: 500;
|
|
||||||
color: var(--vp-c-text-2);
|
|
||||||
margin-bottom: 6px;
|
|
||||||
line-height: 24px;
|
line-height: 24px;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
display: block;
|
display: block;
|
||||||
transition: color 0.25s;
|
transition: color 0.25s;
|
||||||
|
padding: 4px 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.sidebar-title:hover, .sidebar-title.active {
|
.sidebar-link {
|
||||||
|
font-weight: 500;
|
||||||
|
color: var(--vp-c-text-2);
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidebar-link:hover, .sidebar-link.active {
|
||||||
color: var(--vp-c-brand);
|
color: var(--vp-c-brand);
|
||||||
}
|
}
|
||||||
.content {
|
.content {
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ interface Header {
|
|||||||
slug: string;
|
slug: string;
|
||||||
iconCount: number;
|
iconCount: number;
|
||||||
link: string;
|
link: string;
|
||||||
|
name: string;
|
||||||
children: Header[];
|
children: Header[];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -14,36 +15,35 @@ type MenuItem = Omit<Header, 'slug' | 'children'> & {
|
|||||||
children?: MenuItem[];
|
children?: MenuItem[];
|
||||||
};
|
};
|
||||||
|
|
||||||
const props = defineProps<{
|
defineProps<{
|
||||||
headers: MenuItem[];
|
headers: MenuItem[];
|
||||||
root?: boolean;
|
root?: boolean;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const { selectedCategory } = useCategoryView();
|
const { selectedCategory } = useCategoryView();
|
||||||
|
|
||||||
function onClick(event: Event) {
|
function onClick(categoryName: string) {
|
||||||
const target =
|
selectedCategory.value = categoryName;
|
||||||
(event.target as HTMLElement).nodeName === 'span'
|
|
||||||
? (event.target as HTMLElement).parentNode
|
|
||||||
: (event.target as HTMLElement);
|
|
||||||
const href = (target as HTMLAnchorElement)?.href;
|
|
||||||
|
|
||||||
if (href) {
|
const heading = document.querySelector<HTMLAnchorElement>(categoryName);
|
||||||
const id = '#' + href.split('#')[1];
|
|
||||||
const decodedId = decodeURIComponent(id);
|
|
||||||
|
|
||||||
selectedCategory.value = decodedId.replace('#', '');
|
|
||||||
|
|
||||||
const heading = document.querySelector<HTMLAnchorElement>(decodedId);
|
|
||||||
heading?.focus();
|
heading?.focus();
|
||||||
}
|
|
||||||
|
window.history.pushState({}, '', `/icons/categories#${categoryName}`)
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<ul :class="root ? 'root' : 'nested'">
|
<ul :class="root ? 'root' : 'nested'">
|
||||||
<li v-for="{ children, link, title, iconCount } in headers">
|
<li v-for="{ children, link, title, iconCount, name } in headers">
|
||||||
<a class="outline-link" :href="link" @click="onClick" :title="title">
|
<a
|
||||||
|
class="outline-link"
|
||||||
|
:href="link"
|
||||||
|
@click="onClick(name)"
|
||||||
|
:title="title"
|
||||||
|
:class="{
|
||||||
|
inactive: iconCount === 0,
|
||||||
|
}"
|
||||||
|
>
|
||||||
<span>
|
<span>
|
||||||
{{ title }}
|
{{ title }}
|
||||||
</span>
|
</span>
|
||||||
@@ -83,6 +83,10 @@ function onClick(event: Event) {
|
|||||||
transition: color 0.25s;
|
transition: color 0.25s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.outline-link.inactive {
|
||||||
|
color: var(--vp-c-text-4);
|
||||||
|
}
|
||||||
|
|
||||||
.outline-link.nested {
|
.outline-link.nested {
|
||||||
padding-left: 13px;
|
padding-left: 13px;
|
||||||
}
|
}
|
||||||
@@ -93,4 +97,8 @@ function onClick(event: Event) {
|
|||||||
font-size: 11px;
|
font-size: 11px;
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.outline-link.inactive .icon-count {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -1,92 +1,98 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { computed } from 'vue';
|
import { computed } from 'vue';
|
||||||
import { startCase, camelCase } from 'lodash-es'
|
import { toPascalCase } from '@lucide/shared';
|
||||||
import ButtonMenu from '../base/ButtonMenu.vue'
|
import ButtonMenu from '../base/ButtonMenu.vue';
|
||||||
import { useIconStyleContext } from '../../composables/useIconStyle';
|
import { useIconStyleContext } from '../../composables/useIconStyle';
|
||||||
import useConfetti from '../../composables/useConfetti';
|
import useConfetti from '../../composables/useConfetti';
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
name: string
|
name: string;
|
||||||
popoverPosition?: 'top' | 'bottom'
|
popoverPosition?: 'top' | 'bottom';
|
||||||
}>()
|
}>();
|
||||||
const { size, color, strokeWidth, absoluteStrokeWidth } = useIconStyleContext()
|
const { size, color, strokeWidth, absoluteStrokeWidth } = useIconStyleContext();
|
||||||
const { animate, confetti } = useConfetti()
|
const { animate, confetti } = useConfetti();
|
||||||
const componentName = computed(() => {
|
const componentName = computed(() => {
|
||||||
return startCase(camelCase(props.name)).replace(/\s/g, '')
|
return (toPascalCase(props.name) as string).replace(/\s/g, '');
|
||||||
})
|
});
|
||||||
|
|
||||||
function copyJSX() {
|
function copyJSX() {
|
||||||
let attrs = ['']
|
let attrs = [''];
|
||||||
|
|
||||||
if (size.value && size.value !== 24) {
|
if (size.value && size.value !== 24) {
|
||||||
attrs.push(`size={${size.value}}`)
|
attrs.push(`size={${size.value}}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (color.value && color.value !== 'currentColor') {
|
if (color.value && color.value !== 'currentColor') {
|
||||||
attrs.push(`color="${color.value}"`)
|
attrs.push(`color="${color.value}"`);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strokeWidth.value && strokeWidth.value !== 2) {
|
if (strokeWidth.value && strokeWidth.value !== 2) {
|
||||||
attrs.push(`strokeWidth={${strokeWidth.value}}`)
|
attrs.push(`strokeWidth={${strokeWidth.value}}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (absoluteStrokeWidth.value) {
|
if (absoluteStrokeWidth.value) {
|
||||||
attrs.push(`absoluteStrokeWidth`)
|
attrs.push(`absoluteStrokeWidth`);
|
||||||
}
|
}
|
||||||
|
|
||||||
const code = `<${componentName.value}${attrs.join(' ')} />`
|
const code = `<${componentName.value}${attrs.join(' ')} />`;
|
||||||
|
|
||||||
navigator.clipboard.writeText(code)
|
navigator.clipboard.writeText(code);
|
||||||
|
}
|
||||||
|
|
||||||
|
function copyComponentName() {
|
||||||
|
const code = componentName.value;
|
||||||
|
|
||||||
|
navigator.clipboard.writeText(code);
|
||||||
}
|
}
|
||||||
|
|
||||||
function copyVue() {
|
function copyVue() {
|
||||||
let attrs = ['']
|
let attrs = [''];
|
||||||
|
|
||||||
if (size.value && size.value !== 24) {
|
if (size.value && size.value !== 24) {
|
||||||
attrs.push(`:size="${size.value}"`)
|
attrs.push(`:size="${size.value}"`);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (color.value && color.value !== 'currentColor') {
|
if (color.value && color.value !== 'currentColor') {
|
||||||
attrs.push(`color="${color.value}"`)
|
attrs.push(`color="${color.value}"`);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strokeWidth.value && strokeWidth.value !== 2) {
|
if (strokeWidth.value && strokeWidth.value !== 2) {
|
||||||
attrs.push(`:stroke-width="${strokeWidth.value}"`)
|
attrs.push(`:stroke-width="${strokeWidth.value}"`);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (absoluteStrokeWidth.value) {
|
if (absoluteStrokeWidth.value) {
|
||||||
attrs.push(`absoluteStrokeWidth`)
|
attrs.push(`absoluteStrokeWidth`);
|
||||||
}
|
}
|
||||||
|
|
||||||
const code = `<${componentName.value}${attrs.join(' ')} />`
|
const code = `<${componentName.value}${attrs.join(' ')} />`;
|
||||||
|
|
||||||
navigator.clipboard.writeText(code)
|
navigator.clipboard.writeText(code);
|
||||||
}
|
}
|
||||||
|
|
||||||
function copyAngular() {
|
function copyAngular() {
|
||||||
let attrs = ['']
|
let attrs = [''];
|
||||||
|
|
||||||
attrs.push(`name="${props.name}"`)
|
attrs.push(`name="${props.name}"`);
|
||||||
|
|
||||||
if (size.value && size.value !== 24) {
|
if (size.value && size.value !== 24) {
|
||||||
attrs.push(`[size]="${size.value}"`)
|
attrs.push(`[size]="${size.value}"`);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (color.value && color.value !== 'currentColor') {
|
if (color.value && color.value !== 'currentColor') {
|
||||||
attrs.push(`color="${color.value}"`)
|
attrs.push(`color="${color.value}"`);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strokeWidth.value && strokeWidth.value !== 2) {
|
if (strokeWidth.value && strokeWidth.value !== 2) {
|
||||||
attrs.push(`[strokeWidth]="${strokeWidth.value}"`)
|
attrs.push(`[strokeWidth]="${strokeWidth.value}"`);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (absoluteStrokeWidth.value) {
|
if (absoluteStrokeWidth.value) {
|
||||||
attrs.push(`[absoluteStrokeWidth]="true"`)
|
attrs.push(`[absoluteStrokeWidth]="true"`);
|
||||||
}
|
}
|
||||||
|
|
||||||
const code = `<lucide-icon${attrs.join(' ')}></lucide-icon>`
|
const code = `<lucide-icon${attrs.join(' ')}></lucide-icon>`;
|
||||||
|
|
||||||
navigator.clipboard.writeText(code)
|
navigator.clipboard.writeText(code);
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@@ -100,10 +106,11 @@ function copyAngular() {
|
|||||||
data-confetti-text="Copied!"
|
data-confetti-text="Copied!"
|
||||||
:popoverPosition="popoverPosition"
|
:popoverPosition="popoverPosition"
|
||||||
:options="[
|
:options="[
|
||||||
{ text: 'Copy JSX' , onClick: copyJSX },
|
{ text: 'Copy JSX', onClick: copyJSX },
|
||||||
{ text: 'Copy Vue' , onClick: copyVue },
|
{ text: 'Copy Component Name', onClick: copyComponentName },
|
||||||
{ text: 'Copy Svelte' , onClick: copyJSX },
|
{ text: 'Copy Vue', onClick: copyVue },
|
||||||
{ text: 'Copy Angular' , onClick: copyAngular },
|
{ text: 'Copy Svelte', onClick: copyJSX },
|
||||||
|
{ text: 'Copy Angular', onClick: copyAngular },
|
||||||
]"
|
]"
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -11,15 +11,32 @@ import IconInfo from './IconInfo.vue';
|
|||||||
import Badge from '../base/Badge.vue';
|
import Badge from '../base/Badge.vue';
|
||||||
import { computedAsync } from '@vueuse/core';
|
import { computedAsync } from '@vueuse/core';
|
||||||
import { satisfies } from 'semver';
|
import { satisfies } from 'semver';
|
||||||
|
import { useExternalLibs } from '../../composables/useExternalLibs';
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
iconName: string
|
iconName: string | null
|
||||||
}>()
|
}>()
|
||||||
|
|
||||||
|
const { externalIconNodes } = useExternalLibs()
|
||||||
|
|
||||||
|
const { go } = useRouter()
|
||||||
|
|
||||||
const icon = computedAsync<IconEntity | null>(async () => {
|
const icon = computedAsync<IconEntity | null>(async () => {
|
||||||
if (props.iconName) {
|
if (props.iconName) {
|
||||||
|
try {
|
||||||
|
if (props.iconName.includes(':')) {
|
||||||
|
const [library, name] = props.iconName.split(':')
|
||||||
|
|
||||||
|
return externalIconNodes.value[library].find((icon) => icon.name === name)
|
||||||
|
} else {
|
||||||
return (await import(`../../../data/iconDetails/${props.iconName}.ts`)).default as IconEntity
|
return (await import(`../../../data/iconDetails/${props.iconName}.ts`)).default as IconEntity
|
||||||
}
|
}
|
||||||
|
} catch (err) {
|
||||||
|
if (!props.iconName.includes(':')) {
|
||||||
|
go(`/icons/${props.iconName}`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
return null
|
return null
|
||||||
}, null)
|
}, null)
|
||||||
|
|
||||||
@@ -36,8 +53,6 @@ function onClose() {
|
|||||||
emit('close')
|
emit('close')
|
||||||
}
|
}
|
||||||
|
|
||||||
const { go } = useRouter()
|
|
||||||
|
|
||||||
const CloseIcon = createLucideIcon('Close', x)
|
const CloseIcon = createLucideIcon('Close', x)
|
||||||
const Expand = createLucideIcon('Expand', expand)
|
const Expand = createLucideIcon('Expand', expand)
|
||||||
</script>
|
</script>
|
||||||
@@ -51,10 +66,8 @@ const Expand = createLucideIcon('Expand', expand)
|
|||||||
v-if="icon.createdRelease"
|
v-if="icon.createdRelease"
|
||||||
class="version"
|
class="version"
|
||||||
:href="releaseTagLink(icon.createdRelease.version)"
|
:href="releaseTagLink(icon.createdRelease.version)"
|
||||||
target="_blank"
|
|
||||||
rel="noreferrer noopener"
|
|
||||||
>v{{ icon.createdRelease.version }}</Badge>
|
>v{{ icon.createdRelease.version }}</Badge>
|
||||||
<IconButton @click="go(`/icons/${icon.name}`)">
|
<IconButton @click="go(icon.externalLibrary ? `/icons/${icon.externalLibrary}/${icon.name}` : `/icons/${icon.name}`)">
|
||||||
<component :is="Expand" />
|
<component :is="Expand" />
|
||||||
</IconButton>
|
</IconButton>
|
||||||
<IconButton @click="onClose">
|
<IconButton @click="onClose">
|
||||||
@@ -144,11 +157,11 @@ const Expand = createLucideIcon('Expand', expand)
|
|||||||
}
|
}
|
||||||
|
|
||||||
.drawer-enter-active {
|
.drawer-enter-active {
|
||||||
transition: all 0.2s cubic-bezier(.21,.8,.46,.9);
|
transition: opacity 0.5s, transform 0.25s ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
.drawer-leave-active {
|
.drawer-leave-active {
|
||||||
transition: all 0.4s cubic-bezier(1, 0.5, 0.8, 1);
|
transition: opacity 0.25s ease, transform 1.6s ease-out;
|
||||||
}
|
}
|
||||||
|
|
||||||
.drawer-enter-from,
|
.drawer-enter-from,
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import IconItem from './IconItem.vue'
|
|||||||
|
|
||||||
const emit = defineEmits(['setActiveIcon'])
|
const emit = defineEmits(['setActiveIcon'])
|
||||||
|
|
||||||
const props = defineProps<{
|
defineProps<{
|
||||||
icons: IconEntity[]
|
icons: IconEntity[]
|
||||||
activeIcon?: string
|
activeIcon?: string
|
||||||
overlayMode?: boolean
|
overlayMode?: boolean
|
||||||
@@ -25,8 +25,10 @@ function setActiveIcon(name: string) {
|
|||||||
:key="icon.name"
|
:key="icon.name"
|
||||||
>
|
>
|
||||||
<IconItem
|
<IconItem
|
||||||
v-bind="icon"
|
:iconNode="icon.iconNode"
|
||||||
@setActiveIcon="setActiveIcon(icon.name)"
|
:name="icon.name"
|
||||||
|
:externalLibrary="icon.externalLibrary"
|
||||||
|
@setActiveIcon="setActiveIcon"
|
||||||
:active="activeIcon === icon.name"
|
:active="activeIcon === icon.name"
|
||||||
customizable
|
customizable
|
||||||
:overlayMode="overlayMode"
|
:overlayMode="overlayMode"
|
||||||
@@ -40,7 +42,6 @@ function setActiveIcon(name: string) {
|
|||||||
.icons {
|
.icons {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: repeat(auto-fill, minmax(56px, 1fr));
|
grid-template-columns: repeat(auto-fill, minmax(56px, 1fr));
|
||||||
/* padding: 32px 32px 96px; */
|
|
||||||
gap: 8px;
|
gap: 8px;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,10 @@ import CopyCodeButton from './CopyCodeButton.vue';
|
|||||||
import VPButton from 'vitepress/dist/client/theme-default/components/VPButton.vue';
|
import VPButton from 'vitepress/dist/client/theme-default/components/VPButton.vue';
|
||||||
import {useData, useRouter} from 'vitepress';
|
import {useData, useRouter} from 'vitepress';
|
||||||
import { computed } from 'vue';
|
import { computed } from 'vue';
|
||||||
|
import createLucideIcon from 'lucide-vue-next/src/createLucideIcon';
|
||||||
|
import { diamond } from '../../../data/iconNodes'
|
||||||
|
import deprecationReasonTemplate from '../../../../../tools/build-icons/utils/deprecationReasonTemplate.mjs';
|
||||||
|
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
icon: IconEntity
|
icon: IconEntity
|
||||||
@@ -20,13 +24,37 @@ const tags = computed(() => {
|
|||||||
if (!props.icon || !props?.icon?.tags) return []
|
if (!props.icon || !props?.icon?.tags) return []
|
||||||
return props.icon.tags.join(' • ')
|
return props.icon.tags.join(' • ')
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const DiamondIcon = createLucideIcon('Diamond', diamond)
|
||||||
|
|
||||||
|
const deprecatedTitle = computed(() => {
|
||||||
|
if (!props.icon.deprecationReason) return '';
|
||||||
|
return deprecationReasonTemplate(props.icon.deprecationReason, {
|
||||||
|
componentName: props.icon.name,
|
||||||
|
iconName: props.icon.name,
|
||||||
|
toBeRemovedInVersion: props.icon.toBeRemovedInVersion,
|
||||||
|
});
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="icon-info">
|
<div class="icon-info">
|
||||||
|
<div class="icon-name-wrapper">
|
||||||
<IconDetailName class="icon-name">
|
<IconDetailName class="icon-name">
|
||||||
{{ icon.name }}
|
{{ icon.name }}
|
||||||
</IconDetailName>
|
</IconDetailName>
|
||||||
|
<div v-if="icon.externalLibrary" class="icon-external-lib">
|
||||||
|
<DiamondIcon fill="currentColor" :size="12"/>
|
||||||
|
{{ icon.externalLibrary }}
|
||||||
|
</div>
|
||||||
|
<Badge
|
||||||
|
v-if="icon.deprecated"
|
||||||
|
class="deprecated-badge"
|
||||||
|
:title="deprecatedTitle"
|
||||||
|
>
|
||||||
|
Deprecated
|
||||||
|
</Badge>
|
||||||
|
</div>
|
||||||
<div class="tags-scroller" v-if="tags.length">
|
<div class="tags-scroller" v-if="tags.length">
|
||||||
<p class="icon-tags horizontal-scroller">
|
<p class="icon-tags horizontal-scroller">
|
||||||
{{ tags }}
|
{{ tags }}
|
||||||
@@ -44,10 +72,10 @@ const tags = computed(() => {
|
|||||||
|
|
||||||
<div class="group buttons">
|
<div class="group buttons">
|
||||||
<VPButton
|
<VPButton
|
||||||
v-if="!page?.relativePath?.startsWith?.(`icons/${icon.name}`)"
|
v-if="!page?.relativePath?.startsWith?.(icon.externalLibrary ? `icons/${icon.externalLibrary}/${icon.name}`: `icons/${icon.name}`)"
|
||||||
:href="`/icons/${icon.name}`"
|
:href="icon.externalLibrary ? `/icons/${icon.externalLibrary}/${icon.name}`: `/icons/${icon.name}`"
|
||||||
text="See in action"
|
text="See in action"
|
||||||
@click="go(`/icons/${icon.name}`)"
|
@click="go(icon.externalLibrary ? `/icons/${icon.externalLibrary}/${icon.name}`: `/icons/${icon.name}`)"
|
||||||
/>
|
/>
|
||||||
<CopySVGButton :name="icon.name" :popoverPosition="popoverPosition"/>
|
<CopySVGButton :name="icon.name" :popoverPosition="popoverPosition"/>
|
||||||
<CopyCodeButton :name="icon.name" :popoverPosition="popoverPosition"/>
|
<CopyCodeButton :name="icon.name" :popoverPosition="popoverPosition"/>
|
||||||
@@ -67,9 +95,37 @@ const tags = computed(() => {
|
|||||||
text-transform: capitalize;
|
text-transform: capitalize;
|
||||||
}
|
}
|
||||||
.icon-name {
|
.icon-name {
|
||||||
|
margin-right: -36px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon-name-wrapper {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 2px;
|
||||||
margin-bottom: 4px;
|
margin-bottom: 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.icon-external-lib {
|
||||||
|
color: var(--vp-c-brand-dark);
|
||||||
|
padding: 4px 12px;
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: 600;
|
||||||
|
line-height: 28px;
|
||||||
|
display: flex;
|
||||||
|
gap: 8px;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.deprecated-badge {
|
||||||
|
background-color: var(--vp-c-brand-5);
|
||||||
|
margin-left: 40px;
|
||||||
|
opacity: .8;
|
||||||
|
}
|
||||||
|
|
||||||
|
.deprecated-badge:hover {
|
||||||
|
background-color: var(--vp-c-brand-2);
|
||||||
|
}
|
||||||
|
|
||||||
.icon-tags {
|
.icon-tags {
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
color: var(--vp-c-text-2);
|
color: var(--vp-c-text-2);
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import { useRouter } from 'vitepress';
|
|||||||
import getSVGIcon from '../../utils/getSVGIcon';
|
import getSVGIcon from '../../utils/getSVGIcon';
|
||||||
import useConfetti from '../../composables/useConfetti';
|
import useConfetti from '../../composables/useConfetti';
|
||||||
import Tooltip from '../base/Tooltip.vue';
|
import Tooltip from '../base/Tooltip.vue';
|
||||||
|
import { diamond } from '../../../data/iconNodes'
|
||||||
|
|
||||||
const downloadText = 'Download!'
|
const downloadText = 'Download!'
|
||||||
const copiedText = 'Copied!'
|
const copiedText = 'Copied!'
|
||||||
@@ -16,6 +17,7 @@ const props = defineProps<{
|
|||||||
name: string;
|
name: string;
|
||||||
iconNode: IconNode;
|
iconNode: IconNode;
|
||||||
active: boolean;
|
active: boolean;
|
||||||
|
externalLibrary?: string;
|
||||||
customizable?: boolean;
|
customizable?: boolean;
|
||||||
overlayMode?: boolean
|
overlayMode?: boolean
|
||||||
hideIcon?: boolean
|
hideIcon?: boolean
|
||||||
@@ -33,8 +35,9 @@ const icon = computed(() => {
|
|||||||
return createLucideIcon(props.name, props.iconNode)
|
return createLucideIcon(props.name, props.iconNode)
|
||||||
})
|
})
|
||||||
|
|
||||||
async function navigateToIcon(event) {
|
const href = computed(() => props.externalLibrary ? `/icons/${props.externalLibrary}/${props.name}` : `/icons/${props.name}`)
|
||||||
|
|
||||||
|
async function navigateToIcon(event) {
|
||||||
if (event.shiftKey) {
|
if (event.shiftKey) {
|
||||||
event.preventDefault()
|
event.preventDefault()
|
||||||
const svgString = getSVGIcon(event.target.firstChild, {
|
const svgString = getSVGIcon(event.target.firstChild, {
|
||||||
@@ -50,14 +53,16 @@ async function navigateToIcon(event) {
|
|||||||
|
|
||||||
if(props.overlayMode && showOverlay.value) {
|
if(props.overlayMode && showOverlay.value) {
|
||||||
event.preventDefault()
|
event.preventDefault()
|
||||||
window.history.pushState({}, '', `/icons/${props.name}`)
|
|
||||||
emit('setActiveIcon', props.name)
|
window.history.pushState({}, '', props.externalLibrary ? `/icons/${props.externalLibrary}/${props.name}` : `/icons/${props.name}`)
|
||||||
}
|
emit('setActiveIcon', props.externalLibrary ? `${props.externalLibrary}:${props.name}`: props.name)
|
||||||
else {
|
} else {
|
||||||
event.preventDefault()
|
event.preventDefault()
|
||||||
go(`/icons/${props.name}`)
|
go(props.externalLibrary ? `/icons/${props.externalLibrary}/${props.name}` : `/icons/${props.name}`)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const DiamondIcon = createLucideIcon('Diamond', diamond)
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
@@ -67,7 +72,7 @@ async function navigateToIcon(event) {
|
|||||||
@click="navigateToIcon"
|
@click="navigateToIcon"
|
||||||
:class="{ active, animate }"
|
:class="{ active, animate }"
|
||||||
:aria-label="name"
|
:aria-label="name"
|
||||||
:href="`/icons/${props.name}`"
|
|
||||||
:data-confetti-text="confettiText"
|
:data-confetti-text="confettiText"
|
||||||
ref="ref"
|
ref="ref"
|
||||||
>
|
>
|
||||||
@@ -81,6 +86,13 @@ async function navigateToIcon(event) {
|
|||||||
}"
|
}"
|
||||||
/>
|
/>
|
||||||
</KeepAlive>
|
</KeepAlive>
|
||||||
|
<div
|
||||||
|
v-if="externalLibrary"
|
||||||
|
class="floating-diamond"
|
||||||
|
aria-hidden="true"
|
||||||
|
>
|
||||||
|
<DiamondIcon fill="currentColor" :size="8"/>
|
||||||
|
</div>
|
||||||
</a>
|
</a>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
</template>
|
</template>
|
||||||
@@ -89,6 +101,7 @@ async function navigateToIcon(event) {
|
|||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.icon-button {
|
.icon-button {
|
||||||
|
position: relative;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
border: 1px solid transparent;
|
border: 1px solid transparent;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
@@ -105,6 +118,13 @@ async function navigateToIcon(event) {
|
|||||||
color: var(--vp-c-text-1);
|
color: var(--vp-c-text-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.floating-diamond {
|
||||||
|
position: absolute;
|
||||||
|
top: 4px;
|
||||||
|
right: 4px;
|
||||||
|
color: var(--vp-c-brand);
|
||||||
|
}
|
||||||
|
|
||||||
.confetti-button:before,
|
.confetti-button:before,
|
||||||
.confetti-button:after {
|
.confetti-button:after {
|
||||||
z-index: 100;
|
z-index: 100;
|
||||||
|
|||||||
438
docs/.vitepress/theme/components/icons/IconShowcase.vue
Normal file
438
docs/.vitepress/theme/components/icons/IconShowcase.vue
Normal file
@@ -0,0 +1,438 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import type { IconEntity } from '../../types';
|
||||||
|
import { computed } from 'vue';
|
||||||
|
import createLucideIcon from 'lucide-vue-next/src/createLucideIcon.ts';
|
||||||
|
import Calendar from '../../../data/iconDetails/calendar.ts';
|
||||||
|
import Clock from '../../../data/iconDetails/clock.ts';
|
||||||
|
import Bug from '../../../data/iconDetails/bug.ts';
|
||||||
|
import Rocket from '../../../data/iconDetails/rocket.ts';
|
||||||
|
import TriangleAlert from '../../../data/iconDetails/triangle-alert.ts';
|
||||||
|
import PartyPopper from '../../../data/iconDetails/party-popper.ts';
|
||||||
|
import Scissors from '../../../data/iconDetails/scissors.ts';
|
||||||
|
import Copy from '../../../data/iconDetails/copy.ts';
|
||||||
|
import Save from '../../../data/iconDetails/save.ts';
|
||||||
|
import Clipboard from '../../../data/iconDetails/clipboard.ts';
|
||||||
|
import MessageCircle from '../../../data/iconDetails/message-circle.ts';
|
||||||
|
import ThumbsDown from '../../../data/iconDetails/thumbs-down.ts';
|
||||||
|
import ThumbsUp from '../../../data/iconDetails/thumbs-up.ts';
|
||||||
|
import Heart from '../../../data/iconDetails/heart.ts';
|
||||||
|
import Folder from '../../../data/iconDetails/folder.ts';
|
||||||
|
import Files from '../../../data/iconDetails/files.ts';
|
||||||
|
import Plus from '../../../data/iconDetails/plus.ts';
|
||||||
|
import File from '../../../data/iconDetails/file.ts';
|
||||||
|
import FileText from '../../../data/iconDetails/file-text.ts';
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
name: IconEntity['name'];
|
||||||
|
iconNode: IconEntity['iconNode'];
|
||||||
|
}>();
|
||||||
|
|
||||||
|
const iconComponent = computed(() => {
|
||||||
|
if (!props.name || !props.iconNode) return null;
|
||||||
|
return createLucideIcon(props.name, props.iconNode);
|
||||||
|
});
|
||||||
|
|
||||||
|
const CalendarIcon = createLucideIcon('calendar', Calendar.iconNode);
|
||||||
|
const ClockIcon = createLucideIcon('clock', Clock.iconNode);
|
||||||
|
const BugIcon = createLucideIcon('bug', Bug.iconNode);
|
||||||
|
const RocketIcon = createLucideIcon('rocket', Rocket.iconNode);
|
||||||
|
const AlertTriangleIcon = createLucideIcon('alert-triangle', TriangleAlert.iconNode);
|
||||||
|
const ScissorsIcon = createLucideIcon('scissors', Scissors.iconNode);
|
||||||
|
const CopyIcon = createLucideIcon('copy', Copy.iconNode);
|
||||||
|
const SaveIcon = createLucideIcon('save', Save.iconNode);
|
||||||
|
const ClipboardIcon = createLucideIcon('clipboard', Clipboard.iconNode);
|
||||||
|
const PartyPopperIcon = createLucideIcon('party-popper', PartyPopper.iconNode);
|
||||||
|
const HeartIcon = createLucideIcon('heart', Heart.iconNode);
|
||||||
|
const ThumbsUpIcon = createLucideIcon('thumbs-up', ThumbsUp.iconNode);
|
||||||
|
const ThumbsDownIcon = createLucideIcon('thumbs-down', ThumbsDown.iconNode);
|
||||||
|
const MessageCircleIcon = createLucideIcon('message-circle', MessageCircle.iconNode);
|
||||||
|
const FolderIcon = createLucideIcon('folder.ts', Folder.iconNode);
|
||||||
|
const FilesIcon = createLucideIcon('files.ts', Files.iconNode);
|
||||||
|
const PlusIcon = createLucideIcon('plus.ts', Plus.iconNode);
|
||||||
|
const FileIcon = createLucideIcon('file.ts', File.iconNode);
|
||||||
|
const FileTextIcon = createLucideIcon('file-text.ts', FileText.iconNode);
|
||||||
|
|
||||||
|
const prettyName = props.name
|
||||||
|
.split('-')
|
||||||
|
.at(0)
|
||||||
|
.split('')
|
||||||
|
.map((character, index) => (index === 0 ? character.toUpperCase() : character))
|
||||||
|
.join('');
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<section class="showcase">
|
||||||
|
<h2 class="title">See this icon in action</h2>
|
||||||
|
<div class="showcase-grid">
|
||||||
|
<div class="showcase-item column">
|
||||||
|
<div class="placeholder"></div>
|
||||||
|
<div class="placeholder"></div>
|
||||||
|
<div class="placeholder"></div>
|
||||||
|
<div class="placeholder narrow"></div>
|
||||||
|
<div class="spacer"></div>
|
||||||
|
<div class="actions">
|
||||||
|
<button class="button button-brand">
|
||||||
|
<iconComponent />
|
||||||
|
{{ prettyName }}
|
||||||
|
</button>
|
||||||
|
<button class="button button-alt">Cancel</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="showcase-item column">
|
||||||
|
<div class="placeholder narrow"></div>
|
||||||
|
<div class="input-wrapper">
|
||||||
|
<CalendarIcon v-if="name !== 'calendar'" />
|
||||||
|
<ClockIcon v-if="name == 'calendar'" />
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
v-if="name !== 'calendar'"
|
||||||
|
placeholder="Enter a date..."
|
||||||
|
/>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
v-if="name == 'calendar'"
|
||||||
|
placeholder="Enter a time..."
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="spacer"></div>
|
||||||
|
<div class="placeholder narrow"></div>
|
||||||
|
<div class="input-wrapper">
|
||||||
|
<iconComponent />
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
placeholder="Enter a value..."
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="showcase-item column">
|
||||||
|
<div
|
||||||
|
class="row"
|
||||||
|
v-if="name !== 'bug'"
|
||||||
|
>
|
||||||
|
<div class="placeholder"></div>
|
||||||
|
<div class="badge badge-red">
|
||||||
|
<BugIcon :size="20" />
|
||||||
|
Bug
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="row"
|
||||||
|
v-else
|
||||||
|
>
|
||||||
|
<div class="placeholder"></div>
|
||||||
|
<div class="badge badge-red">
|
||||||
|
<AlertTriangleIcon :size="20" />
|
||||||
|
Alert
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="placeholder"></div>
|
||||||
|
<div class="badge badge-indigo">
|
||||||
|
<RocketIcon
|
||||||
|
:size="20"
|
||||||
|
v-if="name !== 'rocket'"
|
||||||
|
/>
|
||||||
|
<PartyPopperIcon
|
||||||
|
:size="20"
|
||||||
|
v-else
|
||||||
|
/>
|
||||||
|
Feature
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="placeholder"></div>
|
||||||
|
<div class="badge badge-green">
|
||||||
|
<iconComponent :size="20" />
|
||||||
|
{{ prettyName }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="showcase-item column">
|
||||||
|
<button class="button button-alt button-square">
|
||||||
|
<FolderIcon v-if="name !== 'folder'" />
|
||||||
|
<FilesIcon v-else />
|
||||||
|
Documents
|
||||||
|
<PlusIcon class="ms-auto" />
|
||||||
|
</button>
|
||||||
|
<button class="button button-alt button-square">
|
||||||
|
<FileIcon v-if="name !== 'file'" />
|
||||||
|
<FileTextIcon v-else />
|
||||||
|
Readme
|
||||||
|
</button>
|
||||||
|
<button class="button button-alt button-square">
|
||||||
|
<iconComponent />
|
||||||
|
{{ prettyName }}
|
||||||
|
<span class="badge-notification ms-auto">12</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div class="showcase-item column">
|
||||||
|
<div class="placeholder"></div>
|
||||||
|
<div class="placeholder"></div>
|
||||||
|
<div class="placeholder"></div>
|
||||||
|
<div class="placeholder narrow"></div>
|
||||||
|
<div class="spacer"></div>
|
||||||
|
<div class="actions">
|
||||||
|
<div class="icon-counter">
|
||||||
|
<HeartIcon v-if="name !== 'heart'" />
|
||||||
|
<ThumbsUpIcon v-else />
|
||||||
|
112
|
||||||
|
</div>
|
||||||
|
<div class="spacer"></div>
|
||||||
|
<div class="icon-counter">
|
||||||
|
<MessageCircleIcon v-if="name !== 'message-circle'" />
|
||||||
|
<ThumbsDownIcon v-else />
|
||||||
|
8
|
||||||
|
</div>
|
||||||
|
<div class="spacer"></div>
|
||||||
|
<div class="icon-counter">
|
||||||
|
<iconComponent />
|
||||||
|
11
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="showcase-item">
|
||||||
|
<div class="column align-items-center">
|
||||||
|
<div class="actions justify-content-center">
|
||||||
|
<button class="button button-icon">
|
||||||
|
<CopyIcon v-if="name !== 'copy'" />
|
||||||
|
<SaveIcon v-else />
|
||||||
|
</button>
|
||||||
|
<button class="button button-icon">
|
||||||
|
<ScissorsIcon v-if="name !== 'scissors'" />
|
||||||
|
<SaveIcon v-else />
|
||||||
|
</button>
|
||||||
|
<button class="button button-icon">
|
||||||
|
<ClipboardIcon v-if="name !== 'clipboard'" />
|
||||||
|
<SaveIcon v-else />
|
||||||
|
</button>
|
||||||
|
<button class="button button-icon">
|
||||||
|
<iconComponent></iconComponent>
|
||||||
|
<span class="badge-notification">2</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div class="spacer"></div>
|
||||||
|
<div class="placeholder"></div>
|
||||||
|
<div class="placeholder"></div>
|
||||||
|
<div class="placeholder"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.showcase {
|
||||||
|
margin-bottom: 32px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.showcase-grid {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));
|
||||||
|
gap: 48px;
|
||||||
|
margin-inline-start: 24px;
|
||||||
|
margin-block-start: 48px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.showcase-item {
|
||||||
|
padding: 24px;
|
||||||
|
border-radius: 8px;
|
||||||
|
background-color: var(--vp-c-bg);
|
||||||
|
box-shadow:
|
||||||
|
var(--vp-shadow-4),
|
||||||
|
-24px -24px 0 var(--vp-c-bg-soft);
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
min-height: 240px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.spacer {
|
||||||
|
flex-basis: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.button {
|
||||||
|
position: relative;
|
||||||
|
border-radius: 32px;
|
||||||
|
padding: 8px 16px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
gap: 12px;
|
||||||
|
font-weight: 500;
|
||||||
|
transition:
|
||||||
|
color 0.25s,
|
||||||
|
border-color 0.25s,
|
||||||
|
background-color 0.25s;
|
||||||
|
|
||||||
|
border-color: var(--vp-button-alt-border);
|
||||||
|
color: var(--vp-button-alt-text);
|
||||||
|
background-color: var(--vp-button-alt-bg);
|
||||||
|
&:hover {
|
||||||
|
border-color: var(--vp-button-alt-hover-border);
|
||||||
|
color: var(--vp-button-alt-hover-text);
|
||||||
|
background-color: var(--vp-button-alt-hover-bg);
|
||||||
|
}
|
||||||
|
&.button-brand {
|
||||||
|
border-color: var(--vp-button-brand-border);
|
||||||
|
color: var(--vp-button-brand-text);
|
||||||
|
background-color: var(--vp-button-brand-bg);
|
||||||
|
&:hover {
|
||||||
|
border-color: var(--vp-button-brand-hover-border);
|
||||||
|
color: var(--vp-button-brand-hover-text);
|
||||||
|
background-color: var(--vp-button-brand-hover-bg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&.button-icon {
|
||||||
|
padding: 12px;
|
||||||
|
}
|
||||||
|
&.button-square {
|
||||||
|
border-radius: 8px;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.actions {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.lucide {
|
||||||
|
flex-shrink: 0;
|
||||||
|
flex-grow: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.placeholder {
|
||||||
|
display: block;
|
||||||
|
background-color: var(--vp-c-bg-soft);
|
||||||
|
border-radius: 32px;
|
||||||
|
height: 16px;
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
&.narrow {
|
||||||
|
width: 33%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.input-wrapper {
|
||||||
|
position: relative;
|
||||||
|
width: 100%;
|
||||||
|
.lucide {
|
||||||
|
position: absolute;
|
||||||
|
inset-inline-start: 12px;
|
||||||
|
inset-block: 50%;
|
||||||
|
translate: 0 -50%;
|
||||||
|
color: var(--vp-c-text-1);
|
||||||
|
opacity: 0.7;
|
||||||
|
}
|
||||||
|
input {
|
||||||
|
padding: 12px 20px;
|
||||||
|
padding-inline-start: 48px;
|
||||||
|
border-radius: 8px;
|
||||||
|
background-color: var(--vp-c-bg-soft);
|
||||||
|
color: var(--vp-c-text-1);
|
||||||
|
display: block;
|
||||||
|
width: 100%;
|
||||||
|
border: 2px solid transparent;
|
||||||
|
transition:
|
||||||
|
color 0.25s,
|
||||||
|
border-color 0.25s,
|
||||||
|
background-color 0.25s;
|
||||||
|
&:hover {
|
||||||
|
border-color: var(--vp-c-border);
|
||||||
|
}
|
||||||
|
&:focus {
|
||||||
|
border-color: var(--vp-c-brand);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&:focus-within {
|
||||||
|
.lucide {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.badge {
|
||||||
|
flex-shrink: 0;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
gap: 6px;
|
||||||
|
padding: 4px 8px;
|
||||||
|
border-radius: 8px;
|
||||||
|
background-color: transparent;
|
||||||
|
overflow: hidden;
|
||||||
|
position: relative;
|
||||||
|
color: var(--badge-color);
|
||||||
|
&:before {
|
||||||
|
content: ' ';
|
||||||
|
inset: 0;
|
||||||
|
position: absolute;
|
||||||
|
background-color: var(--badge-color);
|
||||||
|
opacity: 0.1;
|
||||||
|
}
|
||||||
|
&.badge-indigo {
|
||||||
|
--badge-color: var(--vp-c-indigo-2);
|
||||||
|
}
|
||||||
|
&.badge-green {
|
||||||
|
--badge-color: var(--vp-c-green-2);
|
||||||
|
}
|
||||||
|
&.badge-red {
|
||||||
|
--badge-color: var(--vp-c-brand);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.badge-notification {
|
||||||
|
background-color: var(--vp-c-brand);
|
||||||
|
color: var(--vp-button-brand-text);
|
||||||
|
border-radius: 32px;
|
||||||
|
padding: 0 8px;
|
||||||
|
min-width: 24px;
|
||||||
|
min-height: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.button-icon {
|
||||||
|
.badge-notification {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
right: 0;
|
||||||
|
translate: 33% -33%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.row {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
gap: 12px;
|
||||||
|
align-items: center;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon-counter {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
gap: 6px;
|
||||||
|
color: var(--vp-c-text-2);
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.column {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 12px;
|
||||||
|
align-items: start;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.align-items-center {
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.justify-content-center {
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ms-auto {
|
||||||
|
margin-inline-start: auto;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -1,56 +1,53 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import { IconEntity } from '../../types';
|
||||||
|
|
||||||
|
type CategoryNameRow = {
|
||||||
|
type: 'category';
|
||||||
|
title: string;
|
||||||
|
name: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
type CategoryIconsRow = {
|
||||||
|
type: 'icons';
|
||||||
|
icons: IconEntity[];
|
||||||
|
};
|
||||||
|
|
||||||
|
export type CategoryRow = CategoryNameRow | CategoryIconsRow;
|
||||||
|
</script>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref } from 'vue';
|
|
||||||
import { Category } from '../../types';
|
|
||||||
import IconGrid from './IconGrid.vue'
|
import IconGrid from './IconGrid.vue'
|
||||||
import { vIntersectionObserver } from '@vueuse/components'
|
|
||||||
|
|
||||||
defineProps<{
|
defineProps<{
|
||||||
activeIconName: string
|
activeIconName: string | null
|
||||||
category: Category
|
categoryRow: CategoryRow
|
||||||
}>()
|
}>()
|
||||||
|
|
||||||
|
|
||||||
const emit = defineEmits(['setActiveIcon'])
|
const emit = defineEmits(['setActiveIcon'])
|
||||||
|
|
||||||
const showIcons = ref(false)
|
|
||||||
|
|
||||||
// Added intersection observer to improve performance
|
|
||||||
const onIntersectionObserver: IntersectionObserverCallback = ([{ isIntersecting }]) => {
|
|
||||||
showIcons.value = isIntersecting
|
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<section
|
<h2
|
||||||
class="category"
|
v-if="categoryRow.type === 'category'"
|
||||||
:key="category.name"
|
class="title"
|
||||||
:id="category.name"
|
|
||||||
v-intersection-observer="onIntersectionObserver"
|
|
||||||
>
|
>
|
||||||
<h2 class="title" >
|
<a class="header-anchor" :href="`#${categoryRow.name}`" :aria-label="`Permalink to "${categoryRow.title}"`">​</a>
|
||||||
<a class="header-anchor" :href="`#${category.name}`" :aria-label="`Permalink to "${category.title}"`">​</a>
|
{{ categoryRow.title }}
|
||||||
{{ category.title }}
|
|
||||||
</h2>
|
</h2>
|
||||||
<IconGrid
|
<IconGrid
|
||||||
|
v-else-if="categoryRow.type === 'icons'"
|
||||||
:activeIcon="activeIconName"
|
:activeIcon="activeIconName"
|
||||||
:icons="category.icons"
|
:icons="categoryRow.icons"
|
||||||
@setActiveIcon="$event => $emit('setActiveIcon', $event)"
|
@setActiveIcon="$event => $emit('setActiveIcon', $event)"
|
||||||
overlayMode
|
overlayMode
|
||||||
:hideIcons="!showIcons"
|
|
||||||
/>
|
/>
|
||||||
</section>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.title {
|
.title {
|
||||||
margin-bottom: 24px;
|
margin-bottom: 8px;
|
||||||
font-size: 19px;
|
font-size: 19px;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
padding-top: 86px;
|
padding: 24px 0 8px;
|
||||||
/* scroll-padding-top: 240px; */
|
|
||||||
}
|
|
||||||
|
|
||||||
.category {
|
|
||||||
margin-bottom: calc(-86px + 32px);
|
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref, computed, defineAsyncComponent } from 'vue';
|
import { ref, computed, defineAsyncComponent, onMounted, watch, watchEffect } from 'vue';
|
||||||
import type { IconEntity, Category } from '../../types';
|
import type { IconEntity, Category } from '../../types';
|
||||||
import useSearch from '../../composables/useSearch';
|
import useSearch from '../../composables/useSearch';
|
||||||
import InputSearch from '../base/InputSearch.vue';
|
import InputSearch from '../base/InputSearch.vue';
|
||||||
@@ -8,6 +8,14 @@ import StickyBar from './StickyBar.vue';
|
|||||||
import IconsCategory from './IconsCategory.vue';
|
import IconsCategory from './IconsCategory.vue';
|
||||||
import useFetchTags from '../../composables/useFetchTags';
|
import useFetchTags from '../../composables/useFetchTags';
|
||||||
import useFetchCategories from '../../composables/useFetchCategories';
|
import useFetchCategories from '../../composables/useFetchCategories';
|
||||||
|
import { useElementSize, useEventListener, useVirtualList } from '@vueuse/core';
|
||||||
|
import chunkArray from '../../utils/chunkArray';
|
||||||
|
import { CategoryRow } from './IconsCategory.vue';
|
||||||
|
import useScrollToCategory from '../../composables/useScrollToCategory';
|
||||||
|
import CarbonAdOverlay from './CarbonAdOverlay.vue';
|
||||||
|
|
||||||
|
const ICON_SIZE = 56;
|
||||||
|
const ICON_GRID_GAP = 8;
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
icons: IconEntity[];
|
icons: IconEntity[];
|
||||||
@@ -17,7 +25,6 @@ const props = defineProps<{
|
|||||||
|
|
||||||
const activeIconName = ref(null);
|
const activeIconName = ref(null);
|
||||||
const { searchInput, searchQuery, searchQueryDebounced } = useSearchInput();
|
const { searchInput, searchQuery, searchQueryDebounced } = useSearchInput();
|
||||||
|
|
||||||
const isSearching = computed(() => !!searchQuery.value);
|
const isSearching = computed(() => !!searchQuery.value);
|
||||||
|
|
||||||
function setActiveIconName(name: string) {
|
function setActiveIconName(name: string) {
|
||||||
@@ -27,6 +34,13 @@ function setActiveIconName(name: string) {
|
|||||||
const { execute: fetchTags, data: tags } = useFetchTags();
|
const { execute: fetchTags, data: tags } = useFetchTags();
|
||||||
const { execute: fetchCategories, data: categoriesMap } = useFetchCategories();
|
const { execute: fetchCategories, data: categoriesMap } = useFetchCategories();
|
||||||
|
|
||||||
|
const overviewEl = ref<HTMLElement | null>(null);
|
||||||
|
const { width: containerWidth } = useElementSize(overviewEl)
|
||||||
|
|
||||||
|
const columnSize = computed(() => {
|
||||||
|
return Math.floor((containerWidth.value) / ((ICON_SIZE + ICON_GRID_GAP)));
|
||||||
|
});
|
||||||
|
|
||||||
const mappedIcons = computed(() => {
|
const mappedIcons = computed(() => {
|
||||||
if (tags.value == null) {
|
if (tags.value == null) {
|
||||||
return props.icons;
|
return props.icons;
|
||||||
@@ -43,9 +57,10 @@ const mappedIcons = computed(() => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
const searchResults = useSearch(searchQuery, mappedIcons, [
|
const searchResults = useSearch(searchQueryDebounced, mappedIcons, [
|
||||||
{ name: 'name', weight: 2 },
|
{ name: 'name', weight: 3 },
|
||||||
{ name: 'tags', weight: 1 },
|
{ name: 'aliases', weight: 3 },
|
||||||
|
{ name: 'tags', weight: 2 },
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const categories = computed(() => {
|
const categories = computed(() => {
|
||||||
@@ -54,7 +69,7 @@ const categories = computed(() => {
|
|||||||
return props.categories
|
return props.categories
|
||||||
.map(({ name, title }) => {
|
.map(({ name, title }) => {
|
||||||
const categoryIcons = props.icons.filter((icon) => {
|
const categoryIcons = props.icons.filter((icon) => {
|
||||||
const iconCategories = props.iconCategories[icon.name];
|
const iconCategories = icon?.externalLibrary ? icon.categories : props.iconCategories[icon.name]
|
||||||
|
|
||||||
return iconCategories?.includes(name);
|
return iconCategories?.includes(name);
|
||||||
});
|
});
|
||||||
@@ -71,9 +86,43 @@ const categories = computed(() => {
|
|||||||
icons: searchedCategoryIcons,
|
icons: searchedCategoryIcons,
|
||||||
};
|
};
|
||||||
})
|
})
|
||||||
.filter(({ icons }) => icons.length);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const categoriesList = computed(() => {
|
||||||
|
return categories.value
|
||||||
|
.filter(({ icons }) => icons.length)
|
||||||
|
.reduce<CategoryRow[]>((acc, category) => {
|
||||||
|
acc.push({ type: 'category', title: category.title, name: category.name });
|
||||||
|
|
||||||
|
const categoryIcons = chunkArray(category.icons, columnSize.value);
|
||||||
|
categoryIcons.forEach((icons) => {
|
||||||
|
acc.push({ type: 'icons', icons });
|
||||||
|
});
|
||||||
|
|
||||||
|
return acc;
|
||||||
|
}, []);
|
||||||
|
});
|
||||||
|
|
||||||
|
const { list, containerProps, wrapperProps, scrollTo } = useVirtualList(
|
||||||
|
categoriesList,
|
||||||
|
{
|
||||||
|
itemHeight: ICON_SIZE + ICON_GRID_GAP,
|
||||||
|
overscan: 10
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
useScrollToCategory({
|
||||||
|
categories,
|
||||||
|
categoriesList,
|
||||||
|
scrollTo,
|
||||||
|
searchQueryDebounced,
|
||||||
|
})
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
containerProps.ref.value = document.documentElement;
|
||||||
|
useEventListener(window, 'scroll', containerProps.onScroll)
|
||||||
|
})
|
||||||
|
|
||||||
function onFocusSearchInput() {
|
function onFocusSearchInput() {
|
||||||
if (tags.value == null) {
|
if (tags.value == null) {
|
||||||
fetchTags();
|
fetchTags();
|
||||||
@@ -84,12 +133,24 @@ function onFocusSearchInput() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const NoResults = defineAsyncComponent(() => import('./NoResults.vue'));
|
const NoResults = defineAsyncComponent(() => import('./NoResults.vue'));
|
||||||
|
|
||||||
const IconDetailOverlay = defineAsyncComponent(() => import('./IconDetailOverlay.vue'));
|
const IconDetailOverlay = defineAsyncComponent(() => import('./IconDetailOverlay.vue'));
|
||||||
|
|
||||||
|
function handleCloseDrawer() {
|
||||||
|
setActiveIconName('');
|
||||||
|
|
||||||
|
window.history.pushState({}, '', '/icons/categories');
|
||||||
|
}
|
||||||
|
|
||||||
|
watchEffect(() => {
|
||||||
|
|
||||||
|
console.log(props.icons.find((icon) => icon.name === 'burger'));
|
||||||
|
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<StickyBar class="search-bar category-search">
|
<div ref="overviewEl" class="overview-container">
|
||||||
|
<StickyBar class="category-search">
|
||||||
<InputSearch
|
<InputSearch
|
||||||
:placeholder="`Search ${icons.length} icons ...`"
|
:placeholder="`Search ${icons.length} icons ...`"
|
||||||
v-model="searchQuery"
|
v-model="searchQuery"
|
||||||
@@ -98,19 +159,28 @@ const IconDetailOverlay = defineAsyncComponent(() => import('./IconDetailOverlay
|
|||||||
@focus="onFocusSearchInput"
|
@focus="onFocusSearchInput"
|
||||||
/>
|
/>
|
||||||
</StickyBar>
|
</StickyBar>
|
||||||
<NoResults v-if="categories.length === 0" :searchQuery="searchQuery" @clear="searchQuery = ''" />
|
<NoResults
|
||||||
|
v-if="categories.length === 0"
|
||||||
|
:searchQuery="searchQuery"
|
||||||
|
@clear="searchQuery = ''"
|
||||||
|
/>
|
||||||
|
<div v-bind="wrapperProps">
|
||||||
<IconsCategory
|
<IconsCategory
|
||||||
v-for="category in categories"
|
v-for="{ index, data } in list"
|
||||||
:key="category.name"
|
:categoryRow="data"
|
||||||
:category="category"
|
|
||||||
:activeIconName="activeIconName"
|
:activeIconName="activeIconName"
|
||||||
@setActiveIcon="setActiveIconName"
|
@setActiveIcon="setActiveIconName"
|
||||||
|
:key="index"
|
||||||
/>
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<IconDetailOverlay
|
<IconDetailOverlay
|
||||||
v-if="activeIconName != null"
|
v-if="activeIconName != null"
|
||||||
:iconName="activeIconName"
|
:iconName="activeIconName"
|
||||||
@close="setActiveIconName('')"
|
@close="handleCloseDrawer"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
<CarbonAdOverlay :drawerOpen="!!activeIconName" />
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
@@ -119,6 +189,21 @@ const IconDetailOverlay = defineAsyncComponent(() => import('./IconDetailOverlay
|
|||||||
}
|
}
|
||||||
|
|
||||||
.search-bar.category-search {
|
.search-bar.category-search {
|
||||||
margin-bottom: -54px;
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.title {
|
||||||
|
margin-bottom: 8px;
|
||||||
|
font-size: 19px;
|
||||||
|
font-weight: 500;
|
||||||
|
padding: 24px 0 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.icons {
|
||||||
|
margin-bottom: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.overview-container {
|
||||||
|
padding-bottom: 288px;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -1,15 +1,20 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref, computed, watch, defineAsyncComponent } from 'vue';
|
import { ref, computed, defineAsyncComponent, onMounted, watch } from 'vue';
|
||||||
import type { IconEntity } from '../../types';
|
import type { IconEntity } from '../../types';
|
||||||
import { useMediaQuery, useOffsetPagination } from '@vueuse/core';
|
import { useElementSize, useEventListener, useVirtualList } from '@vueuse/core';
|
||||||
import IconGrid from './IconGrid.vue';
|
import IconGrid from './IconGrid.vue';
|
||||||
import InputSearch from '../base/InputSearch.vue';
|
import InputSearch from '../base/InputSearch.vue';
|
||||||
import useSearch from '../../composables/useSearch';
|
import useSearch from '../../composables/useSearch';
|
||||||
import EndOfPage from '../base/EndOfPage.vue';
|
|
||||||
import useSearchInput from '../../composables/useSearchInput';
|
import useSearchInput from '../../composables/useSearchInput';
|
||||||
import StickyBar from './StickyBar.vue';
|
import StickyBar from './StickyBar.vue';
|
||||||
import useFetchTags from '../../composables/useFetchTags';
|
import useFetchTags from '../../composables/useFetchTags';
|
||||||
import useFetchCategories from '../../composables/useFetchCategories';
|
import useFetchCategories from '../../composables/useFetchCategories';
|
||||||
|
import chunkArray from '../../utils/chunkArray';
|
||||||
|
import CarbonAdOverlay from './CarbonAdOverlay.vue';
|
||||||
|
|
||||||
|
const ICON_SIZE = 56;
|
||||||
|
const ICON_GRID_GAP = 8;
|
||||||
|
const DEFAULT_GRID_ITEMS = 10 * 160;
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
icons: IconEntity[];
|
icons: IconEntity[];
|
||||||
@@ -17,32 +22,16 @@ const props = defineProps<{
|
|||||||
|
|
||||||
const activeIconName = ref(null);
|
const activeIconName = ref(null);
|
||||||
|
|
||||||
const isExtraLargeScreen = useMediaQuery('(min-width: 1440px)');
|
|
||||||
const isLargeScreen = useMediaQuery('(min-width: 1280px)');
|
|
||||||
const isMediumScreen = useMediaQuery('(min-width: 960px)');
|
|
||||||
const isSmallScreen = useMediaQuery('(min-width: 640px)');
|
|
||||||
|
|
||||||
const pageSize = computed(() => {
|
|
||||||
if (isExtraLargeScreen.value) {
|
|
||||||
return 16 * 20;
|
|
||||||
}
|
|
||||||
if (isLargeScreen.value) {
|
|
||||||
return 16 * 12;
|
|
||||||
}
|
|
||||||
if (isMediumScreen.value) {
|
|
||||||
return 13 * 12;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isSmallScreen.value) {
|
|
||||||
return 10 * 10;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 10 * 5;
|
|
||||||
});
|
|
||||||
|
|
||||||
const { execute: fetchTags, data: tags } = useFetchTags();
|
const { execute: fetchTags, data: tags } = useFetchTags();
|
||||||
const { execute: fetchCategories, data: categories } = useFetchCategories();
|
const { execute: fetchCategories, data: categories } = useFetchCategories();
|
||||||
|
|
||||||
|
const overviewEl = ref<HTMLElement | null>(null);
|
||||||
|
const { width: containerWidth } = useElementSize(overviewEl)
|
||||||
|
|
||||||
|
const columnSize = computed(() => {
|
||||||
|
return Math.floor((containerWidth.value) / ((ICON_SIZE + ICON_GRID_GAP)));
|
||||||
|
});
|
||||||
|
|
||||||
const mappedIcons = computed(() => {
|
const mappedIcons = computed(() => {
|
||||||
if (tags.value == null) {
|
if (tags.value == null) {
|
||||||
return props.icons;
|
return props.icons;
|
||||||
@@ -63,26 +52,33 @@ const mappedIcons = computed(() => {
|
|||||||
const { searchInput, searchQuery, searchQueryDebounced } = useSearchInput();
|
const { searchInput, searchQuery, searchQueryDebounced } = useSearchInput();
|
||||||
const searchResults = useSearch(searchQueryDebounced, mappedIcons, [
|
const searchResults = useSearch(searchQueryDebounced, mappedIcons, [
|
||||||
{ name: 'name', weight: 3 },
|
{ name: 'name', weight: 3 },
|
||||||
|
{ name: 'aliases', weight: 3 },
|
||||||
{ name: 'tags', weight: 2 },
|
{ name: 'tags', weight: 2 },
|
||||||
{ name: 'categories', weight: 1 },
|
{ name: 'categories', weight: 1 },
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const { next, currentPage } = useOffsetPagination({ pageSize });
|
const chunkedIcons = computed(() => {
|
||||||
|
return chunkArray(searchResults.value, columnSize.value);
|
||||||
const paginatedIcons = computed(() => {
|
|
||||||
const end = pageSize.value * currentPage.value;
|
|
||||||
|
|
||||||
return searchResults.value.slice(0, end);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const { list, containerProps, wrapperProps, scrollTo } = useVirtualList(
|
||||||
|
chunkedIcons,
|
||||||
|
{
|
||||||
|
itemHeight: ICON_SIZE + ICON_GRID_GAP,
|
||||||
|
overscan: 10
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
containerProps.ref.value = document.documentElement;
|
||||||
|
useEventListener(window, 'scroll', containerProps.onScroll)
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
function setActiveIconName(name: string) {
|
function setActiveIconName(name: string) {
|
||||||
activeIconName.value = name;
|
activeIconName.value = name;
|
||||||
}
|
}
|
||||||
|
|
||||||
watch(searchQueryDebounced, (searchString) => {
|
|
||||||
currentPage.value = 1;
|
|
||||||
});
|
|
||||||
|
|
||||||
function onFocusSearchInput() {
|
function onFocusSearchInput() {
|
||||||
if (tags.value == null) {
|
if (tags.value == null) {
|
||||||
fetchTags();
|
fetchTags();
|
||||||
@@ -95,9 +91,20 @@ function onFocusSearchInput() {
|
|||||||
const NoResults = defineAsyncComponent(() => import('./NoResults.vue'));
|
const NoResults = defineAsyncComponent(() => import('./NoResults.vue'));
|
||||||
|
|
||||||
const IconDetailOverlay = defineAsyncComponent(() => import('./IconDetailOverlay.vue'));
|
const IconDetailOverlay = defineAsyncComponent(() => import('./IconDetailOverlay.vue'));
|
||||||
|
|
||||||
|
watch(searchQueryDebounced, () => {
|
||||||
|
scrollTo(0)
|
||||||
|
})
|
||||||
|
|
||||||
|
function handleCloseDrawer() {
|
||||||
|
setActiveIconName('');
|
||||||
|
|
||||||
|
window.history.pushState({}, '', '/icons/');
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
<div ref="overviewEl" class="overview-container">
|
||||||
<StickyBar>
|
<StickyBar>
|
||||||
<InputSearch
|
<InputSearch
|
||||||
:placeholder="`Search ${icons.length} icons ...`"
|
:placeholder="`Search ${icons.length} icons ...`"
|
||||||
@@ -108,30 +115,45 @@ const IconDetailOverlay = defineAsyncComponent(() => import('./IconDetailOverlay
|
|||||||
/>
|
/>
|
||||||
</StickyBar>
|
</StickyBar>
|
||||||
<NoResults
|
<NoResults
|
||||||
v-if="paginatedIcons.length === 0"
|
v-if="list.length === 0 && searchQuery !== ''"
|
||||||
:searchQuery="searchQuery"
|
:searchQuery="searchQuery"
|
||||||
@clear="searchQuery = ''"
|
@clear="searchQuery = ''"
|
||||||
/>
|
/>
|
||||||
<IconGrid
|
<IconGrid
|
||||||
|
v-else-if="list.length === 0"
|
||||||
|
:key="index"
|
||||||
overlayMode
|
overlayMode
|
||||||
|
:icons="[...searchResults].splice(0, DEFAULT_GRID_ITEMS)"
|
||||||
:activeIcon="activeIconName"
|
:activeIcon="activeIconName"
|
||||||
:icons="paginatedIcons"
|
|
||||||
@setActiveIcon="setActiveIconName"
|
@setActiveIcon="setActiveIconName"
|
||||||
/>
|
/>
|
||||||
<EndOfPage @end-of-page="next" class="bottom-page" />
|
<div
|
||||||
<IconDetailOverlay
|
v-bind="wrapperProps"
|
||||||
v-if="activeIconName != null"
|
class="icon"
|
||||||
:iconName="activeIconName"
|
v-else
|
||||||
@close="setActiveIconName('')"
|
>
|
||||||
|
<IconGrid
|
||||||
|
v-for="{ index, data: icons } in list"
|
||||||
|
:key="index"
|
||||||
|
overlayMode
|
||||||
|
:icons="icons"
|
||||||
|
:activeIcon="activeIconName"
|
||||||
|
@setActiveIcon="setActiveIconName"
|
||||||
/>
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<IconDetailOverlay
|
||||||
|
:iconName="activeIconName"
|
||||||
|
@close="handleCloseDrawer"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<CarbonAdOverlay :drawerOpen="!!activeIconName" />
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
.icons {
|
.icons {
|
||||||
display: grid;
|
margin-bottom: 8px;
|
||||||
grid-template-columns: repeat(auto-fill, minmax(56px, 1fr));
|
|
||||||
gap: 8px;
|
|
||||||
width: 100%;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.icon {
|
.icon {
|
||||||
@@ -142,7 +164,7 @@ const IconDetailOverlay = defineAsyncComponent(() => import('./IconDetailOverlay
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.bottom-page {
|
.overview-container {
|
||||||
height: 288px;
|
padding-bottom: 288px;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -1,9 +1,10 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import {ref} from 'vue'
|
import { ref, onMounted, computed } from 'vue'
|
||||||
import {bird} from '../../../data/iconNodes'
|
import { bird, squirrel, rabbit } from '../../../data/iconNodes'
|
||||||
import createLucideIcon from 'lucide-vue-next/src/createLucideIcon'
|
import createLucideIcon from 'lucide-vue-next/src/createLucideIcon'
|
||||||
import {useEventListener} from '@vueuse/core'
|
import {useEventListener} from '@vueuse/core'
|
||||||
import VPButton from 'vitepress/dist/client/theme-default/components/VPButton.vue'
|
import VPButton from 'vitepress/dist/client/theme-default/components/VPButton.vue'
|
||||||
|
import { IconNode } from '../../types'
|
||||||
|
|
||||||
defineProps<{
|
defineProps<{
|
||||||
searchQuery: string
|
searchQuery: string
|
||||||
@@ -11,29 +12,45 @@ defineProps<{
|
|||||||
|
|
||||||
defineEmits(['clear'])
|
defineEmits(['clear'])
|
||||||
|
|
||||||
const birdIcon = ref<HTMLElement>()
|
const animalIcon = ref<HTMLElement>()
|
||||||
const Bird = createLucideIcon('bird', bird)
|
const randomAnimal = computed<IconNode>(() => {
|
||||||
|
return Math.random() > 0.5 ? squirrel : Math.random() > 0.5 ? rabbit : bird
|
||||||
|
})
|
||||||
|
const animalComponent = computed(() => createLucideIcon('animal', randomAnimal.value))
|
||||||
const flip = ref(false)
|
const flip = ref(false)
|
||||||
|
|
||||||
useEventListener(document, 'mousemove', (mouseEvent) => {
|
onMounted(() => {
|
||||||
const {width, height, x, y} = birdIcon.value.getBoundingClientRect()
|
useEventListener(document, 'mousemove', (mouseEvent) => {
|
||||||
|
const {width, height, x, y} = animalIcon.value.getBoundingClientRect()
|
||||||
|
|
||||||
const centerX = (width / 2) + x
|
const centerX = (width / 2) + x
|
||||||
|
|
||||||
flip.value = mouseEvent.x < centerX
|
flip.value = mouseEvent.x < centerX
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="no-results">
|
<div class="no-results">
|
||||||
<Bird class="bird-icon" ref="birdIcon" :class="{ flip }" :strokeWidth="1"/>
|
<component
|
||||||
|
:is="animalComponent"
|
||||||
|
class="animal-icon"
|
||||||
|
ref="animalIcon"
|
||||||
|
:class="{ flip }"
|
||||||
|
:strokeWidth="1"
|
||||||
|
/>
|
||||||
<h2 class="no-results-text">
|
<h2 class="no-results-text">
|
||||||
No icons found for '{{ searchQuery }}'
|
No icons found for '{{ searchQuery }}'
|
||||||
</h2>
|
</h2>
|
||||||
<VPButton text="Clear your search and try again" theme="alt" @click="$emit('clear')"/>
|
<VPButton
|
||||||
|
text="Clear your search and try again"
|
||||||
|
theme="alt"
|
||||||
|
@click="$emit('clear')"
|
||||||
|
/>
|
||||||
<span class="text-divider">or</span>
|
<span class="text-divider">or</span>
|
||||||
<VPButton text="Search on Github issues"
|
<VPButton
|
||||||
|
text="Search on Github issues"
|
||||||
theme="alt"
|
theme="alt"
|
||||||
:href="`https://github.com/lucide-icons/lucide/issues?q=is%3Aopen+${searchQuery}`"
|
:href="`https://github.com/lucide-icons/lucide/issues?q=is%3Aopen+${searchQuery}`"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
@@ -48,7 +65,7 @@ useEventListener(document, 'mousemove', (mouseEvent) => {
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.bird-icon {
|
.animal-icon {
|
||||||
width: 160px;
|
width: 160px;
|
||||||
height: 160px;
|
height: 160px;
|
||||||
color: var(--vp-c-neutral);
|
color: var(--vp-c-neutral);
|
||||||
@@ -56,12 +73,12 @@ useEventListener(document, 'mousemove', (mouseEvent) => {
|
|||||||
margin-top: 72px;
|
margin-top: 72px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.bird-icon.flip {
|
.animal-icon.flip {
|
||||||
transform: rotateY(180deg);
|
transform: rotateY(180deg);
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (min-width: 960px) {
|
@media (min-width: 960px) {
|
||||||
.bird-icon {
|
.animal-icon {
|
||||||
width: 240px;
|
width: 240px;
|
||||||
height: 240px;
|
height: 240px;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,29 +1,20 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import type { IconEntity } from '../../types'
|
import type { IconEntity } from '../../types';
|
||||||
import IconGrid from './IconGrid.vue'
|
import IconGrid from './IconGrid.vue';
|
||||||
|
|
||||||
defineProps<{
|
defineProps<{
|
||||||
icons: IconEntity[]
|
icons: IconEntity[];
|
||||||
}>()
|
}>();
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<section class="related-icons">
|
<section class="related-icons">
|
||||||
<h2 class="title">
|
<h2 class="title">More icons like this</h2>
|
||||||
Related Icons
|
<IconGrid :icons="icons" />
|
||||||
</h2>
|
|
||||||
<IconGrid
|
|
||||||
:icons="icons"
|
|
||||||
/>
|
|
||||||
</section>
|
</section>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.title {
|
|
||||||
margin-bottom: 24px;
|
|
||||||
font-size: 19px;
|
|
||||||
font-weight: 500;
|
|
||||||
}
|
|
||||||
|
|
||||||
.related-icons {
|
.related-icons {
|
||||||
margin-bottom: 32px;
|
margin-bottom: 32px;
|
||||||
}
|
}
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user