mirror of
https://github.com/lucide-icons/lucide.git
synced 2025-12-17 15:57:42 +01:00
Compare commits
357 Commits
studio/bar
...
fix/fixed-
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a8f578fa8b | ||
|
|
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 |
@@ -8,6 +8,8 @@ squircle
|
|||||||
strikethrough
|
strikethrough
|
||||||
touchpad
|
touchpad
|
||||||
ungroup
|
ungroup
|
||||||
|
pilcrow
|
||||||
|
toc
|
||||||
|
|
||||||
# Brands
|
# Brands
|
||||||
codepen
|
codepen
|
||||||
|
|||||||
@@ -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',
|
||||||
|
|||||||
3
.github/ISSUE_TEMPLATE/02_bug_report.yml
vendored
3
.github/ISSUE_TEMPLATE/02_bug_report.yml
vendored
@@ -69,6 +69,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
|
||||||
|
|||||||
2
.github/pull_request_template.md
vendored
2
.github/pull_request_template.md
vendored
@@ -47,7 +47,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. -->
|
||||||
|
|||||||
2
.github/workflows/ci.yml
vendored
2
.github/workflows/ci.yml
vendored
@@ -17,8 +17,6 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
- uses: pnpm/action-setup@v2
|
- uses: pnpm/action-setup@v2
|
||||||
with:
|
|
||||||
version: 8
|
|
||||||
- uses: actions/setup-node@v4
|
- uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
node-version: 18
|
node-version: 18
|
||||||
|
|||||||
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@v3
|
||||||
|
|
||||||
|
- 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")
|
||||||
|
|
||||||
|
# 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 }}
|
||||||
2
.github/workflows/linting.yml
vendored
2
.github/workflows/linting.yml
vendored
@@ -11,8 +11,6 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
- uses: pnpm/action-setup@v2
|
- uses: pnpm/action-setup@v2
|
||||||
with:
|
|
||||||
version: 8
|
|
||||||
- uses: actions/setup-node@v4
|
- uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
node-version: 18
|
node-version: 18
|
||||||
|
|||||||
17
.github/workflows/lucide-angular.yml
vendored
17
.github/workflows/lucide-angular.yml
vendored
@@ -8,13 +8,11 @@ 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@v2
|
||||||
with:
|
|
||||||
version: 8
|
|
||||||
- uses: actions/setup-node@v4
|
- uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
node-version: 18
|
node-version: 18
|
||||||
@@ -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@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
|
- name: Test
|
||||||
run: pnpm --filter lucide-angular test
|
run: pnpm --filter lucide-angular test
|
||||||
|
|||||||
2
.github/workflows/lucide-font.yml
vendored
2
.github/workflows/lucide-font.yml
vendored
@@ -13,8 +13,6 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
- uses: pnpm/action-setup@v2
|
- uses: pnpm/action-setup@v2
|
||||||
with:
|
|
||||||
version: 8
|
|
||||||
- uses: actions/setup-node@v4
|
- uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
node-version: 18
|
node-version: 18
|
||||||
|
|||||||
6
.github/workflows/lucide-preact.yml
vendored
6
.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
|
||||||
@@ -14,8 +15,6 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
- uses: pnpm/action-setup@v2
|
- uses: pnpm/action-setup@v2
|
||||||
with:
|
|
||||||
version: 8
|
|
||||||
- uses: actions/setup-node@v4
|
- uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
node-version: 18
|
node-version: 18
|
||||||
@@ -24,8 +23,5 @@ jobs:
|
|||||||
- 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
|
||||||
|
|||||||
6
.github/workflows/lucide-react-native.yml
vendored
6
.github/workflows/lucide-react-native.yml
vendored
@@ -4,6 +4,7 @@ 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
|
||||||
@@ -14,8 +15,6 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
- uses: pnpm/action-setup@v2
|
- uses: pnpm/action-setup@v2
|
||||||
with:
|
|
||||||
version: 8
|
|
||||||
- uses: actions/setup-node@v4
|
- uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
node-version: 18
|
node-version: 18
|
||||||
@@ -24,8 +23,5 @@ jobs:
|
|||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: pnpm install --frozen-lockfile
|
run: pnpm install --frozen-lockfile
|
||||||
|
|
||||||
- name: Build
|
|
||||||
run: pnpm --filter lucide-react-native build
|
|
||||||
|
|
||||||
- name: Test
|
- name: Test
|
||||||
run: pnpm --filter lucide-react-native test
|
run: pnpm --filter lucide-react-native test
|
||||||
|
|||||||
18
.github/workflows/lucide-react.yml
vendored
18
.github/workflows/lucide-react.yml
vendored
@@ -4,19 +4,18 @@ 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@v2
|
||||||
with:
|
|
||||||
version: 8
|
|
||||||
- uses: actions/setup-node@v4
|
- uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
node-version: 18
|
node-version: 18
|
||||||
@@ -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@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
|
- 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@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-react test
|
||||||
18
.github/workflows/lucide-solid.yml
vendored
18
.github/workflows/lucide-solid.yml
vendored
@@ -4,18 +4,17 @@ 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@v2
|
||||||
with:
|
|
||||||
version: 8
|
|
||||||
- uses: actions/setup-node@v4
|
- uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
node-version: 18
|
node-version: 18
|
||||||
@@ -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@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
|
- name: Test
|
||||||
run: pnpm --filter lucide-solid test
|
run: pnpm --filter lucide-solid test
|
||||||
|
|||||||
2
.github/workflows/lucide-static.yml
vendored
2
.github/workflows/lucide-static.yml
vendored
@@ -13,8 +13,6 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
- uses: pnpm/action-setup@v2
|
- uses: pnpm/action-setup@v2
|
||||||
with:
|
|
||||||
version: 8
|
|
||||||
- uses: actions/setup-node@v4
|
- uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
node-version: 18
|
node-version: 18
|
||||||
|
|||||||
18
.github/workflows/lucide-svelte.yml
vendored
18
.github/workflows/lucide-svelte.yml
vendored
@@ -4,18 +4,17 @@ 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@v2
|
||||||
with:
|
|
||||||
version: 8
|
|
||||||
- uses: actions/setup-node@v4
|
- uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
node-version: 18
|
node-version: 18
|
||||||
@@ -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@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
|
- name: Test
|
||||||
run: pnpm --filter lucide-svelte test
|
run: pnpm --filter lucide-svelte test
|
||||||
|
|||||||
18
.github/workflows/lucide-vue-next.yml
vendored
18
.github/workflows/lucide-vue-next.yml
vendored
@@ -4,18 +4,17 @@ 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@v2
|
||||||
with:
|
|
||||||
version: 8
|
|
||||||
- uses: actions/setup-node@v4
|
- uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
node-version: 18
|
node-version: 18
|
||||||
@@ -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@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
|
- name: Test
|
||||||
run: pnpm --filter lucide-vue-next test
|
run: pnpm --filter lucide-vue-next test
|
||||||
|
|||||||
18
.github/workflows/lucide-vue.yml
vendored
18
.github/workflows/lucide-vue.yml
vendored
@@ -4,18 +4,17 @@ on:
|
|||||||
pull_request:
|
pull_request:
|
||||||
paths:
|
paths:
|
||||||
- packages/lucide-vue/**
|
- packages/lucide-vue/**
|
||||||
|
- packages/shared/**
|
||||||
- tools/build-icons/**
|
- tools/build-icons/**
|
||||||
- tools/rollup-plugins/**
|
- tools/rollup-plugins/**
|
||||||
- pnpm-lock.yaml
|
- pnpm-lock.yaml
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
lucide-vue:
|
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@v2
|
||||||
with:
|
|
||||||
version: 8
|
|
||||||
- uses: actions/setup-node@v4
|
- uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
node-version: 18
|
node-version: 18
|
||||||
@@ -27,5 +26,18 @@ jobs:
|
|||||||
- name: Build
|
- name: Build
|
||||||
run: pnpm --filter lucide-vue build
|
run: pnpm --filter lucide-vue 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
|
- name: Test
|
||||||
run: pnpm --filter lucide-vue test
|
run: pnpm --filter lucide-vue test
|
||||||
|
|||||||
17
.github/workflows/lucide.yml
vendored
17
.github/workflows/lucide.yml
vendored
@@ -9,13 +9,11 @@ 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@v2
|
||||||
with:
|
|
||||||
version: 8
|
|
||||||
- uses: actions/setup-node@v4
|
- uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
node-version: 18
|
node-version: 18
|
||||||
@@ -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@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
|
- name: Test
|
||||||
run: pnpm --filter lucide test
|
run: pnpm --filter lucide test
|
||||||
|
|||||||
16
.github/workflows/pull-request.yml
vendored
16
.github/workflows/pull-request.yml
vendored
@@ -3,7 +3,7 @@ name: Add Changed Icons comment
|
|||||||
on:
|
on:
|
||||||
pull_request_target:
|
pull_request_target:
|
||||||
paths:
|
paths:
|
||||||
- 'icons/*.svg'
|
- 'icons/*'
|
||||||
branches:
|
branches:
|
||||||
- main
|
- main
|
||||||
- fix-icon-preview
|
- fix-icon-preview
|
||||||
@@ -68,6 +68,16 @@ jobs:
|
|||||||
# input: +++ b/icons/accessibility.json%0A@@ -2,0 +3 @@%0A+ "contributors": ["hi"],%0A@@ -13 +14 @@%0A+}%0A
|
# 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
|
# 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
|
||||||
|
|
||||||
|
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 '"
|
||||||
|
|
||||||
generate-changed-icons-comment:
|
generate-changed-icons-comment:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
permissions:
|
permissions:
|
||||||
@@ -94,6 +104,10 @@ jobs:
|
|||||||
comment-author: 'github-actions[bot]'
|
comment-author: 'github-actions[bot]'
|
||||||
body-includes: Added or changed icons
|
body-includes: Added or changed icons
|
||||||
|
|
||||||
|
- uses: actions/setup-node@v4
|
||||||
|
- name: Install svgson for code preview (safer and faster than installing all deps)
|
||||||
|
run: npm install svgson
|
||||||
|
|
||||||
- name: Generate comment markup
|
- name: Generate comment markup
|
||||||
run: node ./scripts/generateChangedIconsCommentMarkup.mjs >> comment-markup.md
|
run: node ./scripts/generateChangedIconsCommentMarkup.mjs >> comment-markup.md
|
||||||
id: comment-markup
|
id: comment-markup
|
||||||
|
|||||||
6
.github/workflows/release.yml
vendored
6
.github/workflows/release.yml
vendored
@@ -56,8 +56,6 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
- uses: pnpm/action-setup@v2
|
- uses: pnpm/action-setup@v2
|
||||||
with:
|
|
||||||
version: 8
|
|
||||||
- uses: actions/setup-node@v4
|
- uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
node-version: 18
|
node-version: 18
|
||||||
@@ -89,8 +87,6 @@ jobs:
|
|||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
- uses: actions/download-artifact@v3
|
- uses: actions/download-artifact@v3
|
||||||
- uses: pnpm/action-setup@v2
|
- uses: pnpm/action-setup@v2
|
||||||
with:
|
|
||||||
version: 8
|
|
||||||
- uses: actions/setup-node@v4
|
- uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
node-version: 18
|
node-version: 18
|
||||||
@@ -121,8 +117,6 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
- uses: pnpm/action-setup@v2
|
- uses: pnpm/action-setup@v2
|
||||||
with:
|
|
||||||
version: 8
|
|
||||||
- uses: actions/setup-node@v4
|
- uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
node-version: 18
|
node-version: 18
|
||||||
|
|||||||
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
|
||||||
|
|||||||
@@ -39,6 +39,8 @@ You can also [download an Adobe Illustrator template](https://github.com/lucide-
|
|||||||
|
|
||||||
#### [Figma Guide](https://lucide.dev/docs/figma-guide)
|
#### [Figma Guide](https://lucide.dev/docs/figma-guide)
|
||||||
|
|
||||||
|
#### [Affinity Designer Guide](https://lucide.dev/guide/design/affinity-designer-guide)
|
||||||
|
|
||||||
### Submitting Multiple Icons
|
### Submitting Multiple Icons
|
||||||
|
|
||||||
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.
|
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.
|
||||||
@@ -70,7 +72,7 @@ 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).
|
||||||
@@ -125,7 +127,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 builded the package first.
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
# in packages/lucide-react
|
# in packages/lucide-react
|
||||||
|
|||||||
275
README.md
275
README.md
@@ -1,185 +1,46 @@
|
|||||||
<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/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) |
|
||||||
- [Usage](#usage)
|
|
||||||
- [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 +50,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,7 +62,7 @@ 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
|
||||||
|
|
||||||
@@ -274,9 +73,13 @@ Thank you to all the people who contributed to Lucide!
|
|||||||
|
|
||||||
## 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": "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": "Notifications",
|
"title": "Notification",
|
||||||
"icon": "triangle-alert"
|
"icon": "triangle-alert"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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,6 +111,22 @@
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"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-static": {
|
"lucide-static": {
|
||||||
"order": 8,
|
"order": 8,
|
||||||
"icon": "svg",
|
"icon": "svg",
|
||||||
@@ -158,16 +142,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
|
||||||
@@ -301,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"
|
||||||
@@ -340,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,17 @@ 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 Static',
|
text: 'Lucide Static',
|
||||||
link: '/guide/packages/lucide-static',
|
link: '/guide/packages/lucide-static',
|
||||||
@@ -117,6 +121,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>
|
||||||
|
|||||||
@@ -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;
|
||||||
} */
|
} */
|
||||||
|
|||||||
@@ -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,7 +10,7 @@ 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 } in data.packages"
|
||||||
@@ -34,14 +35,6 @@ const { go } = useRouter()
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style scoped>
|
<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;
|
|
||||||
}
|
|
||||||
.packages-list {
|
.packages-list {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
|
|||||||
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>
|
||||||
@@ -6,6 +6,7 @@ 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'
|
import { useCategoryView } from '../../composables/useCategoryView'
|
||||||
|
|
||||||
const { page } = useData()
|
const { page } = useData()
|
||||||
@@ -46,10 +47,13 @@ watch(headers, () => {
|
|||||||
|
|
||||||
<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">
|
||||||
@@ -62,17 +66,20 @@ watch(headers, () => {
|
|||||||
</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 {
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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"
|
||||||
|
|||||||
@@ -7,6 +7,8 @@ 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'
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
icon: IconEntity
|
icon: IconEntity
|
||||||
@@ -20,13 +22,21 @@ 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)
|
||||||
</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>
|
||||||
|
</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 +54,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 +77,27 @@ 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;
|
||||||
|
}
|
||||||
|
|
||||||
.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>
|
||||||
@@ -19,7 +19,7 @@ export type CategoryRow = CategoryNameRow | CategoryIconsRow;
|
|||||||
import IconGrid from './IconGrid.vue'
|
import IconGrid from './IconGrid.vue'
|
||||||
|
|
||||||
defineProps<{
|
defineProps<{
|
||||||
activeIconName: string
|
activeIconName: string | null
|
||||||
categoryRow: CategoryRow
|
categoryRow: CategoryRow
|
||||||
}>()
|
}>()
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref, computed, defineAsyncComponent, onMounted } 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';
|
||||||
@@ -12,6 +12,7 @@ import { useElementSize, useEventListener, useVirtualList } from '@vueuse/core';
|
|||||||
import chunkArray from '../../utils/chunkArray';
|
import chunkArray from '../../utils/chunkArray';
|
||||||
import { CategoryRow } from './IconsCategory.vue';
|
import { CategoryRow } from './IconsCategory.vue';
|
||||||
import useScrollToCategory from '../../composables/useScrollToCategory';
|
import useScrollToCategory from '../../composables/useScrollToCategory';
|
||||||
|
import CarbonAdOverlay from './CarbonAdOverlay.vue';
|
||||||
|
|
||||||
const ICON_SIZE = 56;
|
const ICON_SIZE = 56;
|
||||||
const ICON_GRID_GAP = 8;
|
const ICON_GRID_GAP = 8;
|
||||||
@@ -68,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);
|
||||||
});
|
});
|
||||||
@@ -133,6 +134,18 @@ 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>
|
||||||
@@ -164,8 +177,10 @@ const IconDetailOverlay = defineAsyncComponent(() => import('./IconDetailOverlay
|
|||||||
<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>
|
||||||
|
|||||||
@@ -10,9 +10,11 @@ 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 chunkArray from '../../utils/chunkArray';
|
||||||
|
import CarbonAdOverlay from './CarbonAdOverlay.vue';
|
||||||
|
|
||||||
const ICON_SIZE = 56;
|
const ICON_SIZE = 56;
|
||||||
const ICON_GRID_GAP = 8;
|
const ICON_GRID_GAP = 8;
|
||||||
|
const DEFAULT_GRID_ITEMS = 10 * 160;
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
icons: IconEntity[];
|
icons: IconEntity[];
|
||||||
@@ -93,6 +95,12 @@ const IconDetailOverlay = defineAsyncComponent(() => import('./IconDetailOverlay
|
|||||||
watch(searchQueryDebounced, () => {
|
watch(searchQueryDebounced, () => {
|
||||||
scrollTo(0)
|
scrollTo(0)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
function handleCloseDrawer() {
|
||||||
|
setActiveIconName('');
|
||||||
|
|
||||||
|
window.history.pushState({}, '', '/icons/');
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
@@ -107,11 +115,23 @@ watch(searchQueryDebounced, () => {
|
|||||||
/>
|
/>
|
||||||
</StickyBar>
|
</StickyBar>
|
||||||
<NoResults
|
<NoResults
|
||||||
v-if="list.length === 0"
|
v-if="list.length === 0 && searchQuery !== ''"
|
||||||
:searchQuery="searchQuery"
|
:searchQuery="searchQuery"
|
||||||
@clear="searchQuery = ''"
|
@clear="searchQuery = ''"
|
||||||
/>
|
/>
|
||||||
<div v-bind="wrapperProps" class="icon">
|
<IconGrid
|
||||||
|
v-else-if="list.length === 0"
|
||||||
|
:key="index"
|
||||||
|
overlayMode
|
||||||
|
:icons="[...searchResults].splice(0, DEFAULT_GRID_ITEMS)"
|
||||||
|
:activeIcon="activeIconName"
|
||||||
|
@setActiveIcon="setActiveIconName"
|
||||||
|
/>
|
||||||
|
<div
|
||||||
|
v-bind="wrapperProps"
|
||||||
|
class="icon"
|
||||||
|
v-else
|
||||||
|
>
|
||||||
<IconGrid
|
<IconGrid
|
||||||
v-for="{ index, data: icons } in list"
|
v-for="{ index, data: icons } in list"
|
||||||
:key="index"
|
:key="index"
|
||||||
@@ -124,10 +144,11 @@ watch(searchQueryDebounced, () => {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<IconDetailOverlay
|
<IconDetailOverlay
|
||||||
v-if="activeIconName != null"
|
|
||||||
:iconName="activeIconName"
|
:iconName="activeIconName"
|
||||||
@close="setActiveIconName('')"
|
@close="handleCloseDrawer"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
<CarbonAdOverlay :drawerOpen="!!activeIconName" />
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,47 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import Checkbox from '../base/Checkbox.vue'
|
||||||
|
import SidebarTitle from './SidebarTitle.vue'
|
||||||
|
import { useExternalLibs } from '../../composables/useExternalLibs';
|
||||||
|
import { ExternalLibs } from '../../types';
|
||||||
|
|
||||||
|
interface ExternalLibrary {
|
||||||
|
name: string;
|
||||||
|
value: ExternalLibs;
|
||||||
|
}
|
||||||
|
|
||||||
|
const externalLibraries: ExternalLibrary[] = [
|
||||||
|
{
|
||||||
|
name: 'Lab',
|
||||||
|
value: 'lab'
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
const { selectedLibs } = useExternalLibs();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="external-library-select">
|
||||||
|
<SidebarTitle>
|
||||||
|
Include external libs
|
||||||
|
</SidebarTitle>
|
||||||
|
<ul>
|
||||||
|
<li
|
||||||
|
v-for="library in externalLibraries"
|
||||||
|
:key="library.name"
|
||||||
|
>
|
||||||
|
<Checkbox
|
||||||
|
:label="library.name"
|
||||||
|
:id="library.name"
|
||||||
|
v-model="selectedLibs"
|
||||||
|
:value="library.value"
|
||||||
|
/>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.external-library-select {
|
||||||
|
margin-bottom: 24px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
19
docs/.vitepress/theme/components/icons/SidebarTitle.vue
Normal file
19
docs/.vitepress/theme/components/icons/SidebarTitle.vue
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
<template>
|
||||||
|
<h2 class="sidebar-title sidebar-text">
|
||||||
|
<slot />
|
||||||
|
</h2>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.sidebar-title {
|
||||||
|
font-weight: 700;
|
||||||
|
color: var(--vp-c-text-1);
|
||||||
|
}
|
||||||
|
.sidebar-text {
|
||||||
|
line-height: 24px;
|
||||||
|
font-size: 14px;
|
||||||
|
display: block;
|
||||||
|
transition: color 0.25s;
|
||||||
|
padding: 4px 0;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -23,8 +23,8 @@ const links = computed(() => [
|
|||||||
href: `${githubLink.value}/releases`
|
href: `${githubLink.value}/releases`
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
text: 'Github',
|
text: 'GitHub',
|
||||||
href: `${githubLink.value}/issues`
|
href: `${githubLink.value}`
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
text: 'Issues',
|
text: 'Issues',
|
||||||
|
|||||||
@@ -5,9 +5,10 @@ import fetchPackages from '../../../lib/fetchPackages';
|
|||||||
export default {
|
export default {
|
||||||
async load() {
|
async load() {
|
||||||
const packages = await fetchPackages();
|
const packages = await fetchPackages();
|
||||||
|
|
||||||
return {
|
return {
|
||||||
packages: packages
|
packages: packages
|
||||||
.filter((p) => p.name in packageData)
|
.filter((p) => p?.name != null && p.name in packageData)
|
||||||
.map((pData) => ({
|
.map((pData) => ({
|
||||||
...pData,
|
...pData,
|
||||||
...packageData[pData.name],
|
...packageData[pData.name],
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import {data} from './PackageList.data'
|
import { data } from './PackageList.data'
|
||||||
import GridSection from '../base/GridSection.vue'
|
import GridSection from '../base/GridSection.vue'
|
||||||
import PackageListItem from "./PackageListItem.vue";</script>
|
import PackageListItem from "./PackageListItem.vue";
|
||||||
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<GridSection
|
<GridSection
|
||||||
@@ -38,33 +39,4 @@ import PackageListItem from "./PackageListItem.vue";</script>
|
|||||||
.package-group {
|
.package-group {
|
||||||
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>
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ const props = defineProps<{
|
|||||||
<img v-if="packageData.iconDark" :src="packageData.iconDark" alt="" class="package-icon dark" :class="packageData.iconClass" />
|
<img v-if="packageData.iconDark" :src="packageData.iconDark" alt="" class="package-icon dark" :class="packageData.iconClass" />
|
||||||
</div>
|
</div>
|
||||||
<div class="package-title">
|
<div class="package-title">
|
||||||
<h2 class="title">{{ props.packageData.name }}</h2>
|
<h2 class="title">{{ props.packageData?.name }}</h2>
|
||||||
<a v-for="shield in props.packageData.shields" :href="shield.href" class="package-shield" rel="noreferrer noopener">
|
<a v-for="shield in props.packageData.shields" :href="shield.href" class="package-shield" rel="noreferrer noopener">
|
||||||
<img :src="shield.src" :alt="shield.href" />
|
<img :src="shield.src" :alt="shield.href" />
|
||||||
</a>
|
</a>
|
||||||
|
|||||||
@@ -40,33 +40,4 @@ import ShowcaseListItem from "./ShowcaseListItem.vue";
|
|||||||
.package-group {
|
.package-group {
|
||||||
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>
|
||||||
|
|||||||
57
docs/.vitepress/theme/composables/useExternalLibs.ts
Normal file
57
docs/.vitepress/theme/composables/useExternalLibs.ts
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
import { ref, inject, Ref, watch } from 'vue';
|
||||||
|
import { ExternalLibs, IconEntity } from '../types';
|
||||||
|
|
||||||
|
export const EXTERNAL_LIBS_CONTEXT = Symbol('externalLibs');
|
||||||
|
|
||||||
|
type ExternalIconNodes = Partial<Record<ExternalLibs, IconEntity[]>>;
|
||||||
|
|
||||||
|
interface ExternalLibContext {
|
||||||
|
selectedLibs: Ref<[ExternalLibs]>;
|
||||||
|
externalIconNodes: Ref<ExternalIconNodes>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const externalLibContext = {
|
||||||
|
selectedLibs: ref([]),
|
||||||
|
externalIconNodes: ref({}),
|
||||||
|
};
|
||||||
|
|
||||||
|
const externalLibIconNodesAPI = {
|
||||||
|
lab: 'https://lab.lucide.dev/api/icon-details',
|
||||||
|
};
|
||||||
|
|
||||||
|
export function useExternalLibs(): ExternalLibContext {
|
||||||
|
const context = inject<ExternalLibContext>(EXTERNAL_LIBS_CONTEXT);
|
||||||
|
|
||||||
|
watch(context?.selectedLibs, async (selectedLibs) => {
|
||||||
|
const savedIconNodes = { ...context?.externalIconNodes.value };
|
||||||
|
const newExternalIconNodes: ExternalIconNodes = {};
|
||||||
|
|
||||||
|
try {
|
||||||
|
for (const lib of selectedLibs) {
|
||||||
|
if (savedIconNodes[lib]) {
|
||||||
|
newExternalIconNodes[lib] = savedIconNodes[lib];
|
||||||
|
} else {
|
||||||
|
const response = await fetch(externalLibIconNodesAPI[lib]);
|
||||||
|
const iconNodes = await response.json();
|
||||||
|
|
||||||
|
if (iconNodes) {
|
||||||
|
newExternalIconNodes[lib] = Object.values(iconNodes).map((iconEntity: IconEntity) => ({
|
||||||
|
...iconEntity,
|
||||||
|
externalLibrary: lib,
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
context.externalIconNodes.value = newExternalIconNodes;
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!context) {
|
||||||
|
throw new Error('useExternalLibs must be used with externalLibs context');
|
||||||
|
}
|
||||||
|
|
||||||
|
return context;
|
||||||
|
}
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
import { computed } from 'vue';
|
||||||
|
import { useExternalLibs } from '~/.vitepress/theme/composables/useExternalLibs';
|
||||||
|
import { IconEntity } from '../types';
|
||||||
|
|
||||||
|
const useIconsWithExternalLibs = (initialIcons?: IconEntity[]) => {
|
||||||
|
const { externalIconNodes } = useExternalLibs();
|
||||||
|
|
||||||
|
return computed(() => {
|
||||||
|
let icons = [];
|
||||||
|
|
||||||
|
if (initialIcons) {
|
||||||
|
icons = icons.concat(initialIcons);
|
||||||
|
}
|
||||||
|
|
||||||
|
const externalIconNodesArray = Object.values(externalIconNodes.value);
|
||||||
|
|
||||||
|
if (externalIconNodesArray?.length) {
|
||||||
|
externalIconNodesArray.forEach((iconNodes) => {
|
||||||
|
if (iconNodes?.length) {
|
||||||
|
icons = icons.concat(iconNodes);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return icons;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
export default useIconsWithExternalLibs;
|
||||||
@@ -7,6 +7,7 @@ import HomeHeroIconsCard from './components/home/HomeHeroIconsCard.vue';
|
|||||||
import HomeHeroBefore from './components/home/HomeHeroBefore.vue';
|
import HomeHeroBefore from './components/home/HomeHeroBefore.vue';
|
||||||
import { ICON_STYLE_CONTEXT, iconStyleContext } from './composables/useIconStyle';
|
import { ICON_STYLE_CONTEXT, iconStyleContext } from './composables/useIconStyle';
|
||||||
import { CATEGORY_VIEW_CONTEXT, categoryViewContext } from './composables/useCategoryView';
|
import { CATEGORY_VIEW_CONTEXT, categoryViewContext } from './composables/useCategoryView';
|
||||||
|
import { EXTERNAL_LIBS_CONTEXT, externalLibContext } from './composables/useExternalLibs';
|
||||||
|
|
||||||
const theme: Partial<Theme> = {
|
const theme: Partial<Theme> = {
|
||||||
extends: DefaultTheme,
|
extends: DefaultTheme,
|
||||||
@@ -20,6 +21,7 @@ const theme: Partial<Theme> = {
|
|||||||
enhanceApp({ app }) {
|
enhanceApp({ app }) {
|
||||||
app.provide(ICON_STYLE_CONTEXT, iconStyleContext);
|
app.provide(ICON_STYLE_CONTEXT, iconStyleContext);
|
||||||
app.provide(CATEGORY_VIEW_CONTEXT, categoryViewContext);
|
app.provide(CATEGORY_VIEW_CONTEXT, categoryViewContext);
|
||||||
|
app.provide(EXTERNAL_LIBS_CONTEXT, externalLibContext);
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import { useData } from 'vitepress'
|
|||||||
|
|
||||||
import CategoryList from '../components/icons/CategoryList.vue'
|
import CategoryList from '../components/icons/CategoryList.vue'
|
||||||
import SidebarIconCustomizer from '../components/icons/SidebarIconCustomizer.vue'
|
import SidebarIconCustomizer from '../components/icons/SidebarIconCustomizer.vue'
|
||||||
|
import ExternalLibrarySelect from '../components/icons/SidebarExternalLibrarySelect.vue'
|
||||||
|
|
||||||
const { page } = useData()
|
const { page } = useData()
|
||||||
|
|
||||||
@@ -11,6 +12,7 @@ const { page } = useData()
|
|||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<SidebarIconCustomizer v-if="page?.relativePath?.startsWith?.('icons')"/>
|
<SidebarIconCustomizer v-if="page?.relativePath?.startsWith?.('icons')"/>
|
||||||
|
<ExternalLibrarySelect v-if="page?.relativePath?.startsWith?.('icons')"/>
|
||||||
<CategoryList v-if="page?.relativePath?.startsWith?.('icons')"/>
|
<CategoryList v-if="page?.relativePath?.startsWith?.('icons')"/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -1,13 +1,18 @@
|
|||||||
export type IconNode = [elementName: string, attrs: Record<string, string>][];
|
export type IconNode = [elementName: string, attrs: Record<string, string>][];
|
||||||
export type IconNodeWithKeys = [elementName: string, attrs: Record<string, string>, key: string][];
|
export type IconNodeWithKeys = [elementName: string, attrs: Record<string, string>, key: string][];
|
||||||
|
|
||||||
export interface IconEntity {
|
export interface IconMetaData {
|
||||||
name: string;
|
|
||||||
tags: string[];
|
tags: string[];
|
||||||
categories: string[];
|
categories: string[];
|
||||||
contributors: string[];
|
contributors: string[];
|
||||||
aliases?: string[];
|
aliases?: string[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export type ExternalLibs = 'lab';
|
||||||
|
export interface IconEntity extends IconMetaData {
|
||||||
|
name: string;
|
||||||
iconNode: IconNode;
|
iconNode: IconNode;
|
||||||
|
externalLibrary?: ExternalLibs;
|
||||||
createdRelease?: Release;
|
createdRelease?: Release;
|
||||||
changedRelease?: Release;
|
changedRelease?: Release;
|
||||||
}
|
}
|
||||||
|
|||||||
8
docs/.vitepress/vue-shim.d.ts
vendored
8
docs/.vitepress/vue-shim.d.ts
vendored
@@ -1,5 +1,7 @@
|
|||||||
|
import { IconNode } from 'lucide-vue-next/src/createLucideIcon';
|
||||||
|
import Vue from 'vue';
|
||||||
|
|
||||||
declare module '*.vue' {
|
declare module '*.vue' {
|
||||||
import Vue from 'vue';
|
|
||||||
export default Vue;
|
export default Vue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -16,3 +18,7 @@ declare const resvg_wasm: RequestInfo | URL | Response | BufferSource | WebAssem
|
|||||||
declare module 'node:module' {
|
declare module 'node:module' {
|
||||||
function createRequire(filename: string): NodeRequire;
|
function createRequire(filename: string): NodeRequire;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
declare module '*.node.json' {
|
||||||
|
export default IconNode;
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,4 +1,215 @@
|
|||||||
|
---
|
||||||
|
title: Accessibility
|
||||||
|
---
|
||||||
|
|
||||||
# Accessibility
|
# Accessibility
|
||||||
|
|
||||||
<!-- Description how you should use svg icons keeping web accessible -->
|
Icons are pictures that show what something means without using words. They can be very helpful
|
||||||
<!-- See @JanTrichter comment about some information to write this: https://github.com/lucide-icons/lucide/pull/1521#discussion_r1332141390 -->
|
because they can quickly give information.
|
||||||
|
|
||||||
|
However, not everyone can understand them easily. When using icons it is very important to consider
|
||||||
|
the following aspects of accessibility.
|
||||||
|
|
||||||
|
## Provide visible labels
|
||||||
|
|
||||||
|
Icons are a helpful tool to improve perception, but they aren't a replacement for text.
|
||||||
|
|
||||||
|
In most cases, it is probably a good idea to also provide a textual representation of your icon's
|
||||||
|
function.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
## Contrast
|
||||||
|
|
||||||
|
Ensure there's enough contrast between the icon and its background so that it's visible to people
|
||||||
|
with low vision or color vision deficiencies.
|
||||||
|
|
||||||
|
We recommend
|
||||||
|
following [WCAG 2.1 SC 1.4.3](https://www.w3.org/WAI/WCAG21/Understanding/contrast-minimum.html).
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
## Use of color
|
||||||
|
|
||||||
|
Avoid relying solely on color to convey meaning in icons, as some users may have color blindness.
|
||||||
|
Instead, use additional visual cues like shape, shading or text.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
## Interactivity
|
||||||
|
|
||||||
|
Ensure that interactive icons are accessible via keyboard navigation and provide clear feedback when
|
||||||
|
activated.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
In most cases this is easily done by wrapping them in icon buttons.
|
||||||
|
|
||||||
|
## Minimum target size
|
||||||
|
|
||||||
|
Small targets can be difficult to click or touch, if your icon is interactive, we recommend that it
|
||||||
|
should have a minimum target size of 44×44 pixels.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
In practice, this doesn't necessarily mean that the icon itself should be this large, only its
|
||||||
|
interactive wrapper element.
|
||||||
|
|
||||||
|
## Meaningfulness
|
||||||
|
|
||||||
|
Icons should represent concepts or actions in a universally understandable way. Avoid using abstract
|
||||||
|
or ambiguous, or culture-specific symbols that might confuse some users.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
## Consistency
|
||||||
|
|
||||||
|
Maintain consistency in icon design and usage across your interface to help users learn and
|
||||||
|
understand their meanings more easily.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
## Text Alternatives
|
||||||
|
|
||||||
|
You may have to provide text labels or alternative text descriptions for icons, especially for
|
||||||
|
screen readers used by people with visual impairments.
|
||||||
|
|
||||||
|
However: descriptions should only be provided to standalone icons that aren't purely decorative, as
|
||||||
|
providing accessible names to non-functional elements only increases clutter when using screen
|
||||||
|
readers.
|
||||||
|
|
||||||
|
### On standalone icons
|
||||||
|
|
||||||
|
Icons are usually very unlikely to stand on their own with no semantically meaningful wrapper
|
||||||
|
element. In most cases they will be part of a badge, button (including icon buttons), navigation
|
||||||
|
item or other interactive UI element.
|
||||||
|
|
||||||
|
::: warning
|
||||||
|
In case some of your icons stand alone, and they serve a non-decorative function, make sure to
|
||||||
|
provide the appropriate accessible label for them.
|
||||||
|
:::
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
In general try to avoid using functional icons with no interactivity, we recommend that:
|
||||||
|
|
||||||
|
1) you either add a visible description next to them, or
|
||||||
|
2) place them in badges, labels or on buttons, and at least add a tooltip to them.
|
||||||
|
|
||||||
|
In any such case, it is preferred that the accessible name be provided for these interactive
|
||||||
|
elements (badges, buttons, nav items etc.) only, _not_ the icons themselves.
|
||||||
|
|
||||||
|
### On buttons
|
||||||
|
|
||||||
|
Do not provide an accessible label to icons when used on a button, as this label will be read out by
|
||||||
|
screen readers, leading to nonsensical text.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
::: details Code examples
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
// Don't do this
|
||||||
|
<button>
|
||||||
|
<Plus aria-label="Plus icon"/>
|
||||||
|
Add document
|
||||||
|
</button>
|
||||||
|
|
||||||
|
// Do this, just leave it
|
||||||
|
<button>
|
||||||
|
<Plus/>
|
||||||
|
Add document
|
||||||
|
</button>
|
||||||
|
```
|
||||||
|
|
||||||
|
:::
|
||||||
|
|
||||||
|
### On icon buttons
|
||||||
|
|
||||||
|
Icon buttons are buttons that do not contain any visible text apart from the icon itself (think of
|
||||||
|
the close button of a dialog for example).
|
||||||
|
|
||||||
|
As previously stated, you should provide your accessible label on the icon button itself, not the
|
||||||
|
contained icon.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
::: details Code examples
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
// Don't do this
|
||||||
|
<button class="btn-icon">
|
||||||
|
<Home/>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
// Don't do this either
|
||||||
|
<button class="btn-icon">
|
||||||
|
<Home aria-label="Home icon"/>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
// This works but might not be the best solution, see below
|
||||||
|
<button aria-label="Go to home" class="btn-icon">
|
||||||
|
<Home/>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
// Do this instead
|
||||||
|
<button class="btn-icon">
|
||||||
|
<Home/>
|
||||||
|
<span class="visually-hidden">Go to home</span>
|
||||||
|
</button>
|
||||||
|
```
|
||||||
|
|
||||||
|
:::
|
||||||
|
|
||||||
|
## A note on `aria-label`
|
||||||
|
|
||||||
|
Although you could provide accessible labels to your elements via the `aria-label` attribute, we
|
||||||
|
generally recommend avoiding this and instead suggest that you use your chosen CSS framework's "
|
||||||
|
visually hidden" utility whenever possible. You can
|
||||||
|
[read more about why `aria-label` might not be the best solution](https://gomakethings.com/revisting-aria-label-versus-a-visually-hidden-class/).
|
||||||
|
### Example - Radix UI
|
||||||
|
|
||||||
|
Use [Radix UI's built-in accessible icon utility component](https://www.radix-ui.com/primitives/docs/utilities/accessible-icon).
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
import { ArrowRightIcon } from 'lucide-react';
|
||||||
|
import { AccessibleIcon } from '@radix-ui/react-accessible-icon';
|
||||||
|
|
||||||
|
<AccessibleIcon label="Next item">
|
||||||
|
<ArrowRightIcon />
|
||||||
|
</AccessibleIcon>
|
||||||
|
```
|
||||||
|
### Example - Bootstrap
|
||||||
|
|
||||||
|
```html
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<i data-lucide="phone" aria-hidden="true"></i>
|
||||||
|
<span class="visually-hidden">Phone number</span>
|
||||||
|
</div>
|
||||||
|
```
|
||||||
|
|
||||||
|
### Example - Tailwind CSS
|
||||||
|
|
||||||
|
```html
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<i data-lucide="phone" aria-hidden="true"></i>
|
||||||
|
<span class="sr-only">Phone number</span>
|
||||||
|
</div>
|
||||||
|
```
|
||||||
|
|
||||||
|
If you're not sure, you may consider learning more
|
||||||
|
about [how to hide content.](https://www.a11yproject.com/posts/how-to-hide-content/)
|
||||||
|
|
||||||
|
## Further resources
|
||||||
|
|
||||||
|
We also recommend checking out the following resources about accessibility:
|
||||||
|
|
||||||
|
- [Web Content Accessibility Guidelines (WCAG) 2.1](https://www.w3.org/TR/WCAG21/)
|
||||||
|
- [Web Accessibility Initiative (WAI)](https://www.w3.org/WAI/)
|
||||||
|
- [Learn accessibility on web.dev](https://web.dev/learn/accessibility)
|
||||||
|
- [Inclusive Components](https://inclusive-components.design/)
|
||||||
|
- [A11yTalks](https://www.a11ytalks.com/)
|
||||||
|
- [A11y automation tracker](https://a11y-automation.dev/)
|
||||||
|
- [The A11Y Project](https://www.a11yproject.com/)
|
||||||
|
|||||||
93
docs/guide/advanced/aliased-names.md
Normal file
93
docs/guide/advanced/aliased-names.md
Normal file
@@ -0,0 +1,93 @@
|
|||||||
|
# Aliased Names
|
||||||
|
|
||||||
|
Icons can have multiple names for the same icon. This is because we choose to rename some icons to make them more consistent with the rest of the icon set, or the name was not generic. For example, the `edit-2` icon is renamed to `pen` to make the name more generic, since it is just a pen icon.
|
||||||
|
|
||||||
|
Beside aliases names lucide also includes prefixed and suffixed names to use within your project. This is to prevent import name collisions with other libraries or your own code.
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
// These are all the same icon
|
||||||
|
import {
|
||||||
|
Home,
|
||||||
|
HomeIcon,
|
||||||
|
LucideHome,
|
||||||
|
} from "lucide-react";
|
||||||
|
```
|
||||||
|
|
||||||
|
## Choosing import name style
|
||||||
|
|
||||||
|
To be consistent in your imports or want to change the autocompletion of Lucide icons in your IDE there an option to able the choose the import name style you want.
|
||||||
|
|
||||||
|
This can be done by creating a custom module declaration file to override the lucide imports and turning off the autocomplete in your IDE.
|
||||||
|
|
||||||
|
### Turn off autocomplete in your IDE
|
||||||
|
|
||||||
|
```json [.vscode/settings.json]
|
||||||
|
{
|
||||||
|
"typescript.preferences.autoImportFileExcludePatterns": [
|
||||||
|
"lucide-react", // or
|
||||||
|
"lucide-preact", // or
|
||||||
|
"lucide-react-native", // or
|
||||||
|
"lucide-vue-next",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Create a custom module declaration file
|
||||||
|
|
||||||
|
Only available for `lucide-react`, `lucide-preact`, `lucide-react-native`, `lucide-vue-next` package.
|
||||||
|
This will enable you to choose the import name style you want to use in your project.
|
||||||
|
|
||||||
|
::: code-group
|
||||||
|
|
||||||
|
```ts [React]
|
||||||
|
declare module "lucide-react" {
|
||||||
|
// Prefixed import names
|
||||||
|
export * from "lucide-react/dist/lucide-react.prefixed";
|
||||||
|
// or
|
||||||
|
// Suffixed import names
|
||||||
|
export * from "lucide-react/dist/lucide-react.suffixed";
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
```ts [Vue]
|
||||||
|
declare module "lucide-vue-next" {
|
||||||
|
// Prefixed import names
|
||||||
|
export * from "lucide-vue-next/dist/lucide-vue-next.prefixed";
|
||||||
|
// or
|
||||||
|
// Suffixed import names
|
||||||
|
export * from "lucide-vue-next/dist/lucide-vue-next.suffixed";
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
```ts [Preact]
|
||||||
|
declare module "lucide-preact" {
|
||||||
|
// Prefixed import names
|
||||||
|
export * from "lucide-preact/dist/lucide-preact.prefixed";
|
||||||
|
// or
|
||||||
|
// Suffixed import names
|
||||||
|
export * from "lucide-preact/dist/lucide-preact.suffixed";
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
```ts [React Native]
|
||||||
|
declare module "lucide-react-native" {
|
||||||
|
// Prefixed import names
|
||||||
|
export * from "lucide-react-native/dist/lucide-react-native.prefixed";
|
||||||
|
// or
|
||||||
|
// Suffixed import names
|
||||||
|
export * from "lucide-react-native/dist/lucide-react-native.suffixed";
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
:::
|
||||||
|
|
||||||
|
Place this in your project root or in a folder where your tsconfig.json is located, or locate it in your defined type directory.
|
||||||
|
Easiest way is to create a `@types` folder in your project root and name the file `[package-name].d.ts`.
|
||||||
|
|
||||||
|
### Import name styles
|
||||||
|
|
||||||
|
| Import Style | Available imports | Declaration file import |
|
||||||
|
| ------------- | --------------------------- | ----------------------- |
|
||||||
|
| Default | Home, HomeIcon, LucideHome | |
|
||||||
|
| Prefixed | LucideHome | [package].prefixed |
|
||||||
|
| Suffixed | HomeIcon | [package].suffixed |
|
||||||
18
docs/guide/design/affinity-designer-guide.md
Normal file
18
docs/guide/design/affinity-designer-guide.md
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
---
|
||||||
|
title: Affinity Designer Template Guide
|
||||||
|
---
|
||||||
|
|
||||||
|
# Affinity Designer Template Guide
|
||||||
|
|
||||||
|
This guide describes how to use the Affinity Designer template for Lucide.
|
||||||
|
|
||||||
|
## General Workflow
|
||||||
|
|
||||||
|
>Attention: By default, Affinity Designer sets the unit for stroke to points. Make sure that it is set to pixel. To do this, open `Preferences > User Interface`. Under `Decimal Places for Unit Types`, uncheck `Show Lines in points`.
|
||||||
|
|
||||||
|
1. Download and open the [Affinity Designer template](https://github.com/lucide-icons/lucide/blob/main/docs/public/templates/affinity_designer.aftemplate).
|
||||||
|
2. Follow the [Icon Design Principles](icon-design-guide.md) while you use the template (to ensure integrity with the Lucide icon pack).
|
||||||
|
3. Export the file as SVG (`File > Export`). Make sure that _Rastering_ is set to _Nothing_, _Export text as curves_ is checked (hopefully, you won't need this), _Use hex colors_ is checked, and _Flatten transforms_ is checked.
|
||||||
|
|
||||||
|

|
||||||
|
4. Optimize the exported SVG file further with [SVGOMG](https://jakearchibald.github.io/svgomg/) or [`svgo`](https://github.com/svg/svgo) (using `svgo --multipass exported_icon.svg`).
|
||||||
@@ -52,7 +52,7 @@ Here are rules that should be followed to keep quality and consistency when maki
|
|||||||
|
|
||||||

|

|
||||||
|
|
||||||
**Tip:** place your icon next to circle or square and blur them both; your icon should not feel much darker than the base shape.
|
**Tip:** place your icon next to the circle or square icon and blur them both; your icon should not feel much darker than the base shape.
|
||||||
|
|
||||||
### 10. Icons should be visually centered by their center of gravity.
|
### 10. Icons should be visually centered by their center of gravity.
|
||||||
|
|
||||||
@@ -76,7 +76,7 @@ Here are rules that should be followed to keep quality and consistency when maki
|
|||||||
|
|
||||||

|

|
||||||
|
|
||||||
**Tip:** make sure to use arcs or quadratic curves, when using cubic curves control points should have mirrored angles for smooth curves.
|
**Tip:** make sure to use arcs or quadratic curves. When using cubic curves control points should have mirrored angles for smooth curves.
|
||||||
|
|
||||||
### 13. Icons should aim to be pixel perfect so that they will be sharp on low DPI displays.
|
### 13. Icons should aim to be pixel perfect so that they will be sharp on low DPI displays.
|
||||||
|
|
||||||
@@ -109,8 +109,8 @@ Here are rules that should be followed to keep quality and consistency when maki
|
|||||||
7. Icons depicting multiple elements (e.g. a person and a circle) of different sizes must list these elements in decreasing order of size.\
|
7. Icons depicting multiple elements (e.g. a person and a circle) of different sizes must list these elements in decreasing order of size.\
|
||||||
For example: if the circle is bigger, it should be `circle-person`, if the person is bigger, it should be `person-circle`.
|
For example: if the circle is bigger, it should be `circle-person`, if the person is bigger, it should be `person-circle`.
|
||||||
|
|
||||||
8. Icons depicting multiple elements of roughly equal sizes (e.g. a `ruler` and a `pencil`) must list these elements in English reading order.\
|
8. Icons depicting multiple elements of roughly equal sizes (e.g. a `ruler` and a `pencil`) must list these elements front to back in case one element is in front of the other, otherwise in English reading order (top to bottom, left to right).\
|
||||||
For example: if the `pencil` is either above or left of `ruler`, it should be `pencil-ruler`, otherwise, it should be `ruler-pencil`.
|
For example: if the `pencil` is either in front of, above or left of `ruler`, it should be `pencil-ruler`, otherwise, it should be `ruler-pencil`.
|
||||||
|
|
||||||
9. Icons depicting some sort of variation of an element must use the `[element]-[modifier]` naming scheme, with modifiers being applied to each element respectively.\
|
9. Icons depicting some sort of variation of an element must use the `[element]-[modifier]` naming scheme, with modifiers being applied to each element respectively.\
|
||||||
For example: a dashed circle must be named `circle-dashed`, not `dashed-circle`, and in coordination with the previous guidelines, a dashed circle containing a broken heart would be named `circle-dashed-heart-broken`, due to the heart being smaller than the circle.
|
For example: a dashed circle must be named `circle-dashed`, not `dashed-circle`, and in coordination with the previous guidelines, a dashed circle containing a broken heart would be named `circle-dashed-heart-broken`, due to the heart being smaller than the circle.
|
||||||
@@ -142,7 +142,7 @@ For each icon these attributes are applied, corresponding to the above rules.
|
|||||||
### Minify paths
|
### Minify paths
|
||||||
|
|
||||||
The code of paths can sometimes get quite large. To reduce file size we like to minify the code.
|
The code of paths can sometimes get quite large. To reduce file size we like to minify the code.
|
||||||
We recommend to use the [SVGOMG](https://jakearchibald.github.io/svgomg/) to minify paths to 2 points of precision.
|
We recommend to use [SVGOMG](https://jakearchibald.github.io/svgomg/) to minify paths to 2 points of precision.
|
||||||
|
|
||||||
### Allowed elements
|
### Allowed elements
|
||||||
|
|
||||||
|
|||||||
@@ -12,7 +12,8 @@ Lucide is an open-source icon library that provides 1000+ vector (svg) files for
|
|||||||
## Available Icons
|
## Available Icons
|
||||||
|
|
||||||
Lucide contains icons with different variants and states, allowing users to choose the most suitable icon for their needs. And if a desired icon isn't available yet, users can open a design request, and the Lucide community contributors will help provide new icons. With more icons to choose from, users have more options to work with in their projects.
|
Lucide contains icons with different variants and states, allowing users to choose the most suitable icon for their needs. And if a desired icon isn't available yet, users can open a design request, and the Lucide community contributors will help provide new icons. With more icons to choose from, users have more options to work with in their projects.
|
||||||
Complete Set of Icons
|
|
||||||
|
### Complete Set of Icons
|
||||||
|
|
||||||
As new applications with specific features arise, Lucide aims to provide a complete set of icons for every project. The community follows a set of design rules when designing new icons. These rules maintain standards for the icons, such as recognizability, consistency in style, and readability at all sizes. While creativity is valued in new icons, recognizable design conventions are important to ensure that the icons are easily identifiable by users.
|
As new applications with specific features arise, Lucide aims to provide a complete set of icons for every project. The community follows a set of design rules when designing new icons. These rules maintain standards for the icons, such as recognizability, consistency in style, and readability at all sizes. While creativity is valued in new icons, recognizable design conventions are important to ensure that the icons are easily identifiable by users.
|
||||||
|
|
||||||
@@ -20,9 +21,15 @@ As new applications with specific features arise, Lucide aims to provide a compl
|
|||||||
|
|
||||||
In addition to design, code is also important. Assets like icons can significantly increase bandwidth usage in web projects. With the growing internet, Lucide has a responsibility to keep their assets as small as possible. To achieve this, Lucide uses SVG compression and specific code architecture for tree-shaking abilities. After tree-shaking, you only ship the icons you used, which helps to keep software distribution size to a minimum.
|
In addition to design, code is also important. Assets like icons can significantly increase bandwidth usage in web projects. With the growing internet, Lucide has a responsibility to keep their assets as small as possible. To achieve this, Lucide uses SVG compression and specific code architecture for tree-shaking abilities. After tree-shaking, you only ship the icons you used, which helps to keep software distribution size to a minimum.
|
||||||
|
|
||||||
|
## Accessibility
|
||||||
|
|
||||||
|
Icons are pictures that show what something means without using words. They can be very helpful because they can quickly give information.
|
||||||
|
|
||||||
|
However, not everyone can understand them easily. Read more about [how to use Lucide in an accessible way](./advanced/accessibility.md).
|
||||||
|
|
||||||
## Official Packages
|
## Official Packages
|
||||||
|
|
||||||
Lucide's official packages are designed to work on different platforms, making it easier for users to integrate icons into their projects. The packages are available for various technologies, including [Web (Vanilla)](https://lucide.dev/guide/packages/lucide), [React](https://lucide.dev/guide/packages/lucide-react), [React Native](https://lucide.dev/guide/packages/lucide-react-native), [Vue](https://lucide.dev/guide/packages/lucide-vue), [Vue 3](https://lucide.dev/guide/packages/lucide-vue-next), [Svelte](https://lucide.dev/guide/packages/lucide-svelte),[Preact](https://lucide.dev/guide/packages/lucide-preact), [Solid](https://lucide.dev/guide/packages/lucide-solid), [Angular](https://lucide.dev/guide/packages/lucide-angular), [NodeJS](https://lucide.dev/guide/packages/lucide-static#nodejs) and [Flutter](https://lucide.dev/guide/packages/lucide-flutter).
|
Lucide's official packages are designed to work on different platforms, making it easier for users to integrate icons into their projects. The packages are available for various technologies, including [Web (Vanilla)](https://lucide.dev/guide/packages/lucide), [React](https://lucide.dev/guide/packages/lucide-react), [React Native](https://lucide.dev/guide/packages/lucide-react-native), [Vue](https://lucide.dev/guide/packages/lucide-vue), [Vue 3](https://lucide.dev/guide/packages/lucide-vue-next), [Svelte](https://lucide.dev/guide/packages/lucide-svelte), [Preact](https://lucide.dev/guide/packages/lucide-preact), [Solid](https://lucide.dev/guide/packages/lucide-solid), [Angular](https://lucide.dev/guide/packages/lucide-angular), [NodeJS](https://lucide.dev/guide/packages/lucide-static#nodejs) and [Flutter](https://lucide.dev/guide/packages/lucide-flutter).
|
||||||
|
|
||||||
## Community
|
## Community
|
||||||
If you have any questions about Lucide, feel free to reach out to the community. You can find them on [GitHub](https://github.com/lucide-icons/lucide) and [Discord](https://discord.gg/EH6nSts).
|
If you have any questions about Lucide, feel free to reach out to the community. You can find them on [GitHub](https://github.com/lucide-icons/lucide) and [Discord](https://discord.gg/EH6nSts).
|
||||||
|
|||||||
@@ -22,6 +22,10 @@ yarn add lucide
|
|||||||
npm install lucide
|
npm install lucide
|
||||||
```
|
```
|
||||||
|
|
||||||
|
```sh [bun]
|
||||||
|
bun add lucide
|
||||||
|
```
|
||||||
|
|
||||||
:::
|
:::
|
||||||
|
|
||||||
For more details, see the [documentation](packages/lucide.md).
|
For more details, see the [documentation](packages/lucide.md).
|
||||||
@@ -44,6 +48,10 @@ yarn add lucide-react
|
|||||||
npm install lucide-react
|
npm install lucide-react
|
||||||
```
|
```
|
||||||
|
|
||||||
|
```sh [bun]
|
||||||
|
bun add lucide-react
|
||||||
|
```
|
||||||
|
|
||||||
:::
|
:::
|
||||||
|
|
||||||
For more details, see the [documentation](packages/lucide-react.md).
|
For more details, see the [documentation](packages/lucide-react.md).
|
||||||
@@ -67,6 +75,10 @@ yarn add lucide-vue-next
|
|||||||
npm install lucide-vue-next
|
npm install lucide-vue-next
|
||||||
```
|
```
|
||||||
|
|
||||||
|
```sh [bun]
|
||||||
|
bun add lucide-vue-next
|
||||||
|
```
|
||||||
|
|
||||||
:::
|
:::
|
||||||
|
|
||||||
For more details, see the [documentation](packages/lucide-vue-next.md).
|
For more details, see the [documentation](packages/lucide-vue-next.md).
|
||||||
@@ -90,6 +102,10 @@ yarn add lucide-svelte
|
|||||||
npm install lucide-svelte
|
npm install lucide-svelte
|
||||||
```
|
```
|
||||||
|
|
||||||
|
```sh [bun]
|
||||||
|
bun add lucide-svelte
|
||||||
|
```
|
||||||
|
|
||||||
:::
|
:::
|
||||||
|
|
||||||
For more details, see the [documentation](packages/lucide-svelte.md).
|
For more details, see the [documentation](packages/lucide-svelte.md).
|
||||||
@@ -112,6 +128,10 @@ yarn add lucide-solid
|
|||||||
npm install lucide-solid
|
npm install lucide-solid
|
||||||
```
|
```
|
||||||
|
|
||||||
|
```sh [bun]
|
||||||
|
bun add lucide-solid
|
||||||
|
```
|
||||||
|
|
||||||
:::
|
:::
|
||||||
|
|
||||||
For more details, see the [documentation](packages/lucide-solid.md).
|
For more details, see the [documentation](packages/lucide-solid.md).
|
||||||
@@ -134,6 +154,10 @@ yarn add lucide-angular
|
|||||||
npm install lucide-angular
|
npm install lucide-angular
|
||||||
```
|
```
|
||||||
|
|
||||||
|
```sh [bun]
|
||||||
|
bun add lucide-angular
|
||||||
|
```
|
||||||
|
|
||||||
:::
|
:::
|
||||||
|
|
||||||
For more details, see the [documentation](packages/lucide-angular.md).
|
For more details, see the [documentation](packages/lucide-angular.md).
|
||||||
@@ -156,6 +180,10 @@ yarn add lucide-preact
|
|||||||
npm install lucide-preact
|
npm install lucide-preact
|
||||||
```
|
```
|
||||||
|
|
||||||
|
```sh [bun]
|
||||||
|
bun add lucide-preact
|
||||||
|
```
|
||||||
|
|
||||||
:::
|
:::
|
||||||
|
|
||||||
## Static usage
|
## Static usage
|
||||||
@@ -176,6 +204,10 @@ yarn add lucide-static
|
|||||||
npm install lucide-static
|
npm install lucide-static
|
||||||
```
|
```
|
||||||
|
|
||||||
|
```sh [bun]
|
||||||
|
bun add lucide-static
|
||||||
|
```
|
||||||
|
|
||||||
:::
|
:::
|
||||||
|
|
||||||
For more details, see the [documentation](packages/lucide-static.md).
|
For more details, see the [documentation](packages/lucide-static.md).
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user