mirror of
https://github.com/lucide-icons/lucide.git
synced 2025-12-18 07:17:43 +01:00
Compare commits
210 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
27c0a136cd | ||
|
|
84b3c46b65 | ||
|
|
1a09e7fb39 | ||
|
|
75e9724072 | ||
|
|
fbaccc7d9f | ||
|
|
c24bc4d7ef | ||
|
|
5c8c8f4362 | ||
|
|
ffd2a62941 | ||
|
|
e77959e1a6 | ||
|
|
149ee36e61 | ||
|
|
88bf60b5d7 | ||
|
|
1e5df716a4 | ||
|
|
fc0ea760e5 | ||
|
|
c85275899a | ||
|
|
288edde1ea | ||
|
|
207ff6c487 | ||
|
|
a1a9a4d839 | ||
|
|
c5804ad9a5 | ||
|
|
c72fb4a28b | ||
|
|
da5ad547b5 | ||
|
|
66cfe527b3 | ||
|
|
d1866225ba | ||
|
|
372735999f | ||
|
|
f3a33346dd | ||
|
|
3373acf596 | ||
|
|
73d5bfc318 | ||
|
|
ddbc074aa3 | ||
|
|
8f4d6b1651 | ||
|
|
d8b08f8fda | ||
|
|
fddacb6260 | ||
|
|
3d0c8691c9 | ||
|
|
47998b05aa | ||
|
|
9a9e051343 | ||
|
|
6c6c8448fa | ||
|
|
49445aad3a | ||
|
|
70656eb4f0 | ||
|
|
930f862547 | ||
|
|
931b7f5376 | ||
|
|
81e44bdc40 | ||
|
|
e6e90944b9 | ||
|
|
f6fd369bfe | ||
|
|
bbf183fe48 | ||
|
|
4f5642b872 | ||
|
|
1dce6a141a | ||
|
|
dbfce919fc | ||
|
|
52adb78df8 | ||
|
|
c5cfbed28c | ||
|
|
1e4fd13852 | ||
|
|
0a0fd1cf6c | ||
|
|
487d03fc4d | ||
|
|
950160ad5a | ||
|
|
b6f5898aee | ||
|
|
a9c1dca801 | ||
|
|
c05c7e333f | ||
|
|
dff42fe326 | ||
|
|
c1f642e20f | ||
|
|
cf9565b69c | ||
|
|
4cc4468d2f | ||
|
|
fd9ab8f17a | ||
|
|
c9101f0f39 | ||
|
|
614ef1a1d5 | ||
|
|
1a441812ac | ||
|
|
4a33e90c65 | ||
|
|
062a64a078 | ||
|
|
95a1ea7255 | ||
|
|
a0a5bc8fc2 | ||
|
|
698eded89b | ||
|
|
a70b713572 | ||
|
|
34530ad805 | ||
|
|
f73aed151a | ||
|
|
2bd7748562 | ||
|
|
da8a6c5a1b | ||
|
|
5736028dfa | ||
|
|
45d2063340 | ||
|
|
f71d3ffd1d | ||
|
|
b8c3a5fa0b | ||
|
|
a4076db69b | ||
|
|
55cb681461 | ||
|
|
09d9bb747d | ||
|
|
42f9cdceca | ||
|
|
c652723b32 | ||
|
|
a44328d8be | ||
|
|
376568239f | ||
|
|
92d05b5fca | ||
|
|
27b5b7eaad | ||
|
|
4de1355e54 | ||
|
|
c8d94bf3e1 | ||
|
|
a128d1c3c1 | ||
|
|
e145cb05e2 | ||
|
|
759ff562fd | ||
|
|
ae2899a09e | ||
|
|
8b7ea73aa3 | ||
|
|
1bdeae5364 | ||
|
|
0e307087f6 | ||
|
|
a46114b3e7 | ||
|
|
fcafe0e7b7 | ||
|
|
5312982b8f | ||
|
|
3a13fab009 | ||
|
|
30a69ee670 | ||
|
|
5f442122ab | ||
|
|
e78d910a83 | ||
|
|
ccc8dc2b34 | ||
|
|
96bcca0e08 | ||
|
|
d95b14a70b | ||
|
|
a852a43ef4 | ||
|
|
4953a95e36 | ||
|
|
cad1b95b69 | ||
|
|
92f3fb0f90 | ||
|
|
6e8895d075 | ||
|
|
a1b2ce5b7b | ||
|
|
4a54e87e84 | ||
|
|
d8bdbff9c6 | ||
|
|
70cffa8dd2 | ||
|
|
8cff59627b | ||
|
|
b684a0083b | ||
|
|
9fb4b0b161 | ||
|
|
9ec40ae506 | ||
|
|
890514de6c | ||
|
|
9463b2e445 | ||
|
|
0221022e24 | ||
|
|
751f7cb1e3 | ||
|
|
4c90b84236 | ||
|
|
01be733532 | ||
|
|
4ffa38e013 | ||
|
|
0a38dccdae | ||
|
|
3391b5b717 | ||
|
|
5c145f4e72 | ||
|
|
74429a8e92 | ||
|
|
1e99499dc8 | ||
|
|
724a43e3f0 | ||
|
|
fb79059fca | ||
|
|
9a54838538 | ||
|
|
c7438c0c10 | ||
|
|
667ae303f8 | ||
|
|
dc1d17181f | ||
|
|
26abdb904d | ||
|
|
cf0264745e | ||
|
|
510a5ec3b9 | ||
|
|
e1bc19be4e | ||
|
|
062894e113 | ||
|
|
eaa99b35f6 | ||
|
|
7c22ccfab4 | ||
|
|
e0e171db81 | ||
|
|
3b11552e5e | ||
|
|
d8b455b614 | ||
|
|
79eecc89f6 | ||
|
|
b943430a08 | ||
|
|
cebb0ee84b | ||
|
|
210c56807e | ||
|
|
c2a8f31176 | ||
|
|
a3f70d5b8b | ||
|
|
c97c6ed9e4 | ||
|
|
e9d69c6948 | ||
|
|
270c935cd4 | ||
|
|
b7377d21eb | ||
|
|
7ccf155ad4 | ||
|
|
c696d1e907 | ||
|
|
a8cf24e75a | ||
|
|
4e2773bd2d | ||
|
|
7c8f898893 | ||
|
|
c3951d36c7 | ||
|
|
f958310d91 | ||
|
|
d00cbebcc4 | ||
|
|
3619dfa7f2 | ||
|
|
c844bc668f | ||
|
|
32dec05e0b | ||
|
|
5394d7fceb | ||
|
|
8dea4c7b7f | ||
|
|
b8a595275d | ||
|
|
a7b3ecde63 | ||
|
|
8bcfc225ce | ||
|
|
1d608db223 | ||
|
|
c1cb5d9bc2 | ||
|
|
66f51474cd | ||
|
|
af0b16bc10 | ||
|
|
46d6c3c119 | ||
|
|
d3b8510602 | ||
|
|
97e0f30627 | ||
|
|
24676ddc8e | ||
|
|
92689a3328 | ||
|
|
b578269ecb | ||
|
|
d041a2b02a | ||
|
|
0253326b17 | ||
|
|
275c2cbc69 | ||
|
|
4bd6a273db | ||
|
|
34155d48e7 | ||
|
|
82db590192 | ||
|
|
70be55b78f | ||
|
|
7163aeaa6b | ||
|
|
99cd76bb35 | ||
|
|
f5fb1ec263 | ||
|
|
6916aebee4 | ||
|
|
65d213264f | ||
|
|
ee77147aff | ||
|
|
3b7b74fe86 | ||
|
|
3a2f052ce9 | ||
|
|
cf34d61971 | ||
|
|
2814a63b8f | ||
|
|
4bcab462dc | ||
|
|
6c93bb97c7 | ||
|
|
3c1993c463 | ||
|
|
7a57c306c3 | ||
|
|
32637199f5 | ||
|
|
e490bc35b8 | ||
|
|
496058cc15 | ||
|
|
4ee46673af | ||
|
|
5a46f4b87c | ||
|
|
875e8a2d06 | ||
|
|
e006a171c1 | ||
|
|
606706e8e0 |
@@ -4,3 +4,7 @@ coverage
|
|||||||
lib
|
lib
|
||||||
tests
|
tests
|
||||||
node_modules
|
node_modules
|
||||||
|
.eslintrc.js
|
||||||
|
docs/images
|
||||||
|
docs/guide/basics/examples
|
||||||
|
packages/lucide-react/dynamicIconImports.js
|
||||||
|
|||||||
41
.eslintrc.js
41
.eslintrc.js
@@ -1,10 +1,13 @@
|
|||||||
|
const DEFAULT_ATTRS = require('./scripts/render/default-attrs.json');
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
|
root: true,
|
||||||
env: {
|
env: {
|
||||||
browser: true,
|
browser: true,
|
||||||
node: true,
|
node: true,
|
||||||
},
|
},
|
||||||
extends: ['airbnb-base', 'prettier'],
|
extends: ['airbnb-base', 'prettier'],
|
||||||
plugins: ['import', 'prettier'],
|
plugins: ['import', 'prettier', '@html-eslint'],
|
||||||
rules: {
|
rules: {
|
||||||
'no-console': 'off',
|
'no-console': 'off',
|
||||||
'no-param-reassign': 'off',
|
'no-param-reassign': 'off',
|
||||||
@@ -15,6 +18,7 @@ module.exports = {
|
|||||||
{
|
{
|
||||||
singleQuote: true,
|
singleQuote: true,
|
||||||
trailingComma: 'all',
|
trailingComma: 'all',
|
||||||
|
printWidth: 100
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
'import/no-extraneous-dependencies': [
|
'import/no-extraneous-dependencies': [
|
||||||
@@ -37,4 +41,39 @@ module.exports = {
|
|||||||
ecmaVersion: 'latest',
|
ecmaVersion: 'latest',
|
||||||
sourceType: 'module',
|
sourceType: 'module',
|
||||||
},
|
},
|
||||||
|
overrides: [
|
||||||
|
{
|
||||||
|
files: ['./icons/*.svg'],
|
||||||
|
parser: '@html-eslint/parser',
|
||||||
|
rules: {
|
||||||
|
'prettier/prettier': 'off',
|
||||||
|
'@html-eslint/require-doctype': 'off',
|
||||||
|
'@html-eslint/no-duplicate-attrs': 'error',
|
||||||
|
'@html-eslint/no-inline-styles': 'error',
|
||||||
|
'@html-eslint/require-attrs': [
|
||||||
|
'error',
|
||||||
|
...Object.entries(DEFAULT_ATTRS)
|
||||||
|
.map(([attr, value]) => ({ tag: 'svg', attr, value: String(value) }))
|
||||||
|
],
|
||||||
|
'@html-eslint/indent': ['error', 2],
|
||||||
|
"@html-eslint/no-multiple-empty-lines": ["error", { "max": 0 }],
|
||||||
|
'@html-eslint/no-extra-spacing-attrs': [
|
||||||
|
'error',
|
||||||
|
{
|
||||||
|
enforceBeforeSelfClose: true,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
'@html-eslint/require-closing-tags': [
|
||||||
|
'error',
|
||||||
|
{
|
||||||
|
selfClosing: 'always',
|
||||||
|
allowSelfClosingCustom: true,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
'@html-eslint/element-newline': 'error',
|
||||||
|
'@html-eslint/no-trailing-spaces': 'error',
|
||||||
|
'@html-eslint/quotes': 'error',
|
||||||
|
}
|
||||||
|
},
|
||||||
|
],
|
||||||
};
|
};
|
||||||
|
|||||||
49
.github/ISSUE_TEMPLATE/01_icon_request.yml
vendored
Normal file
49
.github/ISSUE_TEMPLATE/01_icon_request.yml
vendored
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
name: Icon request
|
||||||
|
description: Suggest a new icon for this project
|
||||||
|
labels: ['🙌 icon request']
|
||||||
|
body:
|
||||||
|
- type: markdown
|
||||||
|
attributes:
|
||||||
|
value: |
|
||||||
|
Before submitting an icon request check if it has already been requested. If there is an open request, please add a 👍.
|
||||||
|
|
||||||
|
**Important note**: No new brand logos are allowed, see https://github.com/lucide-icons/lucide/issues/670.
|
||||||
|
Existing brand icons will also be phased out. For brand icons, consider using https://simpleicons.org, which offers purpose-built SVGs that are also on a 24×24px grid.
|
||||||
|
- type: input
|
||||||
|
id: name
|
||||||
|
attributes:
|
||||||
|
label: Icon name
|
||||||
|
description: What should this icon depict? For multiple icons, provide a comma-separated list.
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
- type: textarea
|
||||||
|
id: use-cases
|
||||||
|
attributes:
|
||||||
|
label: Use cases
|
||||||
|
description: Why do you need this icon? Include at least two real-life use cases per requested icon, avoiding generic descriptions like "it's a car icon".
|
||||||
|
placeholder: e.g. I need a star icon to use in my rating system.
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
- type: textarea
|
||||||
|
id: design-ideas
|
||||||
|
attributes:
|
||||||
|
label: Design ideas
|
||||||
|
description: What should this icon look like? Provide simple, minimalistic icon examples from other sets or your own drafts to help us visualize your request.
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
- type: checkboxes
|
||||||
|
id: checklist
|
||||||
|
attributes:
|
||||||
|
label: Checklist
|
||||||
|
description: Please review the following checklist before submitting your request.
|
||||||
|
options:
|
||||||
|
- label: I have searched if someone has submitted a similar issue before and there weren't any. (Please make sure to also search closed issues, as this issue might already have been resolved.)
|
||||||
|
required: true
|
||||||
|
- label: I have searched existing icons to make sure it does not already exist and I didn't find any.
|
||||||
|
required: true
|
||||||
|
- label: I am not requesting a brand logo and the art is not protected by copyright.
|
||||||
|
required: true
|
||||||
|
- label: I am not requesting an icon that includes religious, political imagery or hate symbols.
|
||||||
|
required: true
|
||||||
|
- label: I have provided appropriate use cases for the icon(s) requested.
|
||||||
|
required: true
|
||||||
90
.github/ISSUE_TEMPLATE/02_bug_report.yml
vendored
Normal file
90
.github/ISSUE_TEMPLATE/02_bug_report.yml
vendored
Normal file
@@ -0,0 +1,90 @@
|
|||||||
|
name: Bug report
|
||||||
|
description: Create a report to help us improve
|
||||||
|
labels: ['🐛 bug']
|
||||||
|
body:
|
||||||
|
- type: markdown
|
||||||
|
attributes:
|
||||||
|
value: |
|
||||||
|
Before reporting an issue, please search to see if someone has filed a similar issue before. If there is already an open issue, please add a 👍 and/or leave a comment with additional information.
|
||||||
|
- type: checkboxes
|
||||||
|
id: packages
|
||||||
|
attributes:
|
||||||
|
label: Package
|
||||||
|
description: Which Lucide packages are affected? You may select more than one.
|
||||||
|
options:
|
||||||
|
- label: lucide
|
||||||
|
- label: lucide-angular
|
||||||
|
- label: lucide-flutter
|
||||||
|
- label: lucide-preact
|
||||||
|
- label: lucide-react
|
||||||
|
- label: lucide-react-native
|
||||||
|
- label: lucide-solid
|
||||||
|
- label: lucide-svelte
|
||||||
|
- label: lucide-vue
|
||||||
|
- label: lucide-vue-next
|
||||||
|
- label: Figma plugin
|
||||||
|
- label: source/main
|
||||||
|
- label: other/not relevant
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
- type: input
|
||||||
|
id: version
|
||||||
|
attributes:
|
||||||
|
label: Version
|
||||||
|
description: What version of Lucide are you running?
|
||||||
|
placeholder: e.g. 0.289.1
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
- type: checkboxes
|
||||||
|
id: browsers
|
||||||
|
attributes:
|
||||||
|
label: Browser
|
||||||
|
description: In which browser(s) are you experiencing the issue? You may select more than one.
|
||||||
|
options:
|
||||||
|
- label: Chrome/Chromium
|
||||||
|
- label: Firefox
|
||||||
|
- label: Safari
|
||||||
|
- label: Edge
|
||||||
|
- label: iOS Safari
|
||||||
|
- label: Opera
|
||||||
|
- label: Other/not relevant
|
||||||
|
validations:
|
||||||
|
required: false
|
||||||
|
- type: checkboxes
|
||||||
|
id: operating-systems
|
||||||
|
attributes:
|
||||||
|
label: Operating system
|
||||||
|
description: In which operating systems a you experiencing the issue? You may select more than one.
|
||||||
|
options:
|
||||||
|
- label: Windows
|
||||||
|
- label: Linux
|
||||||
|
- label: macOS
|
||||||
|
- label: Other/not relevant
|
||||||
|
- type: textarea
|
||||||
|
id: description
|
||||||
|
attributes:
|
||||||
|
label: Description
|
||||||
|
description: Try to describe in detail the problem you're running into and provide additional context about your working environment if necessary.
|
||||||
|
placeholder: e.g. When I do X, Y happens instead of Z
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
- type: textarea
|
||||||
|
id: steps-to-reproduce
|
||||||
|
attributes:
|
||||||
|
label: Steps to reproduce
|
||||||
|
description: Please provide a detailed guide on how this issue can be reproduced or a live example with a working reproduction on Codesandbox, JSFiddle or similar.
|
||||||
|
placeholder: |
|
||||||
|
1. Import `check` icon
|
||||||
|
2. Add to a React component/view
|
||||||
|
3. Run the react app
|
||||||
|
4. Notice that the `check` isn't rendering correctly which seems a encoding problem
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
- type: checkboxes
|
||||||
|
id: checklist
|
||||||
|
attributes:
|
||||||
|
label: Checklist
|
||||||
|
description: Please review the following checklist before submitting your issue.
|
||||||
|
options:
|
||||||
|
- label: I have searched if someone has submitted a similar issue before and there weren't any. (Please make sure to also search closed issues, as this issue might already have been resolved.)
|
||||||
|
required: true
|
||||||
62
.github/ISSUE_TEMPLATE/03_bug_report_site.yml
vendored
Normal file
62
.github/ISSUE_TEMPLATE/03_bug_report_site.yml
vendored
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
name: lucide.dev bug report
|
||||||
|
description: Help us improve the Lucide site
|
||||||
|
labels: ['🐛 bug', '🌍 site']
|
||||||
|
body:
|
||||||
|
- type: markdown
|
||||||
|
attributes:
|
||||||
|
value: |
|
||||||
|
Before reporting an issue, please search to see if someone has filed a similar issue before. If there is already an open issue, please add a 👍 and/or leave a comment with additional information.
|
||||||
|
- type: checkboxes
|
||||||
|
id: browsers
|
||||||
|
attributes:
|
||||||
|
label: Browser
|
||||||
|
description: In which browser(s) are you experiencing the issue? You may select more than one.
|
||||||
|
options:
|
||||||
|
- label: Chrome/Chromium
|
||||||
|
- label: Firefox
|
||||||
|
- label: Safari
|
||||||
|
- label: Edge
|
||||||
|
- label: iOS Safari
|
||||||
|
- label: Opera
|
||||||
|
- label: Other/not relevant
|
||||||
|
validations:
|
||||||
|
required: false
|
||||||
|
- type: checkboxes
|
||||||
|
id: operating-systems
|
||||||
|
attributes:
|
||||||
|
label: Operating system
|
||||||
|
description: In which operating systems are you experiencing the issue? You may select more than one.
|
||||||
|
options:
|
||||||
|
- label: Windows
|
||||||
|
- label: Linux
|
||||||
|
- label: macOS
|
||||||
|
- label: Other/not relevant
|
||||||
|
- type: textarea
|
||||||
|
id: description
|
||||||
|
attributes:
|
||||||
|
label: Description
|
||||||
|
description: Try to describe in detail the problem you're running into and provide additional context about your working environment if necessary.
|
||||||
|
placeholder: e.g. When I do X, Y happens instead of Z
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
- type: textarea
|
||||||
|
id: stepsToReproduce
|
||||||
|
attributes:
|
||||||
|
label: Steps to reproduce
|
||||||
|
description: Please provide a detailed guide on how this issue can be reproduced.
|
||||||
|
placeholder: |
|
||||||
|
1. I click on an icon
|
||||||
|
2. I click on `Copy SVG` in the drawer
|
||||||
|
3. I paste from the clipboard
|
||||||
|
4. A base64 encoded data URI is inserted.
|
||||||
|
...
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
- type: checkboxes
|
||||||
|
id: checklist
|
||||||
|
attributes:
|
||||||
|
label: Checklist
|
||||||
|
description: Please review the following checklist before submitting your issue.
|
||||||
|
options:
|
||||||
|
- label: I have searched if someone has submitted a similar issue before and there weren't any. (Please make sure to also search closed issues, as this issue might already have been resolved.)
|
||||||
|
required: true
|
||||||
53
.github/ISSUE_TEMPLATE/04_feature_request.yml
vendored
Normal file
53
.github/ISSUE_TEMPLATE/04_feature_request.yml
vendored
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
name: Feature request
|
||||||
|
description: Share with us your ideas on how Lucide could be improved upon.
|
||||||
|
labels: ['💡 idea']
|
||||||
|
body:
|
||||||
|
- type: markdown
|
||||||
|
attributes:
|
||||||
|
value: |
|
||||||
|
Before submitting a new feature request, please search to see if someone has filed a similar request before. If there is already an open issue, please add a 👍 and/or leave a comment with additional information.
|
||||||
|
- type: checkboxes
|
||||||
|
id: packages
|
||||||
|
attributes:
|
||||||
|
label: Package
|
||||||
|
description: Which Lucide project do you wish this feature were added to? You may select more than one.
|
||||||
|
options:
|
||||||
|
- label: lucide
|
||||||
|
- label: lucide-angular
|
||||||
|
- label: lucide-flutter
|
||||||
|
- label: lucide-preact
|
||||||
|
- label: lucide-react
|
||||||
|
- label: lucide-react-native
|
||||||
|
- label: lucide-solid
|
||||||
|
- label: lucide-svelte
|
||||||
|
- label: lucide-vue
|
||||||
|
- label: lucide-vue-next
|
||||||
|
- label: Figma plugin
|
||||||
|
- label: all JS packages
|
||||||
|
- label: site
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
- type: textarea
|
||||||
|
id: description
|
||||||
|
attributes:
|
||||||
|
label: Description
|
||||||
|
description: Try to describe in detail the feature you wish existed.
|
||||||
|
placeholder: e.g. I want to be able to set extra CSS classes on icon components.
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
- type: textarea
|
||||||
|
id: use-cases
|
||||||
|
attributes:
|
||||||
|
label: Use cases
|
||||||
|
description: Why do you need this feature? Provide real-life use cases as to why this feature will be useful for others.
|
||||||
|
placeholder: e.g. I could use the extra classes to add animation or global custom styling to some icons.
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
- type: checkboxes
|
||||||
|
id: checklist
|
||||||
|
attributes:
|
||||||
|
label: Checklist
|
||||||
|
description: Please check the following items before submitting your issue.
|
||||||
|
options:
|
||||||
|
- label: I have searched the existing issues to make sure this bug has not already been reported.
|
||||||
|
required: true
|
||||||
68
.github/ISSUE_TEMPLATE/bug_report.md
vendored
68
.github/ISSUE_TEMPLATE/bug_report.md
vendored
@@ -1,68 +0,0 @@
|
|||||||
---
|
|
||||||
name: Bug report
|
|
||||||
about: Create a report to help us improve
|
|
||||||
labels: "🐛 bug"
|
|
||||||
---
|
|
||||||
|
|
||||||
<!--
|
|
||||||
Before reporting an issue, please search to see if someone has filed a similar issue before. If there is already an open issue, please add a 👍 and/or leave a comment with additional information.
|
|
||||||
-->
|
|
||||||
|
|
||||||
## Prerequisites
|
|
||||||
|
|
||||||
* Version:
|
|
||||||
* Are you running from source/main:
|
|
||||||
* Are you using a released build:
|
|
||||||
* Operating system:
|
|
||||||
* Bits:
|
|
||||||
|
|
||||||
## Step to reproduce
|
|
||||||
|
|
||||||
*(Type here)*
|
|
||||||
|
|
||||||
### Actual behavior
|
|
||||||
|
|
||||||
## Any message or error
|
|
||||||
|
|
||||||
*(Type here)*
|
|
||||||
|
|
||||||
## Resources
|
|
||||||
|
|
||||||
* Links
|
|
||||||
* Screenshots
|
|
||||||
|
|
||||||
|
|
||||||
Here is what a great bug report would look like:
|
|
||||||
|
|
||||||
```
|
|
||||||
## Prerequisites
|
|
||||||
|
|
||||||
Version: Release v3.1.0
|
|
||||||
Running from: Import using webpack
|
|
||||||
Operating system: Mac OSX
|
|
||||||
Bits: 64 bits
|
|
||||||
|
|
||||||
## Step to reproduce
|
|
||||||
|
|
||||||
- Import `check` icon
|
|
||||||
- Add to a React component/view
|
|
||||||
- Run the react app
|
|
||||||
- Notice that the `check` isn't rendering correctly which seems a encoding problem
|
|
||||||
|
|
||||||
### Actual behavior:
|
|
||||||
|
|
||||||
- Import `check` icon
|
|
||||||
- Add to a React component/view
|
|
||||||
- Run the react app
|
|
||||||
- Check is displayed with correct encoding (e.g UTF-8)
|
|
||||||
|
|
||||||
## Any message or error
|
|
||||||
|
|
||||||
No console output
|
|
||||||
...
|
|
||||||
|
|
||||||
## Resources
|
|
||||||
|
|
||||||
No resources
|
|
||||||
...
|
|
||||||
```
|
|
||||||
18
.github/ISSUE_TEMPLATE/icon_request.md
vendored
18
.github/ISSUE_TEMPLATE/icon_request.md
vendored
@@ -1,18 +0,0 @@
|
|||||||
---
|
|
||||||
name: Icon request
|
|
||||||
about: Suggest an new icon for this project
|
|
||||||
labels: "🙌 icon request"
|
|
||||||
---
|
|
||||||
|
|
||||||
<!--
|
|
||||||
Before creating an icon request, please search to see if someone has requested the icon already. If there is an open request, please add a 👍.
|
|
||||||
A note about brand logos and related material : We follow the decision from Feather Icons (https://github.com/feathericons/feather/issues/763) to deprecate icons relating to brands.
|
|
||||||
You will find some in the set, but we won't add any new ones. https://simpleicons.org has 24x24 SVG icons for this purpose.
|
|
||||||
|
|
||||||
-->
|
|
||||||
|
|
||||||
## Icon Request
|
|
||||||
|
|
||||||
* Icon name:
|
|
||||||
* Use case:
|
|
||||||
* _Screenshots_ of similar icons:
|
|
||||||
15
.github/PULL_REQUEST_TEMPLATE/new-icon.md
vendored
15
.github/PULL_REQUEST_TEMPLATE/new-icon.md
vendored
@@ -1,15 +0,0 @@
|
|||||||
---
|
|
||||||
name: New icon
|
|
||||||
about: Add a new icon to the library
|
|
||||||
labels: "🎨 <icon"
|
|
||||||
---
|
|
||||||
|
|
||||||
<!-- Thanks for submitting an icon! Please make sure you read the icon design guide
|
|
||||||
at https://github.com/lucide-icons/lucide/blob/main/docs/icon-design-guide.md beforehand,
|
|
||||||
and please fill everything below. -->
|
|
||||||
|
|
||||||
- **Name of the icon** : <!-- `icon` -->
|
|
||||||
- **Tags (alternative names for this icon)** (add them in as a separate json file using the same icon name) :
|
|
||||||
- **What is the purpose of this icon?** : <!-- Shows that one can click it to... / Is used to denote or label... -->
|
|
||||||
- **100% scale preview** : <!-- upload an image -->
|
|
||||||
- **Have you considered alternative possibilities** for its naming or design? :
|
|
||||||
8
.github/actions/build-and-test.yml
vendored
8
.github/actions/build-and-test.yml
vendored
@@ -24,15 +24,15 @@ runs:
|
|||||||
- name: Get pnpm store directory
|
- name: Get pnpm store directory
|
||||||
id: pnpm-cache
|
id: pnpm-cache
|
||||||
run: |
|
run: |
|
||||||
echo "::set-output name=pnpm_cache_dir::$(pnpm store path)"
|
echo "STORE_PATH=$(pnpm store path)" >> $GITHUB_OUTPUT
|
||||||
|
|
||||||
- uses: actions/cache@v3
|
- uses: actions/cache@v3
|
||||||
name: Setup pnpm cache
|
name: Setup pnpm cache
|
||||||
with:
|
with:
|
||||||
path: ${{ steps.pnpm-cache.outputs.pnpm_cache_dir }}
|
path: ${{ steps.pnpm-cache.outputs.STORE_PATH }}
|
||||||
key: ${{ runner.os }}-lucide-preact-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}
|
key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}
|
||||||
restore-keys: |
|
restore-keys: |
|
||||||
${{ runner.os }}-lucide-preact-pnpm-store-
|
${{ runner.os }}-pnpm-store-
|
||||||
|
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: pnpm install --filter lucide-preact
|
run: pnpm install --filter lucide-preact
|
||||||
|
|||||||
8
.github/actions/check-icons.yml
vendored
8
.github/actions/check-icons.yml
vendored
@@ -24,15 +24,15 @@ runs:
|
|||||||
- name: Get pnpm store directory
|
- name: Get pnpm store directory
|
||||||
id: pnpm-cache
|
id: pnpm-cache
|
||||||
run: |
|
run: |
|
||||||
echo "::set-output name=pnpm_cache_dir::$(pnpm store path)"
|
echo "STORE_PATH=$(pnpm store path)" >> $GITHUB_OUTPUT
|
||||||
|
|
||||||
- uses: actions/cache@v3
|
- uses: actions/cache@v3
|
||||||
name: Setup pnpm cache
|
name: Setup pnpm cache
|
||||||
with:
|
with:
|
||||||
path: ${{ steps.pnpm-cache.outputs.pnpm_cache_dir }}
|
path: ${{ steps.pnpm-cache.outputs.STORE_PATH }}
|
||||||
key: ${{ runner.os }}-lucide-preact-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}
|
key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}
|
||||||
restore-keys: |
|
restore-keys: |
|
||||||
${{ runner.os }}-lucide-preact-pnpm-store-
|
${{ runner.os }}-pnpm-store-
|
||||||
|
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: pnpm install --filter .
|
run: pnpm install --filter .
|
||||||
|
|||||||
62
.github/labeler.yml
vendored
Normal file
62
.github/labeler.yml
vendored
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
# For changed dependencies
|
||||||
|
📦 dependencies:
|
||||||
|
- pnpm-lock.yaml
|
||||||
|
|
||||||
|
# For changes in documentation
|
||||||
|
📖 documentation:
|
||||||
|
- docs/*.md
|
||||||
|
- docs/**/*.md
|
||||||
|
|
||||||
|
# For changes in the site, but not markdown files
|
||||||
|
🌍 site:
|
||||||
|
- 'docs/**'
|
||||||
|
|
||||||
|
# For changes in the metadata
|
||||||
|
🫧 metadata:
|
||||||
|
- 'icons/*.json'
|
||||||
|
- categories/*
|
||||||
|
|
||||||
|
# For changes or added icons
|
||||||
|
🎨 icon:
|
||||||
|
- 'icons/*.svg'
|
||||||
|
|
||||||
|
# For changes in the lucide package
|
||||||
|
🧳 lucide package:
|
||||||
|
- 'packages/lucide/*'
|
||||||
|
|
||||||
|
# For changes in the lucide React package
|
||||||
|
⚛️ react package:
|
||||||
|
- 'packages/lucide-react/*'
|
||||||
|
|
||||||
|
# For changes in the lucide React Native package
|
||||||
|
⚛️ react native package:
|
||||||
|
- 'packages/lucide-react-native/*'
|
||||||
|
|
||||||
|
# For changes in the lucide vue packages
|
||||||
|
💎 vue package:
|
||||||
|
- 'packages/lucide-vue/*'
|
||||||
|
- 'packages/lucide-vue-next/*'
|
||||||
|
|
||||||
|
# For changes in the lucide angular package
|
||||||
|
🅰️ angular package:
|
||||||
|
- 'packages/lucide-angular/*'
|
||||||
|
|
||||||
|
# For changes in the lucide preact package
|
||||||
|
⚛️ preact package:
|
||||||
|
- 'packages/lucide-preact/*'
|
||||||
|
|
||||||
|
# For changes in the lucide svelte package
|
||||||
|
🧣 svelte package:
|
||||||
|
- 'packages/lucide-svelte/*'
|
||||||
|
|
||||||
|
# For changes in the lucide solid package
|
||||||
|
🪝 solid package:
|
||||||
|
- 'packages/lucide-solid/*'
|
||||||
|
|
||||||
|
# For changes in the lucide static package
|
||||||
|
🪨 static package:
|
||||||
|
- 'packages/lucide-static/*'
|
||||||
|
|
||||||
|
# For changes in the lucide flutter package
|
||||||
|
🏹 flutter package:
|
||||||
|
- 'packages/lucide-flutter/*'
|
||||||
55
.github/pull_request_template.md
vendored
Normal file
55
.github/pull_request_template.md
vendored
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
<!-- Thank you for contributing! -->
|
||||||
|
|
||||||
|
<!-- Insert `closes #issueNumber` here if merging this PR will resolve an existing issue -->
|
||||||
|
|
||||||
|
## What is the purpose of this pull request?
|
||||||
|
<!-- Please choose one of the following, and put an "x" next to it. -->
|
||||||
|
- [ ] New Icon
|
||||||
|
- [ ] Bug fix
|
||||||
|
- [ ] New Feature
|
||||||
|
- [ ] Documentation update
|
||||||
|
- [ ] Other:
|
||||||
|
|
||||||
|
### Description
|
||||||
|
<!-- Please insert your description here and provide info about the "what" this PR is contribution -->
|
||||||
|
|
||||||
|
### Icon use case <!-- ONLY for new icons, remove this part if not icon PR -->
|
||||||
|
<!-- What is the purpose of this icon? For each icon added, please insert at least two real life use cases (the more the better). Text like "it's a car icon" is not accepted. -->
|
||||||
|
|
||||||
|
### Alternative icon designs <!-- ONLY for new icons, remove this part if not icon PR -->
|
||||||
|
<!-- If you have any alternative icon designs, please attach them here. -->
|
||||||
|
|
||||||
|
## Icon Design Checklist <!-- ONLY for new icons, remove this part if not icon PR -->
|
||||||
|
|
||||||
|
### Concept <!-- ONLY for new icons -->
|
||||||
|
<!-- All of these requirements must be fulfilled. -->
|
||||||
|
- [ ] I have provided valid use cases for each icon.
|
||||||
|
- [ ] I have not added any a brand or logo icon.
|
||||||
|
- [ ] I have not used any hate symbols.
|
||||||
|
- [ ] I have not included any religious or political imagery.
|
||||||
|
|
||||||
|
### Author, credits & license<!-- ONLY for new icons. -->
|
||||||
|
<!-- Please choose one of the following, and put an "x" next to it. -->
|
||||||
|
- [ ] The icons are solely my own creation.
|
||||||
|
- [ ] The icons were originally created in #<issueNumber> by @<githubUser>
|
||||||
|
- [ ] I've based them on the following Lucide icons: <!-- provide the list of icons -->
|
||||||
|
- [ ] I've based them on the following design: <!-- provide source URL and license permitting use -->
|
||||||
|
|
||||||
|
### Naming <!-- ONLY for new icons -->
|
||||||
|
<!-- All of these requirements must be fulfilled. -->
|
||||||
|
- [ ] I've read and followed the [naming conventions](https://lucide.dev/guide/design/icon-design-guide#naming-conventions)
|
||||||
|
- [ ] I've named icons by what they are rather than their use case.
|
||||||
|
- [ ] I've provided meta JSON files in `icons/[iconName].json`.
|
||||||
|
|
||||||
|
### Design <!-- ONLY for new icons -->
|
||||||
|
<!-- All of these requirements must be fulfilled. -->
|
||||||
|
- [ ] I've read and followed the [icon design guidelines](https://lucide.dev/guide/design/icon-design-guide)
|
||||||
|
- [ ] 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 are visually centered.
|
||||||
|
- [ ] I've correctly optimized all icons to two points of precision.
|
||||||
|
|
||||||
|
## Before Submitting <!-- For every PR! -->
|
||||||
|
<!-- All of these requirements must be fulfilled. -->
|
||||||
|
- [ ] I've read the [Contribution Guidelines](https://github.com/lucide-icons/lucide/blob/main/CONTRIBUTING.md).
|
||||||
|
- [ ] I've checked if there was an existing PR that solves the same issue.
|
||||||
59
.github/workflows/ci.yml
vendored
59
.github/workflows/ci.yml
vendored
@@ -10,64 +10,47 @@ on:
|
|||||||
jobs:
|
jobs:
|
||||||
create-release:
|
create-release:
|
||||||
if: github.repository == 'lucide-icons/lucide'
|
if: github.repository == 'lucide-icons/lucide'
|
||||||
|
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
outputs:
|
||||||
|
VERSION: ${{ steps.new-version.outputs.NEW_VERSION }}
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
- uses: actions/setup-node@v3
|
- uses: pnpm/action-setup@v2
|
||||||
with:
|
with:
|
||||||
node-version: 16
|
version: 8
|
||||||
|
- uses: actions/setup-node@v3.8.1
|
||||||
- uses: pnpm/action-setup@v2.0.1
|
|
||||||
name: Install pnpm
|
|
||||||
id: pnpm-install
|
|
||||||
with:
|
with:
|
||||||
version: 7
|
node-version: 18
|
||||||
run_install: false
|
cache: 'pnpm'
|
||||||
|
|
||||||
- name: Get pnpm store directory
|
|
||||||
id: pnpm-cache
|
|
||||||
run: |
|
|
||||||
echo "::set-output name=pnpm_cache_dir::$(pnpm store path)"
|
|
||||||
|
|
||||||
- uses: actions/cache@v3
|
|
||||||
name: Setup pnpm cache
|
|
||||||
with:
|
|
||||||
path: ${{ steps.pnpm-cache.outputs.pnpm_cache_dir }}
|
|
||||||
key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}
|
|
||||||
restore-keys: |
|
|
||||||
${{ runner.os }}-pnpm-store-
|
|
||||||
|
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: pnpm install
|
run: pnpm install --frozen-lockfile
|
||||||
|
|
||||||
- name: Fetch tags
|
- name: Fetch tags
|
||||||
run: git fetch --all --tags
|
run: git fetch --all --tags
|
||||||
|
|
||||||
- name: Get latest tag
|
- name: Get latest tag
|
||||||
id: latest-tag
|
id: latest-tag
|
||||||
run: echo "::set-output name=LATEST_TAG::$(git describe --tags `git rev-list --tags --max-count=1`)"
|
run: echo "LATEST_TAG=$(git describe --tags `git rev-list --tags --max-count=1`)" >> $GITHUB_OUTPUT
|
||||||
|
|
||||||
- name: Install dependencies
|
|
||||||
run: pnpm install
|
|
||||||
|
|
||||||
- name: Check if we can patch
|
- name: Check if we can patch
|
||||||
run: .github/workflows/version-up.sh --minor
|
run: .github/workflows/version-up.sh --minor
|
||||||
|
|
||||||
- name: Create new version
|
- name: Create new version
|
||||||
id: new-version
|
id: new-version
|
||||||
run: echo "::set-output name=NEW_VERSION::$(.github/workflows/version-up.sh --minor)"
|
run: echo "NEW_VERSION=$(.github/workflows/version-up.sh --minor)" >> $GITHUB_OUTPUT
|
||||||
|
|
||||||
- name: Create change log
|
- name: Create change log
|
||||||
id: change-log
|
id: change-log
|
||||||
run: |
|
run: |
|
||||||
CHANGE_LOG=$(pnpm run generate:changelog --old-tag=${{ steps.latest-tag.outputs.LATEST_TAG }})
|
CHANGE_LOG=$(pnpm run generate:changelog --old-tag=${{ steps.latest-tag.outputs.LATEST_TAG }})
|
||||||
CHANGE_LOG="${CHANGE_LOG//'%'/'%25'}"
|
CHANGE_LOG=$(tail -n +5 <<< $CHANGE_LOG)
|
||||||
CHANGE_LOG="${CHANGE_LOG//$'\n'/'%0A'}"
|
|
||||||
CHANGE_LOG="${CHANGE_LOG//$'\r'/'%0D'}"
|
|
||||||
echo $CHANGE_LOG
|
echo $CHANGE_LOG
|
||||||
echo "::set-output name=CHANGE_LOG::$CHANGE_LOG"
|
EOF=$(dd if=/dev/urandom bs=15 count=1 status=none | base64)
|
||||||
|
echo "CHANGE_LOG<<$EOF" >> $GITHUB_OUTPUT
|
||||||
|
echo "$CHANGE_LOG" >> $GITHUB_OUTPUT
|
||||||
|
echo "$EOF" >> $GITHUB_OUTPUT
|
||||||
env:
|
env:
|
||||||
GITHUB_API_KEY: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_API_KEY: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
@@ -76,11 +59,17 @@ jobs:
|
|||||||
echo '${{ steps.new-version.outputs.NEW_VERSION }}'
|
echo '${{ steps.new-version.outputs.NEW_VERSION }}'
|
||||||
echo '${{ steps.change-log.outputs.CHANGE_LOG }}'
|
echo '${{ steps.change-log.outputs.CHANGE_LOG }}'
|
||||||
|
|
||||||
- name: Release
|
- name: Create Release
|
||||||
uses: softprops/action-gh-release@v1
|
uses: softprops/action-gh-release@v1
|
||||||
env:
|
|
||||||
GITHUB_TOKEN: ${{ secrets.CREATE_RELEASE_TOKEN }}
|
|
||||||
with:
|
with:
|
||||||
tag_name: ${{ steps.new-version.outputs.NEW_VERSION }}
|
tag_name: ${{ steps.new-version.outputs.NEW_VERSION }}
|
||||||
name: New icons ${{ steps.new-version.outputs.NEW_VERSION }}
|
name: New icons ${{ steps.new-version.outputs.NEW_VERSION }}
|
||||||
body: ${{ steps.change-log.outputs.CHANGE_LOG }}
|
body: ${{ steps.change-log.outputs.CHANGE_LOG }}
|
||||||
|
|
||||||
|
start-release:
|
||||||
|
if: github.repository == 'lucide-icons/lucide'
|
||||||
|
needs: create-release
|
||||||
|
uses: './.github/workflows/release.yml'
|
||||||
|
secrets: inherit
|
||||||
|
with:
|
||||||
|
version: ${{ needs.create-release.outputs.VERSION }}
|
||||||
|
|||||||
12
.github/workflows/labeler.yml
vendored
Normal file
12
.github/workflows/labeler.yml
vendored
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
name: "Pull Request Labeler"
|
||||||
|
on:
|
||||||
|
- pull_request_target
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
triage:
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
pull-requests: write
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/labeler@v4
|
||||||
25
.github/workflows/linting.yml
vendored
Normal file
25
.github/workflows/linting.yml
vendored
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
name: Linting
|
||||||
|
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
paths:
|
||||||
|
- icons/**
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
linting:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
- uses: pnpm/action-setup@v2
|
||||||
|
with:
|
||||||
|
version: 8
|
||||||
|
- uses: actions/setup-node@v3.8.1
|
||||||
|
with:
|
||||||
|
node-version: 18
|
||||||
|
cache: 'pnpm'
|
||||||
|
|
||||||
|
- name: Install Dependencies
|
||||||
|
run: pnpm install --frozen-lockfile
|
||||||
|
|
||||||
|
- name: Run Linter
|
||||||
|
run: pnpm lint
|
||||||
29
.github/workflows/lucide-angular.yml
vendored
29
.github/workflows/lucide-angular.yml
vendored
@@ -4,6 +4,7 @@ on:
|
|||||||
pull_request:
|
pull_request:
|
||||||
paths:
|
paths:
|
||||||
- packages/lucide-angular/**
|
- packages/lucide-angular/**
|
||||||
|
- tools/build-icons/**
|
||||||
- pnpm-lock.yaml
|
- pnpm-lock.yaml
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
@@ -11,32 +12,16 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
- uses: actions/setup-node@v3
|
- uses: pnpm/action-setup@v2
|
||||||
with:
|
with:
|
||||||
node-version: 16
|
version: 8
|
||||||
|
- uses: actions/setup-node@v3.8.1
|
||||||
- uses: pnpm/action-setup@v2.0.1
|
|
||||||
name: Install pnpm
|
|
||||||
id: pnpm-install
|
|
||||||
with:
|
with:
|
||||||
version: 7
|
node-version: 18
|
||||||
run_install: false
|
cache: 'pnpm'
|
||||||
|
|
||||||
- name: Get pnpm store directory
|
|
||||||
id: pnpm-cache
|
|
||||||
run: |
|
|
||||||
echo "::set-output name=pnpm_cache_dir::$(pnpm store path)"
|
|
||||||
|
|
||||||
- uses: actions/cache@v3
|
|
||||||
name: Setup pnpm cache
|
|
||||||
with:
|
|
||||||
path: ${{ steps.pnpm-cache.outputs.pnpm_cache_dir }}
|
|
||||||
key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}
|
|
||||||
restore-keys: |
|
|
||||||
${{ runner.os }}-pnpm-store-
|
|
||||||
|
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: pnpm install
|
run: pnpm install --frozen-lockfile
|
||||||
|
|
||||||
- name: Build
|
- name: Build
|
||||||
run: pnpm --filter lucide-angular build
|
run: pnpm --filter lucide-angular build
|
||||||
|
|||||||
37
.github/workflows/lucide-font.yml
vendored
37
.github/workflows/lucide-font.yml
vendored
@@ -4,49 +4,30 @@ on:
|
|||||||
pull_request:
|
pull_request:
|
||||||
paths:
|
paths:
|
||||||
- icons/**
|
- icons/**
|
||||||
|
- tools/build-font/**
|
||||||
- pnpm-lock.yaml
|
- pnpm-lock.yaml
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
lucide-font:
|
lucide-font:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
container: ericfennis/lucide-font:latest
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
- uses: actions/setup-node@v3.4.1
|
- uses: pnpm/action-setup@v2
|
||||||
with:
|
with:
|
||||||
node-version: 16
|
version: 8
|
||||||
|
- uses: actions/setup-node@v3.8.1
|
||||||
- uses: pnpm/action-setup@v2.0.1
|
|
||||||
name: Install pnpm
|
|
||||||
id: pnpm-install
|
|
||||||
with:
|
with:
|
||||||
version: 7
|
node-version: 18
|
||||||
run_install: false
|
cache: 'pnpm'
|
||||||
|
|
||||||
- name: Get pnpm store directory
|
|
||||||
id: pnpm-cache
|
|
||||||
run: |
|
|
||||||
echo "::set-output name=pnpm_cache_dir::$(pnpm store path)"
|
|
||||||
|
|
||||||
- uses: actions/cache@v3
|
|
||||||
name: Setup pnpm cache
|
|
||||||
with:
|
|
||||||
path: ${{ steps.pnpm-cache.outputs.pnpm_cache_dir }}
|
|
||||||
key: ${{ runner.os }}-lucide-font-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}
|
|
||||||
restore-keys: |
|
|
||||||
${{ runner.os }}-lucide-font-pnpm-store-
|
|
||||||
|
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: pnpm install --filter outline-svg
|
run: pnpm install --frozen-lockfile
|
||||||
|
|
||||||
- name: Outline svg Icons
|
- name: Outline svg Icons
|
||||||
run: pnpm build:outline-icons
|
run: pnpm build:outline-icons
|
||||||
|
|
||||||
- name: Create directory
|
- name: Create font in ./lucide-font
|
||||||
run: mkdir lucide-font
|
run: pnpm build:font
|
||||||
|
|
||||||
- name: Build font
|
|
||||||
run: fontcustom compile "./outlined" -h -n "lucide" -o ./lucide-font -F
|
|
||||||
|
|
||||||
- name: "Upload to Artifacts"
|
- name: "Upload to Artifacts"
|
||||||
uses: actions/upload-artifact@v1
|
uses: actions/upload-artifact@v1
|
||||||
|
|||||||
30
.github/workflows/lucide-preact.yml
vendored
30
.github/workflows/lucide-preact.yml
vendored
@@ -4,6 +4,8 @@ on:
|
|||||||
pull_request:
|
pull_request:
|
||||||
paths:
|
paths:
|
||||||
- packages/lucide-preact/**
|
- packages/lucide-preact/**
|
||||||
|
- tools/build-icons/**
|
||||||
|
- tools/rollup-plugins/**
|
||||||
- pnpm-lock.yaml
|
- pnpm-lock.yaml
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
@@ -11,32 +13,16 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
- uses: actions/setup-node@v3
|
- uses: pnpm/action-setup@v2
|
||||||
with:
|
with:
|
||||||
node-version: 16
|
version: 8
|
||||||
|
- uses: actions/setup-node@v3.8.1
|
||||||
- uses: pnpm/action-setup@v2.0.1
|
|
||||||
name: Install pnpm
|
|
||||||
id: pnpm-install
|
|
||||||
with:
|
with:
|
||||||
version: 7
|
node-version: 18
|
||||||
run_install: false
|
cache: 'pnpm'
|
||||||
|
|
||||||
- name: Get pnpm store directory
|
|
||||||
id: pnpm-cache
|
|
||||||
run: |
|
|
||||||
echo "::set-output name=pnpm_cache_dir::$(pnpm store path)"
|
|
||||||
|
|
||||||
- uses: actions/cache@v3
|
|
||||||
name: Setup pnpm cache
|
|
||||||
with:
|
|
||||||
path: ${{ steps.pnpm-cache.outputs.pnpm_cache_dir }}
|
|
||||||
key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}
|
|
||||||
restore-keys: |
|
|
||||||
${{ runner.os }}-pnpm-store-
|
|
||||||
|
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: pnpm install
|
run: pnpm install --frozen-lockfile
|
||||||
|
|
||||||
- name: Build
|
- name: Build
|
||||||
run: pnpm --filter lucide-preact build
|
run: pnpm --filter lucide-preact build
|
||||||
|
|||||||
30
.github/workflows/lucide-react-native.yml
vendored
30
.github/workflows/lucide-react-native.yml
vendored
@@ -4,6 +4,8 @@ on:
|
|||||||
pull_request:
|
pull_request:
|
||||||
paths:
|
paths:
|
||||||
- packages/lucide-react-native/**
|
- packages/lucide-react-native/**
|
||||||
|
- tools/build-icons/**
|
||||||
|
- tools/rollup-plugins/**
|
||||||
- pnpm-lock.yaml
|
- pnpm-lock.yaml
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
@@ -11,32 +13,16 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
- uses: actions/setup-node@v3
|
- uses: pnpm/action-setup@v2
|
||||||
with:
|
with:
|
||||||
node-version: 16
|
version: 8
|
||||||
|
- uses: actions/setup-node@v3.8.1
|
||||||
- uses: pnpm/action-setup@v2.0.1
|
|
||||||
name: Install pnpm
|
|
||||||
id: pnpm-install
|
|
||||||
with:
|
with:
|
||||||
version: 7
|
node-version: 18
|
||||||
run_install: false
|
cache: 'pnpm'
|
||||||
|
|
||||||
- name: Get pnpm store directory
|
|
||||||
id: pnpm-cache
|
|
||||||
run: |
|
|
||||||
echo "::set-output name=pnpm_cache_dir::$(pnpm store path)"
|
|
||||||
|
|
||||||
- uses: actions/cache@v3
|
|
||||||
name: Setup pnpm cache
|
|
||||||
with:
|
|
||||||
path: ${{ steps.pnpm-cache.outputs.pnpm_cache_dir }}
|
|
||||||
key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}
|
|
||||||
restore-keys: |
|
|
||||||
${{ runner.os }}-pnpm-store-
|
|
||||||
|
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: pnpm install
|
run: pnpm install --frozen-lockfile
|
||||||
|
|
||||||
- name: Build
|
- name: Build
|
||||||
run: pnpm --filter lucide-react-native build
|
run: pnpm --filter lucide-react-native build
|
||||||
|
|||||||
31
.github/workflows/lucide-react.yml
vendored
31
.github/workflows/lucide-react.yml
vendored
@@ -4,6 +4,9 @@ on:
|
|||||||
pull_request:
|
pull_request:
|
||||||
paths:
|
paths:
|
||||||
- packages/lucide-react/**
|
- packages/lucide-react/**
|
||||||
|
- tools/build-icons/**
|
||||||
|
- tools/rollup-plugins/**
|
||||||
|
- scripts/generateNextJSAliases.mjs
|
||||||
- pnpm-lock.yaml
|
- pnpm-lock.yaml
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
@@ -11,32 +14,16 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
- uses: actions/setup-node@v3
|
- uses: pnpm/action-setup@v2
|
||||||
with:
|
with:
|
||||||
node-version: 16
|
version: 8
|
||||||
|
- uses: actions/setup-node@v3.8.1
|
||||||
- uses: pnpm/action-setup@v2.0.1
|
|
||||||
name: Install pnpm
|
|
||||||
id: pnpm-install
|
|
||||||
with:
|
with:
|
||||||
version: 7
|
node-version: 18
|
||||||
run_install: false
|
cache: 'pnpm'
|
||||||
|
|
||||||
- name: Get pnpm store directory
|
|
||||||
id: pnpm-cache
|
|
||||||
run: |
|
|
||||||
echo "::set-output name=pnpm_cache_dir::$(pnpm store path)"
|
|
||||||
|
|
||||||
- uses: actions/cache@v3
|
|
||||||
name: Setup pnpm cache
|
|
||||||
with:
|
|
||||||
path: ${{ steps.pnpm-cache.outputs.pnpm_cache_dir }}
|
|
||||||
key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}
|
|
||||||
restore-keys: |
|
|
||||||
${{ runner.os }}-pnpm-store-
|
|
||||||
|
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: pnpm install
|
run: pnpm install --frozen-lockfile
|
||||||
|
|
||||||
- name: Build
|
- name: Build
|
||||||
run: pnpm --filter lucide-react build
|
run: pnpm --filter lucide-react build
|
||||||
|
|||||||
30
.github/workflows/lucide-solid.yml
vendored
30
.github/workflows/lucide-solid.yml
vendored
@@ -4,6 +4,8 @@ on:
|
|||||||
pull_request:
|
pull_request:
|
||||||
paths:
|
paths:
|
||||||
- packages/lucide-solid/**
|
- packages/lucide-solid/**
|
||||||
|
- tools/build-icons/**
|
||||||
|
- tools/rollup-plugins/**
|
||||||
- pnpm-lock.yaml
|
- pnpm-lock.yaml
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
@@ -11,32 +13,16 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
- uses: actions/setup-node@v3
|
- uses: pnpm/action-setup@v2
|
||||||
with:
|
with:
|
||||||
node-version: 16
|
version: 8
|
||||||
|
- uses: actions/setup-node@v3.8.1
|
||||||
- uses: pnpm/action-setup@v2.0.1
|
|
||||||
name: Install pnpm
|
|
||||||
id: pnpm-install
|
|
||||||
with:
|
with:
|
||||||
version: 7
|
node-version: 18
|
||||||
run_install: false
|
cache: 'pnpm'
|
||||||
|
|
||||||
- name: Get pnpm store directory
|
|
||||||
id: pnpm-cache
|
|
||||||
run: |
|
|
||||||
echo "::set-output name=pnpm_cache_dir::$(pnpm store path)"
|
|
||||||
|
|
||||||
- uses: actions/cache@v3
|
|
||||||
name: Setup pnpm cache
|
|
||||||
with:
|
|
||||||
path: ${{ steps.pnpm-cache.outputs.pnpm_cache_dir }}
|
|
||||||
key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}
|
|
||||||
restore-keys: |
|
|
||||||
${{ runner.os }}-pnpm-store-
|
|
||||||
|
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: pnpm install
|
run: pnpm install --frozen-lockfile
|
||||||
|
|
||||||
- name: Build
|
- name: Build
|
||||||
run: pnpm --filter lucide-solid build
|
run: pnpm --filter lucide-solid build
|
||||||
|
|||||||
29
.github/workflows/lucide-static.yml
vendored
29
.github/workflows/lucide-static.yml
vendored
@@ -4,6 +4,7 @@ on:
|
|||||||
pull_request:
|
pull_request:
|
||||||
paths:
|
paths:
|
||||||
- packages/lucide-static/**
|
- packages/lucide-static/**
|
||||||
|
- tools/build-icons/**
|
||||||
- pnpm-lock.yaml
|
- pnpm-lock.yaml
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
@@ -11,32 +12,16 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
- uses: actions/setup-node@v3
|
- uses: pnpm/action-setup@v2
|
||||||
with:
|
with:
|
||||||
node-version: 16
|
version: 8
|
||||||
|
- uses: actions/setup-node@v3.8.1
|
||||||
- uses: pnpm/action-setup@v2.0.1
|
|
||||||
name: Install pnpm
|
|
||||||
id: pnpm-install
|
|
||||||
with:
|
with:
|
||||||
version: 7
|
node-version: 18
|
||||||
run_install: false
|
cache: 'pnpm'
|
||||||
|
|
||||||
- name: Get pnpm store directory
|
|
||||||
id: pnpm-cache
|
|
||||||
run: |
|
|
||||||
echo "::set-output name=pnpm_cache_dir::$(pnpm store path)"
|
|
||||||
|
|
||||||
- uses: actions/cache@v3
|
|
||||||
name: Setup pnpm cache
|
|
||||||
with:
|
|
||||||
path: ${{ steps.pnpm-cache.outputs.pnpm_cache_dir }}
|
|
||||||
key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}
|
|
||||||
restore-keys: |
|
|
||||||
${{ runner.os }}-pnpm-store-
|
|
||||||
|
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: pnpm install
|
run: pnpm install --frozen-lockfile
|
||||||
|
|
||||||
- name: Build
|
- name: Build
|
||||||
run: pnpm --filter lucide-static build
|
run: pnpm --filter lucide-static build
|
||||||
|
|||||||
30
.github/workflows/lucide-svelte.yml
vendored
30
.github/workflows/lucide-svelte.yml
vendored
@@ -4,6 +4,8 @@ on:
|
|||||||
pull_request:
|
pull_request:
|
||||||
paths:
|
paths:
|
||||||
- packages/lucide-svelte/**
|
- packages/lucide-svelte/**
|
||||||
|
- tools/build-icons/**
|
||||||
|
- tools/rollup-plugins/**
|
||||||
- pnpm-lock.yaml
|
- pnpm-lock.yaml
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
@@ -11,32 +13,16 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
- uses: actions/setup-node@v3
|
- uses: pnpm/action-setup@v2
|
||||||
with:
|
with:
|
||||||
node-version: 16
|
version: 8
|
||||||
|
- uses: actions/setup-node@v3.8.1
|
||||||
- uses: pnpm/action-setup@v2.0.1
|
|
||||||
name: Install pnpm
|
|
||||||
id: pnpm-install
|
|
||||||
with:
|
with:
|
||||||
version: 7
|
node-version: 18
|
||||||
run_install: false
|
cache: 'pnpm'
|
||||||
|
|
||||||
- name: Get pnpm store directory
|
|
||||||
id: pnpm-cache
|
|
||||||
run: |
|
|
||||||
echo "::set-output name=pnpm_cache_dir::$(pnpm store path)"
|
|
||||||
|
|
||||||
- uses: actions/cache@v3
|
|
||||||
name: Setup pnpm cache
|
|
||||||
with:
|
|
||||||
path: ${{ steps.pnpm-cache.outputs.pnpm_cache_dir }}
|
|
||||||
key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}
|
|
||||||
restore-keys: |
|
|
||||||
${{ runner.os }}-pnpm-store-
|
|
||||||
|
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: pnpm install
|
run: pnpm install --frozen-lockfile
|
||||||
|
|
||||||
- name: Build
|
- name: Build
|
||||||
run: pnpm --filter lucide-svelte build
|
run: pnpm --filter lucide-svelte build
|
||||||
|
|||||||
30
.github/workflows/lucide-vue-next.yml
vendored
30
.github/workflows/lucide-vue-next.yml
vendored
@@ -4,6 +4,8 @@ on:
|
|||||||
pull_request:
|
pull_request:
|
||||||
paths:
|
paths:
|
||||||
- packages/lucide-vue-next/**
|
- packages/lucide-vue-next/**
|
||||||
|
- tools/build-icons/**
|
||||||
|
- tools/rollup-plugins/**
|
||||||
- pnpm-lock.yaml
|
- pnpm-lock.yaml
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
@@ -11,32 +13,16 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
- uses: actions/setup-node@v3
|
- uses: pnpm/action-setup@v2
|
||||||
with:
|
with:
|
||||||
node-version: 16
|
version: 8
|
||||||
|
- uses: actions/setup-node@v3.8.1
|
||||||
- uses: pnpm/action-setup@v2.0.1
|
|
||||||
name: Install pnpm
|
|
||||||
id: pnpm-install
|
|
||||||
with:
|
with:
|
||||||
version: 7
|
node-version: 18
|
||||||
run_install: false
|
cache: 'pnpm'
|
||||||
|
|
||||||
- name: Get pnpm store directory
|
|
||||||
id: pnpm-cache
|
|
||||||
run: |
|
|
||||||
echo "::set-output name=pnpm_cache_dir::$(pnpm store path)"
|
|
||||||
|
|
||||||
- uses: actions/cache@v3
|
|
||||||
name: Setup pnpm cache
|
|
||||||
with:
|
|
||||||
path: ${{ steps.pnpm-cache.outputs.pnpm_cache_dir }}
|
|
||||||
key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}
|
|
||||||
restore-keys: |
|
|
||||||
${{ runner.os }}-pnpm-store-
|
|
||||||
|
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: pnpm install
|
run: pnpm install --frozen-lockfile
|
||||||
|
|
||||||
- name: Build
|
- name: Build
|
||||||
run: pnpm --filter lucide-vue-next build
|
run: pnpm --filter lucide-vue-next build
|
||||||
|
|||||||
30
.github/workflows/lucide-vue.yml
vendored
30
.github/workflows/lucide-vue.yml
vendored
@@ -4,6 +4,8 @@ on:
|
|||||||
pull_request:
|
pull_request:
|
||||||
paths:
|
paths:
|
||||||
- packages/lucide-vue/**
|
- packages/lucide-vue/**
|
||||||
|
- tools/build-icons/**
|
||||||
|
- tools/rollup-plugins/**
|
||||||
- pnpm-lock.yaml
|
- pnpm-lock.yaml
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
@@ -11,32 +13,16 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
- uses: actions/setup-node@v3
|
- uses: pnpm/action-setup@v2
|
||||||
with:
|
with:
|
||||||
node-version: 16
|
version: 8
|
||||||
|
- uses: actions/setup-node@v3.8.1
|
||||||
- uses: pnpm/action-setup@v2.0.1
|
|
||||||
name: Install pnpm
|
|
||||||
id: pnpm-install
|
|
||||||
with:
|
with:
|
||||||
version: 7
|
node-version: 18
|
||||||
run_install: false
|
cache: 'pnpm'
|
||||||
|
|
||||||
- name: Get pnpm store directory
|
|
||||||
id: pnpm-cache
|
|
||||||
run: |
|
|
||||||
echo "::set-output name=pnpm_cache_dir::$(pnpm store path)"
|
|
||||||
|
|
||||||
- uses: actions/cache@v3
|
|
||||||
name: Setup pnpm cache
|
|
||||||
with:
|
|
||||||
path: ${{ steps.pnpm-cache.outputs.pnpm_cache_dir }}
|
|
||||||
key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}
|
|
||||||
restore-keys: |
|
|
||||||
${{ runner.os }}-pnpm-store-
|
|
||||||
|
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: pnpm install
|
run: pnpm install --frozen-lockfile
|
||||||
|
|
||||||
- name: Build
|
- name: Build
|
||||||
run: pnpm --filter lucide-vue build
|
run: pnpm --filter lucide-vue build
|
||||||
|
|||||||
30
.github/workflows/lucide.yml
vendored
30
.github/workflows/lucide.yml
vendored
@@ -4,6 +4,8 @@ on:
|
|||||||
pull_request:
|
pull_request:
|
||||||
paths:
|
paths:
|
||||||
- packages/lucide/**
|
- packages/lucide/**
|
||||||
|
- tools/build-icons/**
|
||||||
|
- tools/rollup-plugins/**
|
||||||
- pnpm-lock.yaml
|
- pnpm-lock.yaml
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
@@ -11,32 +13,16 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
- uses: actions/setup-node@v3
|
- uses: pnpm/action-setup@v2
|
||||||
with:
|
with:
|
||||||
node-version: 16
|
version: 8
|
||||||
|
- uses: actions/setup-node@v3.8.1
|
||||||
- uses: pnpm/action-setup@v2.0.1
|
|
||||||
name: Install pnpm
|
|
||||||
id: pnpm-install
|
|
||||||
with:
|
with:
|
||||||
version: 7
|
node-version: 18
|
||||||
run_install: false
|
cache: 'pnpm'
|
||||||
|
|
||||||
- name: Get pnpm store directory
|
|
||||||
id: pnpm-cache
|
|
||||||
run: |
|
|
||||||
echo "::set-output name=pnpm_cache_dir::$(pnpm store path)"
|
|
||||||
|
|
||||||
- uses: actions/cache@v3
|
|
||||||
name: Setup pnpm cache
|
|
||||||
with:
|
|
||||||
path: ${{ steps.pnpm-cache.outputs.pnpm_cache_dir }}
|
|
||||||
key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}
|
|
||||||
restore-keys: |
|
|
||||||
${{ runner.os }}-pnpm-store-
|
|
||||||
|
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: pnpm install
|
run: pnpm install --frozen-lockfile
|
||||||
|
|
||||||
- name: Build
|
- name: Build
|
||||||
run: pnpm --filter lucide build
|
run: pnpm --filter lucide build
|
||||||
|
|||||||
61
.github/workflows/pull-request.yml
vendored
61
.github/workflows/pull-request.yml
vendored
@@ -5,13 +5,48 @@ on:
|
|||||||
paths:
|
paths:
|
||||||
- 'icons/*.svg'
|
- 'icons/*.svg'
|
||||||
|
|
||||||
permissions:
|
|
||||||
pull-requests: write
|
|
||||||
contents: write
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
|
lint-contributors:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
with:
|
||||||
|
fetch-depth: 0
|
||||||
|
ref: refs/pull/${{ github.event.pull_request.number }}/merge
|
||||||
|
- name: Get changed files
|
||||||
|
id: changed-files
|
||||||
|
uses: tj-actions/changed-files@v35
|
||||||
|
with:
|
||||||
|
files: icons/*
|
||||||
|
- uses: actions/setup-node@v3.8.1
|
||||||
|
- name: Install simple-git (safer and faster than installing all deps)
|
||||||
|
run: npm install simple-git
|
||||||
|
- env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
FETCH_DEPTH: ${{ github.event.pull_request.commits }}
|
||||||
|
run: node ./scripts/updateContributors.mjs ${{ steps.changed-files.outputs.all_changed_files }}
|
||||||
|
- name: Generate annotations
|
||||||
|
env:
|
||||||
|
ANNOTATION_SEVERITY: notice
|
||||||
|
ANNOTATION_TITLE: Contributors have changed!
|
||||||
|
ANNOTATION_DESCRIPTION: Don't add people who have only performed automatic optimizations.
|
||||||
|
run: |
|
||||||
|
git diff --unified=0 -- icons/*.json | # diff icon metadata (unified=0 gives the correct chunk line number)
|
||||||
|
perl -ne '/^(\+|- |@)/ && print' | # get chunks (lines that start with "+++", "@@", "+ ", "- ")
|
||||||
|
perl -pe 's/\n/%0A/' | # url encode line breaks (\n -> %0A)
|
||||||
|
perl -pe 's/%0A(\+\+\+ b\/)/\n\1/g' | # split chunks(one chunk per line)
|
||||||
|
perl -pe "s/\+\+\+ b\/([^@]*)%0A@@ -(\d+)[^\s]* \+(\d+)[^@]*@@(.*)/::$ANNOTATION_SEVERITY file=\1,line=\2,endLine=\3,title=$ANNOTATION_TITLE::$ANNOTATION_DESCRIPTION%0A\4/"
|
||||||
|
# Example for the previous substitution
|
||||||
|
# input: +++ b/icons/accessibility.json%0A@@ -2,0 +3 @@%0A+ "contributors": ["hi"],%0A@@ -13 +14 @@%0A+}%0A
|
||||||
|
# output: ::$ANNOTATION_SEVERITY file=icons/accessibility.json,line=2,endLine=3,title=$ANNOTATION_TITLE::$ANNOTATION_DESCRIPTION%0A%0A+ "contributors": ["hi"],%0A@@ -13 +14 @@%0A+}%0A
|
||||||
|
# - name: Fail if contributors have changed
|
||||||
|
# run: git diff --exit-code -- icons/*.json
|
||||||
|
|
||||||
add-changed-icons-comment:
|
add-changed-icons-comment:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
permissions:
|
||||||
|
pull-requests: write
|
||||||
|
contents: write
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
with:
|
with:
|
||||||
@@ -22,6 +57,20 @@ jobs:
|
|||||||
uses: tj-actions/changed-files@v35
|
uses: tj-actions/changed-files@v35
|
||||||
with:
|
with:
|
||||||
files: icons/*.svg
|
files: icons/*.svg
|
||||||
|
- name: Generate 24px dpi preview
|
||||||
|
id: generate-24px-dpi-preview
|
||||||
|
run: |
|
||||||
|
delimiter="$(openssl rand -hex 8)"
|
||||||
|
echo "body<<$delimiter" >> $GITHUB_OUTPUT
|
||||||
|
for file in ${{ steps.changed-files.outputs.all_changed_files }}; do
|
||||||
|
cat "$file" | # get file content
|
||||||
|
tr '\n' ' ' | # remove line breaks
|
||||||
|
sed -e 's/<svg[^>]*>/<svg>/g' | # remove attributes from svg element
|
||||||
|
base64 -w 0 | # encode svg
|
||||||
|
sed "s|.*|<img title=\"$file\" alt=\"$file\" src=\"https://lucide.dev/api/gh-icon/dpi/24/&.svg\"/> |"
|
||||||
|
done | tr '\n' ' ' >> $GITHUB_OUTPUT
|
||||||
|
echo >> $GITHUB_OUTPUT
|
||||||
|
echo "$delimiter" >> $GITHUB_OUTPUT
|
||||||
- name: Generate cohesion check random
|
- name: Generate cohesion check random
|
||||||
id: generate-cohesion-check-random
|
id: generate-cohesion-check-random
|
||||||
run: |
|
run: |
|
||||||
@@ -134,6 +183,10 @@ jobs:
|
|||||||
${{ steps.generate-3px-stroke-width.outputs.body }}<br/>
|
${{ steps.generate-3px-stroke-width.outputs.body }}<br/>
|
||||||
</details>
|
</details>
|
||||||
<details>
|
<details>
|
||||||
|
<summary>DPI Preview (24px)</summary>
|
||||||
|
${{ steps.generate-24px-dpi-preview.outputs.body }}<br/>
|
||||||
|
</details>
|
||||||
|
<details>
|
||||||
<summary>Icon X-rays</summary>
|
<summary>Icon X-rays</summary>
|
||||||
${{ steps.generate-x-rays.outputs.body }}
|
${{ steps.generate-x-rays.outputs.body }}
|
||||||
</details>
|
</details>
|
||||||
|
|||||||
715
.github/workflows/release.yml
vendored
715
.github/workflows/release.yml
vendored
@@ -5,6 +5,13 @@ on:
|
|||||||
tags:
|
tags:
|
||||||
- 'v*'
|
- 'v*'
|
||||||
|
|
||||||
|
workflow_call:
|
||||||
|
inputs:
|
||||||
|
version:
|
||||||
|
required: true
|
||||||
|
description: Version
|
||||||
|
type: string
|
||||||
|
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
inputs:
|
inputs:
|
||||||
version:
|
version:
|
||||||
@@ -12,8 +19,8 @@ on:
|
|||||||
required: true
|
required: true
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
pre-build:
|
pre-release:
|
||||||
if: github.repository == 'lucide-icons/lucide' && contains('["locness3","ericfennis", "johnletey", "karsa-mistmere"]', github.actor)
|
if: github.repository == 'lucide-icons/lucide' && contains('["ericfennis", "karsa-mistmere"]', github.actor)
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
outputs:
|
outputs:
|
||||||
VERSION: ${{ steps.get_version.outputs.VERSION }}
|
VERSION: ${{ steps.get_version.outputs.VERSION }}
|
||||||
@@ -23,544 +30,78 @@ jobs:
|
|||||||
id: get_version
|
id: get_version
|
||||||
run: |
|
run: |
|
||||||
echo $VERSION_REF
|
echo $VERSION_REF
|
||||||
echo ::set-output name=VERSION::${VERSION_REF/refs\/tags\/\v}
|
echo "VERSION=${VERSION_REF/refs\/tags\/\v}" >> $GITHUB_OUTPUT
|
||||||
env:
|
env:
|
||||||
VERSION_REF: ${{ github.event.inputs.version || github.ref }}
|
VERSION_REF: ${{ inputs.version || github.event.inputs.version || github.ref }}
|
||||||
|
|
||||||
lucide:
|
release:
|
||||||
if: github.repository == 'lucide-icons/lucide'
|
if: github.repository == 'lucide-icons/lucide'
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
needs: pre-build
|
needs: pre-release
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
package: [
|
||||||
|
'lucide',
|
||||||
|
'lucide-react',
|
||||||
|
'lucide-react-native',
|
||||||
|
'lucide-vue',
|
||||||
|
'lucide-vue-next',
|
||||||
|
'lucide-angular',
|
||||||
|
'lucide-preact',
|
||||||
|
'lucide-solid',
|
||||||
|
'lucide-svelte',
|
||||||
|
]
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
|
- uses: pnpm/action-setup@v2
|
||||||
|
with:
|
||||||
|
version: 8
|
||||||
- uses: actions/setup-node@v3
|
- uses: actions/setup-node@v3
|
||||||
with:
|
with:
|
||||||
node-version: 16
|
node-version: 18
|
||||||
|
cache: 'pnpm'
|
||||||
- uses: pnpm/action-setup@v2.0.1
|
|
||||||
name: Install pnpm
|
|
||||||
id: pnpm-install
|
|
||||||
with:
|
|
||||||
version: 7
|
|
||||||
run_install: false
|
|
||||||
|
|
||||||
- name: Get pnpm store directory
|
|
||||||
id: pnpm-cache
|
|
||||||
run: |
|
|
||||||
echo "::set-output name=pnpm_cache_dir::$(pnpm store path)"
|
|
||||||
|
|
||||||
- uses: actions/cache@v3
|
|
||||||
name: Setup pnpm cache
|
|
||||||
with:
|
|
||||||
path: ${{ steps.pnpm-cache.outputs.pnpm_cache_dir }}
|
|
||||||
key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}
|
|
||||||
restore-keys: |
|
|
||||||
${{ runner.os }}-pnpm-store-
|
|
||||||
|
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: pnpm install
|
run: pnpm install --frozen-lockfile
|
||||||
|
|
||||||
- name: Set Auth Token
|
- name: Set Auth Token
|
||||||
run: npm config set //registry.npmjs.org/:_authToken ${{ secrets.NPM_TOKEN }}
|
run: npm config set //registry.npmjs.org/:_authToken ${{ inputs.NPM_TOKEN || secrets.NPM_TOKEN }}
|
||||||
|
|
||||||
- name: Set new version
|
- name: Set new version
|
||||||
run: pnpm --filter lucide version --new-version ${{ needs.pre-build.outputs.VERSION }} --no-git-tag-version
|
run: pnpm --filter ${{ matrix.package }} version --new-version ${{ needs.pre-release.outputs.VERSION }} --no-git-tag-version
|
||||||
|
|
||||||
- name: Build
|
- name: Build
|
||||||
run: pnpm --filter lucide build
|
run: pnpm --filter ${{ matrix.package }} build
|
||||||
|
|
||||||
- name: Test
|
- name: Test
|
||||||
run: pnpm --filter lucide test
|
run: pnpm --filter ${{ matrix.package }} test
|
||||||
|
|
||||||
- name: Publish
|
- name: Publish
|
||||||
run: pnpm --filter lucide publish --no-git-checks
|
run: pnpm --filter ${{ matrix.package }} publish --no-git-checks --ignore-scripts
|
||||||
|
|
||||||
- name: Upload package.json
|
|
||||||
uses: actions/upload-artifact@v2
|
|
||||||
with:
|
|
||||||
name: lucide-package-json
|
|
||||||
path: packages/lucide/package.json
|
|
||||||
|
|
||||||
lucide-react:
|
|
||||||
if: github.repository == 'lucide-icons/lucide'
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
needs: pre-build
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
|
|
||||||
- uses: actions/setup-node@v3
|
|
||||||
with:
|
|
||||||
node-version: 16
|
|
||||||
|
|
||||||
- uses: pnpm/action-setup@v2.0.1
|
|
||||||
name: Install pnpm
|
|
||||||
id: pnpm-install
|
|
||||||
with:
|
|
||||||
version: 7
|
|
||||||
run_install: false
|
|
||||||
|
|
||||||
- name: Get pnpm store directory
|
|
||||||
id: pnpm-cache
|
|
||||||
run: |
|
|
||||||
echo "::set-output name=pnpm_cache_dir::$(pnpm store path)"
|
|
||||||
|
|
||||||
- uses: actions/cache@v3
|
|
||||||
name: Setup pnpm cache
|
|
||||||
with:
|
|
||||||
path: ${{ steps.pnpm-cache.outputs.pnpm_cache_dir }}
|
|
||||||
key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}
|
|
||||||
restore-keys: |
|
|
||||||
${{ runner.os }}-pnpm-store-
|
|
||||||
|
|
||||||
- name: Install dependencies
|
|
||||||
run: pnpm install
|
|
||||||
|
|
||||||
- name: Set Auth Token
|
|
||||||
run: npm config set //registry.npmjs.org/:_authToken ${{ secrets.NPM_TOKEN }}
|
|
||||||
|
|
||||||
- name: Set package.json version lucide
|
|
||||||
run: pnpm --filter lucide-react version --new-version ${{ needs.pre-build.outputs.VERSION }} --no-git-tag-version
|
|
||||||
|
|
||||||
- name: Build
|
|
||||||
run: pnpm --filter lucide-react build
|
|
||||||
|
|
||||||
- name: Test
|
|
||||||
run: pnpm --filter lucide-react test
|
|
||||||
|
|
||||||
- name: Publish
|
|
||||||
run: pnpm --filter lucide-react publish --no-git-checks
|
|
||||||
|
|
||||||
- name: Upload package.json
|
|
||||||
uses: actions/upload-artifact@v2
|
|
||||||
with:
|
|
||||||
name: lucide-react-package-json
|
|
||||||
path: packages/lucide-react/package.json
|
|
||||||
|
|
||||||
lucide-react-native:
|
|
||||||
if: github.repository == 'lucide-icons/lucide'
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
needs: pre-build
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
|
|
||||||
- uses: actions/setup-node@v3
|
|
||||||
with:
|
|
||||||
node-version: 16
|
|
||||||
|
|
||||||
- uses: pnpm/action-setup@v2.0.1
|
|
||||||
name: Install pnpm
|
|
||||||
id: pnpm-install
|
|
||||||
with:
|
|
||||||
version: 7
|
|
||||||
run_install: false
|
|
||||||
|
|
||||||
- name: Get pnpm store directory
|
|
||||||
id: pnpm-cache
|
|
||||||
run: |
|
|
||||||
echo "::set-output name=pnpm_cache_dir::$(pnpm store path)"
|
|
||||||
|
|
||||||
- uses: actions/cache@v3
|
|
||||||
name: Setup pnpm cache
|
|
||||||
with:
|
|
||||||
path: ${{ steps.pnpm-cache.outputs.pnpm_cache_dir }}
|
|
||||||
key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}
|
|
||||||
restore-keys: |
|
|
||||||
${{ runner.os }}-pnpm-store-
|
|
||||||
|
|
||||||
- name: Install dependencies
|
|
||||||
run: pnpm install
|
|
||||||
|
|
||||||
- name: Set Auth Token
|
|
||||||
run: npm config set //registry.npmjs.org/:_authToken ${{ secrets.NPM_TOKEN }}
|
|
||||||
|
|
||||||
- name: Set package.json version lucide
|
|
||||||
run: pnpm --filter lucide-react-native version --new-version ${{ needs.pre-build.outputs.VERSION }} --no-git-tag-version
|
|
||||||
|
|
||||||
- name: Build
|
|
||||||
run: pnpm --filter lucide-react-native build
|
|
||||||
|
|
||||||
- name: Test
|
|
||||||
run: pnpm --filter lucide-react-native test
|
|
||||||
|
|
||||||
- name: Publish
|
|
||||||
run: pnpm --filter lucide-react-native publish --no-git-checks
|
|
||||||
|
|
||||||
- name: Upload package.json
|
|
||||||
uses: actions/upload-artifact@v2
|
|
||||||
with:
|
|
||||||
name: lucide-react-native-package-json
|
|
||||||
path: packages/lucide-react-native/package.json
|
|
||||||
|
|
||||||
lucide-vue:
|
|
||||||
if: github.repository == 'lucide-icons/lucide'
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
needs: pre-build
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
|
|
||||||
- uses: actions/setup-node@v3
|
|
||||||
with:
|
|
||||||
node-version: 16
|
|
||||||
|
|
||||||
- uses: pnpm/action-setup@v2.0.1
|
|
||||||
name: Install pnpm
|
|
||||||
id: pnpm-install
|
|
||||||
with:
|
|
||||||
version: 7
|
|
||||||
run_install: false
|
|
||||||
|
|
||||||
- name: Get pnpm store directory
|
|
||||||
id: pnpm-cache
|
|
||||||
run: |
|
|
||||||
echo "::set-output name=pnpm_cache_dir::$(pnpm store path)"
|
|
||||||
|
|
||||||
- uses: actions/cache@v3
|
|
||||||
name: Setup pnpm cache
|
|
||||||
with:
|
|
||||||
path: ${{ steps.pnpm-cache.outputs.pnpm_cache_dir }}
|
|
||||||
key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}
|
|
||||||
restore-keys: |
|
|
||||||
${{ runner.os }}-pnpm-store-
|
|
||||||
|
|
||||||
- name: Install dependencies
|
|
||||||
run: pnpm install
|
|
||||||
|
|
||||||
- name: Set Auth Token
|
|
||||||
run: npm config set //registry.npmjs.org/:_authToken ${{ secrets.NPM_TOKEN }}
|
|
||||||
|
|
||||||
- name: Set new version
|
|
||||||
run: pnpm --filter lucide-vue version --new-version ${{ needs.pre-build.outputs.VERSION }} --no-git-tag-version
|
|
||||||
|
|
||||||
- name: Build
|
|
||||||
run: pnpm --filter lucide-vue build
|
|
||||||
|
|
||||||
- name: Test
|
|
||||||
run: pnpm --filter lucide-vue test
|
|
||||||
|
|
||||||
- name: Publish
|
|
||||||
run: pnpm --filter lucide-vue publish --no-git-checks
|
|
||||||
|
|
||||||
- name: Upload package.json
|
|
||||||
uses: actions/upload-artifact@v2
|
|
||||||
with:
|
|
||||||
name: lucide-vue-package-json
|
|
||||||
path: packages/lucide-vue/package.json
|
|
||||||
|
|
||||||
lucide-vue-next:
|
|
||||||
if: github.repository == 'lucide-icons/lucide'
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
needs: pre-build
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
|
|
||||||
- uses: actions/setup-node@v3
|
|
||||||
with:
|
|
||||||
node-version: 16
|
|
||||||
|
|
||||||
- uses: pnpm/action-setup@v2.0.1
|
|
||||||
name: Install pnpm
|
|
||||||
id: pnpm-install
|
|
||||||
with:
|
|
||||||
version: 7
|
|
||||||
run_install: false
|
|
||||||
|
|
||||||
- name: Get pnpm store directory
|
|
||||||
id: pnpm-cache
|
|
||||||
run: |
|
|
||||||
echo "::set-output name=pnpm_cache_dir::$(pnpm store path)"
|
|
||||||
|
|
||||||
- uses: actions/cache@v3
|
|
||||||
name: Setup pnpm cache
|
|
||||||
with:
|
|
||||||
path: ${{ steps.pnpm-cache.outputs.pnpm_cache_dir }}
|
|
||||||
key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}
|
|
||||||
restore-keys: |
|
|
||||||
${{ runner.os }}-pnpm-store-
|
|
||||||
|
|
||||||
- name: Install dependencies
|
|
||||||
run: pnpm install
|
|
||||||
|
|
||||||
- name: Set Auth Token
|
|
||||||
run: npm config set //registry.npmjs.org/:_authToken ${{ secrets.NPM_TOKEN }}
|
|
||||||
|
|
||||||
- name: Set new version
|
|
||||||
run: pnpm --filter lucide-vue-next version --new-version ${{ needs.pre-build.outputs.VERSION }} --no-git-tag-version
|
|
||||||
|
|
||||||
- name: Build
|
|
||||||
run: pnpm --filter lucide-vue-next build
|
|
||||||
|
|
||||||
- name: Test
|
|
||||||
run: pnpm --filter lucide-vue-next test
|
|
||||||
|
|
||||||
- name: Publish
|
|
||||||
run: pnpm --filter lucide-vue-next publish --no-git-checks
|
|
||||||
|
|
||||||
- name: Upload package.json
|
|
||||||
uses: actions/upload-artifact@v2
|
|
||||||
with:
|
|
||||||
name: lucide-vue-next-package-json
|
|
||||||
path: packages/lucide-vue-next/package.json
|
|
||||||
|
|
||||||
lucide-angular:
|
|
||||||
if: github.repository == 'lucide-icons/lucide'
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
needs: pre-build
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
|
|
||||||
- uses: actions/setup-node@v3
|
|
||||||
with:
|
|
||||||
node-version: 16
|
|
||||||
|
|
||||||
- uses: pnpm/action-setup@v2.0.1
|
|
||||||
name: Install pnpm
|
|
||||||
id: pnpm-install
|
|
||||||
with:
|
|
||||||
version: 7
|
|
||||||
run_install: false
|
|
||||||
|
|
||||||
- name: Get pnpm store directory
|
|
||||||
id: pnpm-cache
|
|
||||||
run: |
|
|
||||||
echo "::set-output name=pnpm_cache_dir::$(pnpm store path)"
|
|
||||||
|
|
||||||
- uses: actions/cache@v3
|
|
||||||
name: Setup pnpm cache
|
|
||||||
with:
|
|
||||||
path: ${{ steps.pnpm-cache.outputs.pnpm_cache_dir }}
|
|
||||||
key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}
|
|
||||||
restore-keys: |
|
|
||||||
${{ runner.os }}-pnpm-store-
|
|
||||||
|
|
||||||
- name: Install dependencies
|
|
||||||
run: pnpm install
|
|
||||||
|
|
||||||
- name: Set Auth Token
|
|
||||||
run: npm config set //registry.npmjs.org/:_authToken ${{ secrets.NPM_TOKEN }}
|
|
||||||
|
|
||||||
- name: Set package.json version lucide
|
|
||||||
run: pnpm --filter lucide-angular version --new-version ${{ needs.pre-build.outputs.VERSION }} --no-git-tag-version
|
|
||||||
|
|
||||||
- name: Build
|
|
||||||
run: pnpm --filter lucide-angular build
|
|
||||||
|
|
||||||
- name: Test
|
|
||||||
run: pnpm --filter lucide-angular test
|
|
||||||
|
|
||||||
- name: Publish
|
|
||||||
run: pnpm --filter lucide-angular publish --no-git-checks --ignore-scripts
|
|
||||||
|
|
||||||
- name: Upload package.json
|
|
||||||
uses: actions/upload-artifact@v2
|
|
||||||
with:
|
|
||||||
name: lucide-angular-package-json
|
|
||||||
path: packages/lucide-angular/package.json
|
|
||||||
|
|
||||||
lucide-preact:
|
|
||||||
if: github.repository == 'lucide-icons/lucide'
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
needs: pre-build
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
|
|
||||||
- uses: actions/setup-node@v3
|
|
||||||
with:
|
|
||||||
node-version: 16
|
|
||||||
|
|
||||||
- uses: pnpm/action-setup@v2.0.1
|
|
||||||
name: Install pnpm
|
|
||||||
id: pnpm-install
|
|
||||||
with:
|
|
||||||
version: 7
|
|
||||||
run_install: false
|
|
||||||
|
|
||||||
- name: Get pnpm store directory
|
|
||||||
id: pnpm-cache
|
|
||||||
run: |
|
|
||||||
echo "::set-output name=pnpm_cache_dir::$(pnpm store path)"
|
|
||||||
|
|
||||||
- uses: actions/cache@v3
|
|
||||||
name: Setup pnpm cache
|
|
||||||
with:
|
|
||||||
path: ${{ steps.pnpm-cache.outputs.pnpm_cache_dir }}
|
|
||||||
key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}
|
|
||||||
restore-keys: |
|
|
||||||
${{ runner.os }}-pnpm-store-
|
|
||||||
|
|
||||||
- name: Install dependencies
|
|
||||||
run: pnpm install
|
|
||||||
|
|
||||||
- name: Set Auth Token
|
|
||||||
run: npm config set //registry.npmjs.org/:_authToken ${{ secrets.NPM_TOKEN }}
|
|
||||||
|
|
||||||
- name: Set package.json version lucide
|
|
||||||
run: pnpm --filter lucide-preact version --new-version ${{ needs.pre-build.outputs.VERSION }} --no-git-tag-version
|
|
||||||
|
|
||||||
- name: Build
|
|
||||||
run: pnpm --filter lucide-preact build
|
|
||||||
|
|
||||||
- name: Test
|
|
||||||
run: pnpm --filter lucide-preact test
|
|
||||||
|
|
||||||
- name: Publish
|
|
||||||
run: pnpm --filter lucide-preact publish --no-git-checks
|
|
||||||
|
|
||||||
- name: Upload package.json
|
|
||||||
uses: actions/upload-artifact@v2
|
|
||||||
with:
|
|
||||||
name: lucide-preact-package-json
|
|
||||||
path: packages/lucide-preact/package.json
|
|
||||||
|
|
||||||
lucide-solid:
|
|
||||||
if: github.repository == 'lucide-icons/lucide'
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
needs: pre-build
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
|
|
||||||
- uses: actions/setup-node@v3
|
|
||||||
with:
|
|
||||||
node-version: 16
|
|
||||||
|
|
||||||
- uses: pnpm/action-setup@v2.0.1
|
|
||||||
name: Install pnpm
|
|
||||||
id: pnpm-install
|
|
||||||
with:
|
|
||||||
version: 7
|
|
||||||
run_install: false
|
|
||||||
|
|
||||||
- name: Get pnpm store directory
|
|
||||||
id: pnpm-cache
|
|
||||||
run: |
|
|
||||||
echo "::set-output name=pnpm_cache_dir::$(pnpm store path)"
|
|
||||||
|
|
||||||
- uses: actions/cache@v3
|
|
||||||
name: Setup pnpm cache
|
|
||||||
with:
|
|
||||||
path: ${{ steps.pnpm-cache.outputs.pnpm_cache_dir }}
|
|
||||||
key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}
|
|
||||||
restore-keys: |
|
|
||||||
${{ runner.os }}-pnpm-store-
|
|
||||||
|
|
||||||
- name: Install dependencies
|
|
||||||
run: pnpm install
|
|
||||||
|
|
||||||
- name: Set Auth Token
|
|
||||||
run: npm config set //registry.npmjs.org/:_authToken ${{ secrets.NPM_TOKEN }}
|
|
||||||
|
|
||||||
- name: Set package.json version lucide
|
|
||||||
run: pnpm --filter lucide-solid version --new-version ${{ needs.pre-build.outputs.VERSION }} --no-git-tag-version
|
|
||||||
|
|
||||||
- name: Build
|
|
||||||
run: pnpm --filter lucide-solid build
|
|
||||||
|
|
||||||
- name: Test
|
|
||||||
run: pnpm --filter lucide-solid test
|
|
||||||
|
|
||||||
- name: Publish
|
|
||||||
run: pnpm --filter lucide-solid publish --no-git-checks
|
|
||||||
|
|
||||||
- name: Upload package.json
|
|
||||||
uses: actions/upload-artifact@v2
|
|
||||||
with:
|
|
||||||
name: lucide-solid-package-json
|
|
||||||
path: packages/lucide-solid/package.json
|
|
||||||
|
|
||||||
lucide-svelte:
|
|
||||||
if: github.repository == 'lucide-icons/lucide'
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
needs: pre-build
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
|
|
||||||
- uses: actions/setup-node@v3
|
|
||||||
with:
|
|
||||||
node-version: 16
|
|
||||||
|
|
||||||
- uses: pnpm/action-setup@v2.0.1
|
|
||||||
name: Install pnpm
|
|
||||||
id: pnpm-install
|
|
||||||
with:
|
|
||||||
version: 7
|
|
||||||
run_install: false
|
|
||||||
|
|
||||||
- name: Get pnpm store directory
|
|
||||||
id: pnpm-cache
|
|
||||||
run: |
|
|
||||||
echo "::set-output name=pnpm_cache_dir::$(pnpm store path)"
|
|
||||||
|
|
||||||
- uses: actions/cache@v3
|
|
||||||
name: Setup pnpm cache
|
|
||||||
with:
|
|
||||||
path: ${{ steps.pnpm-cache.outputs.pnpm_cache_dir }}
|
|
||||||
key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}
|
|
||||||
restore-keys: |
|
|
||||||
${{ runner.os }}-pnpm-store-
|
|
||||||
|
|
||||||
- name: Install dependencies
|
|
||||||
run: pnpm install
|
|
||||||
|
|
||||||
- name: Set Auth Token
|
|
||||||
run: npm config set //registry.npmjs.org/:_authToken ${{ secrets.NPM_TOKEN }}
|
|
||||||
|
|
||||||
- name: Set package.json version lucide
|
|
||||||
run: pnpm --filter lucide-svelte version --new-version ${{ needs.pre-build.outputs.VERSION }} --no-git-tag-version
|
|
||||||
|
|
||||||
- name: Build
|
|
||||||
run: pnpm --filter lucide-svelte build
|
|
||||||
|
|
||||||
- name: Test
|
|
||||||
run: pnpm --filter lucide-svelte test
|
|
||||||
|
|
||||||
- name: Publish
|
|
||||||
run: pnpm --filter lucide-svelte publish --no-git-checks
|
|
||||||
|
|
||||||
- name: Upload package.json
|
|
||||||
uses: actions/upload-artifact@v2
|
|
||||||
with:
|
|
||||||
name: lucide-svelte-package-json
|
|
||||||
path: packages/lucide-svelte/package.json
|
|
||||||
|
|
||||||
lucide-static:
|
lucide-static:
|
||||||
if: github.repository == 'lucide-icons/lucide'
|
if: github.repository == 'lucide-icons/lucide'
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
needs: [pre-build, lucide-font]
|
needs: [pre-release, lucide-font]
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
- uses: actions/download-artifact@v2
|
- uses: actions/download-artifact@v2
|
||||||
|
- uses: pnpm/action-setup@v2
|
||||||
|
with:
|
||||||
|
version: 8
|
||||||
- uses: actions/setup-node@v3
|
- uses: actions/setup-node@v3
|
||||||
with:
|
with:
|
||||||
node-version: 16
|
node-version: 18
|
||||||
|
cache: 'pnpm'
|
||||||
- uses: pnpm/action-setup@v2.0.1
|
|
||||||
name: Install pnpm
|
|
||||||
id: pnpm-install
|
|
||||||
with:
|
|
||||||
version: 7
|
|
||||||
run_install: false
|
|
||||||
|
|
||||||
- name: Get pnpm store directory
|
|
||||||
id: pnpm-cache
|
|
||||||
run: |
|
|
||||||
echo "::set-output name=pnpm_cache_dir::$(pnpm store path)"
|
|
||||||
|
|
||||||
- uses: actions/cache@v3
|
|
||||||
name: Setup pnpm cache
|
|
||||||
with:
|
|
||||||
path: ${{ steps.pnpm-cache.outputs.pnpm_cache_dir }}
|
|
||||||
key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}
|
|
||||||
restore-keys: |
|
|
||||||
${{ runner.os }}-pnpm-store-
|
|
||||||
|
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: pnpm install
|
run: pnpm install --frozen-lockfile
|
||||||
|
|
||||||
- name: Set Auth Token
|
- name: Set Auth Token
|
||||||
run: npm config set //registry.npmjs.org/:_authToken ${{ secrets.NPM_TOKEN }}
|
run: npm config set //registry.npmjs.org/:_authToken ${{ secrets.NPM_TOKEN }}
|
||||||
|
|
||||||
- name: Set new version
|
- name: Set new version
|
||||||
run: pnpm --filter lucide-static version --new-version ${{ needs.pre-build.outputs.VERSION }} --no-git-tag-version
|
run: pnpm --filter lucide-static version --new-version ${{ needs.pre-release.outputs.VERSION }} --no-git-tag-version
|
||||||
|
|
||||||
- name: Move Font
|
- name: Move Font
|
||||||
run: cp -r lucide-font packages/lucide-static/font
|
run: cp -r lucide-font packages/lucide-static/font
|
||||||
@@ -571,54 +112,28 @@ jobs:
|
|||||||
- name: Publish
|
- name: Publish
|
||||||
run: pnpm --filter lucide-static publish --no-git-checks
|
run: pnpm --filter lucide-static publish --no-git-checks
|
||||||
|
|
||||||
- name: Upload package.json
|
|
||||||
uses: actions/upload-artifact@v2
|
|
||||||
with:
|
|
||||||
name: lucide-static-package-json
|
|
||||||
path: packages/lucide-static/package.json
|
|
||||||
|
|
||||||
lucide-font:
|
lucide-font:
|
||||||
if: github.repository == 'lucide-icons/lucide'
|
if: github.repository == 'lucide-icons/lucide'
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
needs: pre-build
|
needs: pre-release
|
||||||
container: ericfennis/lucide-font:latest
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
- uses: actions/setup-node@v3.4.1
|
- uses: pnpm/action-setup@v2
|
||||||
with:
|
with:
|
||||||
node-version: 16
|
version: 8
|
||||||
|
- uses: actions/setup-node@v3
|
||||||
- uses: pnpm/action-setup@v2.0.1
|
|
||||||
name: Install pnpm
|
|
||||||
id: pnpm-install
|
|
||||||
with:
|
with:
|
||||||
version: 7
|
node-version: 18
|
||||||
run_install: false
|
cache: 'pnpm'
|
||||||
|
|
||||||
- name: Get pnpm store directory
|
|
||||||
id: pnpm-cache
|
|
||||||
run: |
|
|
||||||
echo "::set-output name=pnpm_cache_dir::$(pnpm store path)"
|
|
||||||
|
|
||||||
- uses: actions/cache@v3
|
|
||||||
name: Setup pnpm cache
|
|
||||||
with:
|
|
||||||
path: ${{ steps.pnpm-cache.outputs.pnpm_cache_dir }}
|
|
||||||
key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}
|
|
||||||
restore-keys: |
|
|
||||||
${{ runner.os }}-pnpm-store-
|
|
||||||
|
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: pnpm install --filter outline-svg
|
run: pnpm install --frozen-lockfile
|
||||||
|
|
||||||
- name: Outline svg Icons
|
- name: Outline svg Icons
|
||||||
run: pnpm build:outline-icons
|
run: pnpm build:outline-icons
|
||||||
|
|
||||||
- name: Create directory
|
- name: Create font in ./lucide-font
|
||||||
run: mkdir lucide-font
|
run: pnpm build:font
|
||||||
|
|
||||||
- name: Build font
|
|
||||||
run: fontcustom compile "./outlined" -h -n "lucide" -o ./lucide-font -F
|
|
||||||
|
|
||||||
- name: "Upload to Artifacts"
|
- name: "Upload to Artifacts"
|
||||||
uses: actions/upload-artifact@v1
|
uses: actions/upload-artifact@v1
|
||||||
@@ -626,130 +141,26 @@ jobs:
|
|||||||
name: lucide-font
|
name: lucide-font
|
||||||
path: lucide-font
|
path: lucide-font
|
||||||
|
|
||||||
lucide-flutter:
|
|
||||||
if: github.repository == 'lucide-icons/lucide'
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
needs: [pre-build, lucide-font]
|
|
||||||
container:
|
|
||||||
image: cirrusci/flutter:latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
- uses: actions/download-artifact@v2
|
|
||||||
- uses: actions/cache@v2
|
|
||||||
with:
|
|
||||||
path: ~/.pub-cache
|
|
||||||
key: ${{ runner.os }}-pub-${{ hashFiles('~/.pub-cache') }}
|
|
||||||
restore-keys: |
|
|
||||||
${{ runner.os }}-pub-
|
|
||||||
|
|
||||||
- name: Setup credentials
|
|
||||||
run: |
|
|
||||||
mkdir -p ~/.pub-cache
|
|
||||||
cat <<EOF > ~/.pub-cache/credentials.json
|
|
||||||
{
|
|
||||||
"accessToken": "${{ secrets.GOOGLE_OAUTH_ACCESS_TOKEN }}",
|
|
||||||
"refreshToken": "${{ secrets.GOOGLE_OAUTH_REFRESH_TOKEN }}",
|
|
||||||
"idToken": "${{ secrets.GOOGLE_OAUTH_ID_TOKEN }}",
|
|
||||||
"tokenEndpoint":"https://accounts.google.com/o/oauth2/token",
|
|
||||||
"scopes": [ "openid", "https://www.googleapis.com/auth/userinfo.email" ],
|
|
||||||
"expiration": 1629835569218
|
|
||||||
}
|
|
||||||
EOF
|
|
||||||
|
|
||||||
- name: Get packages
|
|
||||||
run: flutter pub get
|
|
||||||
working-directory: packages/lucide-flutter
|
|
||||||
|
|
||||||
- name: List lucide-font folder
|
|
||||||
run: ls lucide-font
|
|
||||||
|
|
||||||
- name: Copy assets from lucide-font directory
|
|
||||||
run: |
|
|
||||||
mkdir packages/lucide-flutter/assets
|
|
||||||
cp lucide-font/lucide.ttf packages/lucide-flutter/assets/lucide.ttf
|
|
||||||
cp lucide-font/lucide-preview.html packages/lucide-flutter/assets/lucide-preview.html
|
|
||||||
|
|
||||||
- name: Generate exports file
|
|
||||||
run: |
|
|
||||||
dart tool/generate_fonts.dart assets/lucide-preview.html
|
|
||||||
flutter format .
|
|
||||||
working-directory: packages/lucide-flutter
|
|
||||||
|
|
||||||
- name: Test
|
|
||||||
run: flutter test
|
|
||||||
working-directory: packages/lucide-flutter
|
|
||||||
|
|
||||||
- name: Copy License
|
|
||||||
run: cp ../../LICENSE ./LICENSE
|
|
||||||
working-directory: packages/lucide-flutter
|
|
||||||
|
|
||||||
- name: Update yaml
|
|
||||||
run: sed -E 's/(version:)[^\n]*/\1 ${{ needs.pre-build.outputs.VERSION }}/;' pubspec.yaml > pubspec && mv pubspec pubspec.yaml
|
|
||||||
working-directory: packages/lucide-flutter
|
|
||||||
|
|
||||||
- name: Flutter publish
|
|
||||||
run: flutter pub publish -f
|
|
||||||
working-directory: packages/lucide-flutter
|
|
||||||
|
|
||||||
- name: Upload pubspec.yaml
|
|
||||||
uses: actions/upload-artifact@v2
|
|
||||||
with:
|
|
||||||
name: lucide-flutter-pubspec-yaml
|
|
||||||
path: packages/lucide-flutter/pubspec.yaml
|
|
||||||
|
|
||||||
post-release:
|
post-release:
|
||||||
if: github.repository == 'lucide-icons/lucide'
|
if: github.repository == 'lucide-icons/lucide'
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
needs:
|
needs: [
|
||||||
[
|
pre-release,
|
||||||
pre-build,
|
lucide-font,
|
||||||
lucide,
|
]
|
||||||
lucide-react,
|
|
||||||
lucide-react-native,
|
|
||||||
lucide-vue,
|
|
||||||
lucide-vue-next,
|
|
||||||
lucide-angular,
|
|
||||||
lucide-svelte,
|
|
||||||
lucide-preact,
|
|
||||||
lucide-flutter,
|
|
||||||
lucide-font,
|
|
||||||
]
|
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
- uses: actions/download-artifact@v2
|
- uses: actions/download-artifact@v2
|
||||||
|
|
||||||
- name: Commit package files
|
|
||||||
run: |
|
|
||||||
mv lucide-package-json/package.json packages/lucide/package.json
|
|
||||||
mv lucide-react-package-json/package.json packages/lucide-react/package.json
|
|
||||||
mv lucide-react-native-package-json/package.json packages/lucide-react-native/package.json
|
|
||||||
mv lucide-vue-package-json/package.json packages/lucide-vue/package.json
|
|
||||||
mv lucide-preact-package-json/package.json packages/lucide-preact/package.json
|
|
||||||
mv lucide-svelte-package-json/package.json packages/lucide-svelte/package.json
|
|
||||||
mv lucide-vue-next-package-json/package.json packages/lucide-vue-next/package.json
|
|
||||||
mv lucide-angular-package-json/package.json packages/lucide-angular/package.json
|
|
||||||
mv lucide-flutter-pubspec-yaml/pubspec.yaml packages/lucide-flutter/pubspec.yaml
|
|
||||||
|
|
||||||
- name: Commit package.jsons
|
|
||||||
run: |
|
|
||||||
git add packages/*/package.json packages/lucide-flutter/pubspec.yaml
|
|
||||||
git -c user.name="Lucide Bot" -c user.email="lucide-bot@users.noreply.github.com" \
|
|
||||||
commit -m ":package: Bump lucide package versions to ${{ needs.pre-build.outputs.VERSION }}" --no-verify --quiet
|
|
||||||
git remote set-url --push origin https://lucide-bot:${{ secrets.GITHUB_TOKEN }}@github.com/$GITHUB_REPOSITORY.git
|
|
||||||
git push origin HEAD:main
|
|
||||||
|
|
||||||
- name: Zip font and icons
|
- name: Zip font and icons
|
||||||
run: |
|
run: |
|
||||||
zip -r lucide-font-${{ needs.pre-build.outputs.VERSION }}.zip lucide-font
|
zip -r lucide-font-${{ needs.pre-release.outputs.VERSION }}.zip lucide-font
|
||||||
zip -r lucide-icons-${{ needs.pre-build.outputs.VERSION }}.zip icons
|
zip -r lucide-icons-${{ needs.pre-release.outputs.VERSION }}.zip icons
|
||||||
|
|
||||||
- name: Release zip and fonts
|
- name: Release zip and fonts
|
||||||
uses: softprops/action-gh-release@v1
|
uses: softprops/action-gh-release@v1
|
||||||
env:
|
|
||||||
GITHUB_TOKEN: ${{ secrets.CREATE_RELEASE_TOKEN }}
|
|
||||||
with:
|
with:
|
||||||
tag_name: v${{ needs.pre-build.outputs.VERSION }}
|
tag_name: ${{ needs.pre-release.outputs.VERSION }}
|
||||||
files: |
|
files: |
|
||||||
lucide-font-${{ needs.pre-build.outputs.VERSION }}.zip
|
lucide-font-${{ needs.pre-release.outputs.VERSION }}.zip
|
||||||
lucide-icons-${{ needs.pre-build.outputs.VERSION }}.zip
|
lucide-icons-${{ needs.pre-release.outputs.VERSION }}.zip
|
||||||
|
|||||||
5
.gitignore
vendored
5
.gitignore
vendored
@@ -17,6 +17,10 @@ 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/dynamicIconImports.ts
|
||||||
|
packages/**/dynamicIconImports.js
|
||||||
|
packages/**/dynamicIconImports.d.ts
|
||||||
|
packages/**/dynamicIconImports.js.map
|
||||||
packages/**/LICENSE
|
packages/**/LICENSE
|
||||||
categories.json
|
categories.json
|
||||||
tags.json
|
tags.json
|
||||||
@@ -30,6 +34,7 @@ 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/iconDetails
|
||||||
docs/.vitepress/data/relatedIcons.json
|
docs/.vitepress/data/relatedIcons.json
|
||||||
docs/.vercel
|
docs/.vercel
|
||||||
docs/.nitro
|
docs/.nitro
|
||||||
|
|||||||
8
.vscode/settings.json
vendored
8
.vscode/settings.json
vendored
@@ -3,5 +3,11 @@
|
|||||||
"devs",
|
"devs",
|
||||||
"preact",
|
"preact",
|
||||||
"Preact"
|
"Preact"
|
||||||
]
|
],
|
||||||
|
"eslint.enable": true,
|
||||||
|
"eslint.validate": [
|
||||||
|
"javascript",
|
||||||
|
"svg"
|
||||||
|
],
|
||||||
|
"svg.preview.background": "transparent"
|
||||||
}
|
}
|
||||||
|
|||||||
95
.vscode/svg.code-snippets
vendored
Normal file
95
.vscode/svg.code-snippets
vendored
Normal file
@@ -0,0 +1,95 @@
|
|||||||
|
{
|
||||||
|
"Lucide SVG": {
|
||||||
|
"scope": "xml",
|
||||||
|
"description": "Base SVG with Lucide attributes.",
|
||||||
|
"prefix": [
|
||||||
|
"svg",
|
||||||
|
"lucide"
|
||||||
|
],
|
||||||
|
"body": [
|
||||||
|
"<svg",
|
||||||
|
" xmlns=\"http://www.w3.org/2000/svg\"",
|
||||||
|
" width=\"24\"",
|
||||||
|
" height=\"24\"",
|
||||||
|
" viewBox=\"0 0 24 24\"",
|
||||||
|
" fill=\"none\"",
|
||||||
|
" stroke=\"currentColor\"",
|
||||||
|
" stroke-width=\"2\"",
|
||||||
|
" stroke-linecap=\"round\"",
|
||||||
|
" stroke-linejoin=\"round\"",
|
||||||
|
">",
|
||||||
|
" $0",
|
||||||
|
"</svg>"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"Rectangle": {
|
||||||
|
"scope": "xml",
|
||||||
|
"description": "SVG `rect`angle, with Lucide defaults.",
|
||||||
|
"prefix": [
|
||||||
|
"rect",
|
||||||
|
"<rect"
|
||||||
|
],
|
||||||
|
"body": "<rect width=\"${1:20}\" height=\"${2:12}\" x=\"${3:2}\" y=\"${4:6}\" rx=\"${5|2,1|}\"/>"
|
||||||
|
},
|
||||||
|
"Square": {
|
||||||
|
"scope": "xml",
|
||||||
|
"description": "SVG square `rect`angle, with Lucide defaults.",
|
||||||
|
"prefix": [
|
||||||
|
"square",
|
||||||
|
"rect",
|
||||||
|
"<rect",
|
||||||
|
"tile"
|
||||||
|
],
|
||||||
|
"body": "<rect width=\"${1:18}\" height=\"$1\" x=\"${2:3}\" y=\"${3:$2}\" rx=\"${4|2,1|}\" />"
|
||||||
|
},
|
||||||
|
"Circle": {
|
||||||
|
"scope": "xml",
|
||||||
|
"description": "SVG `circle`, with Lucide defaults.",
|
||||||
|
"prefix": [
|
||||||
|
"circle",
|
||||||
|
"<circle"
|
||||||
|
],
|
||||||
|
"body": "<circle cx=\"${2:12}\" cy=\"${3:$2}\" r=\"${1|10,2,.5|}\" />"
|
||||||
|
},
|
||||||
|
"Ellipse": {
|
||||||
|
"scope": "xml",
|
||||||
|
"description": "SVG `ellipse`.",
|
||||||
|
"prefix": [
|
||||||
|
"ellipse",
|
||||||
|
"<ellipse"
|
||||||
|
],
|
||||||
|
"body": "<ellipse cx=\"${3:12}\" cy=\"${4:$3}\" rx=\"${1:10}\" ry=\"${2:$1}\" />"
|
||||||
|
},
|
||||||
|
"Path": {
|
||||||
|
"scope": "xml",
|
||||||
|
"description": "SVG custom `path`.",
|
||||||
|
"prefix": [
|
||||||
|
"path",
|
||||||
|
"<path",
|
||||||
|
"polyline",
|
||||||
|
"<polyline",
|
||||||
|
"polygon",
|
||||||
|
"<polygon"
|
||||||
|
],
|
||||||
|
"body": "<path d=\"${1|M,m|}$0\" />"
|
||||||
|
},
|
||||||
|
"Line": {
|
||||||
|
"scope": "xml",
|
||||||
|
"description": "SVG `path`, preffered to `line` in Lucide.",
|
||||||
|
"prefix": [
|
||||||
|
"line",
|
||||||
|
"<line",
|
||||||
|
"minus"
|
||||||
|
],
|
||||||
|
"body": "<path d=\"M${3:5} ${4:12}${1|h,v|}${2:14}\" />"
|
||||||
|
},
|
||||||
|
"Dot": {
|
||||||
|
"scope": "xml",
|
||||||
|
"description": "SVG small dot, within the Lucide guidelines.",
|
||||||
|
"prefix": [
|
||||||
|
"dot",
|
||||||
|
"."
|
||||||
|
],
|
||||||
|
"body": "<path d=\"M ${1:12} ${2:$1}h.01\" />"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -33,7 +33,7 @@ Here you can find instructions on how to implement the guidelines with different
|
|||||||
|
|
||||||
#### [Adobe Illustrator Guide](https://lucide.dev/docs/illustrator-guide)
|
#### [Adobe Illustrator Guide](https://lucide.dev/docs/illustrator-guide)
|
||||||
|
|
||||||
You can also [download an Adobe Illustrator template](https://lucide.dev/templates/illustrator-template.ai).
|
You can also [download an Adobe Illustrator template](https://github.com/lucide-icons/lucide/blob/main/docs/public/templates/illustrator_template.ai).
|
||||||
|
|
||||||
#### [Inkscape Guide](https://lucide.dev/docs/inkscape-guide)
|
#### [Inkscape Guide](https://lucide.dev/docs/inkscape-guide)
|
||||||
|
|
||||||
|
|||||||
22
README.md
22
README.md
@@ -18,7 +18,7 @@ Lucide is trying to expand the icon set as much as possible while staying faithf
|
|||||||
### Why choose Lucide over Feather Icons
|
### Why choose Lucide over Feather Icons
|
||||||
|
|
||||||
- More icons to work with: Lucide already has hundreds of icons more than Feather does.
|
- More icons to work with: Lucide already has hundreds of icons more than Feather does.
|
||||||
- Official librairies and integrations with popular frameworks and design tools.
|
- Official libraries and integrations with popular frameworks and design tools.
|
||||||
- Well maintained code base.
|
- Well maintained code base.
|
||||||
- Active community, regularly growing and improving the set.
|
- Active community, regularly growing and improving the set.
|
||||||
|
|
||||||
@@ -35,7 +35,6 @@ Lucide is trying to expand the icon set as much as possible while staying faithf
|
|||||||
- [Static (svg sprite, font, icons ..)](#static-svg-sprite-font-icons-)
|
- [Static (svg sprite, font, icons ..)](#static-svg-sprite-font-icons-)
|
||||||
- [Figma](#figma)
|
- [Figma](#figma)
|
||||||
- [Laravel](#laravel)
|
- [Laravel](#laravel)
|
||||||
- [Flutter](#flutter)
|
|
||||||
- [Svelte](#svelte)
|
- [Svelte](#svelte)
|
||||||
- [Solid](#solid)
|
- [Solid](#solid)
|
||||||
- [Hyva](#hyva)
|
- [Hyva](#hyva)
|
||||||
@@ -166,8 +165,8 @@ For more details, see the [documentation](https://github.com/lucide-icons/lucide
|
|||||||
### Static (svg sprite, font, icons ..)
|
### Static (svg sprite, font, icons ..)
|
||||||
|
|
||||||
Assets:
|
Assets:
|
||||||
[Font Files](https://github.com/lucide-icons/lucide/releases/tag/latest)
|
[Font Files](https://github.com/lucide-icons/lucide/releases/latest)
|
||||||
[SVG Files](https://github.com/lucide-icons/lucide/releases/tag/latest)
|
[SVG Files](https://github.com/lucide-icons/lucide/releases/latest)
|
||||||
[SVG Sprite](https://cdn.jsdelivr.net/npm/lucide-static@latest/sprite.svg)
|
[SVG Sprite](https://cdn.jsdelivr.net/npm/lucide-static@latest/sprite.svg)
|
||||||
|
|
||||||
NPM package
|
NPM package
|
||||||
@@ -200,16 +199,6 @@ composer require mallardduck/blade-lucide-icons
|
|||||||
|
|
||||||
For more details, see the [documentation](https://github.com/mallardduck/blade-lucide-icons/blob/main/README.md).
|
For more details, see the [documentation](https://github.com/mallardduck/blade-lucide-icons/blob/main/README.md).
|
||||||
|
|
||||||
### Flutter
|
|
||||||
|
|
||||||
Implementation of Lucide icon library for Flutter applications.
|
|
||||||
|
|
||||||
```sh
|
|
||||||
flutter pub add lucide_icons
|
|
||||||
```
|
|
||||||
|
|
||||||
For more details, see the [pub.dev](https://pub.dev/packages/lucide_icons).
|
|
||||||
|
|
||||||
### Svelte
|
### Svelte
|
||||||
|
|
||||||
Implementation of the lucide icon library for Svelte applications.
|
Implementation of the lucide icon library for Svelte applications.
|
||||||
@@ -285,6 +274,9 @@ 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="./site/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>
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"$schema": "../category.schema.json",
|
"$schema": "../category.schema.json",
|
||||||
"title": "Transportation",
|
"title": "Transportation",
|
||||||
"icon": "train"
|
"icon": "train-front"
|
||||||
}
|
}
|
||||||
@@ -12,9 +12,11 @@
|
|||||||
},
|
},
|
||||||
"title": "Lucide Icons category schema",
|
"title": "Lucide Icons category schema",
|
||||||
"type": "object",
|
"type": "object",
|
||||||
|
"additionalProperties": false,
|
||||||
|
"required": ["$schema", "icon", "title"],
|
||||||
"properties": {
|
"properties": {
|
||||||
"title": {
|
"$schema": {
|
||||||
"type": "string"
|
"const": "../category.schema.json"
|
||||||
},
|
},
|
||||||
"description": {
|
"description": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
@@ -22,13 +24,12 @@
|
|||||||
"icon": {
|
"icon": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
|
"title": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
"weight": {
|
"weight": {
|
||||||
"type": "integer"
|
"type": "integer"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"required": [
|
|
||||||
"title",
|
|
||||||
"icon"
|
|
||||||
],
|
|
||||||
"description": "A JSON Schema for categories defined by Lucide Icons."
|
"description": "A JSON Schema for categories defined by Lucide Icons."
|
||||||
}
|
}
|
||||||
|
|||||||
11
docs/.vitepress/api/categories/index.get.ts
Normal file
11
docs/.vitepress/api/categories/index.get.ts
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
import { eventHandler, setResponseHeader } from 'h3'
|
||||||
|
import iconMetaData from '../../data/iconMetaData'
|
||||||
|
|
||||||
|
export default eventHandler((event) => {
|
||||||
|
setResponseHeader(event, 'Cache-Control', 'public, max-age=86400')
|
||||||
|
setResponseHeader(event, 'Access-Control-Allow-Origin', '*')
|
||||||
|
|
||||||
|
return Object.fromEntries(
|
||||||
|
Object.entries(iconMetaData).map(([name, { categories }]) => [ name, categories ])
|
||||||
|
)
|
||||||
|
})
|
||||||
@@ -1,41 +1,53 @@
|
|||||||
import { eventHandler, setResponseHeader, defaultContentType } from 'h3'
|
import { eventHandler, setResponseHeader, defaultContentType } from 'h3';
|
||||||
import { renderToString, renderToStaticMarkup } from 'react-dom/server'
|
import { renderToString, renderToStaticMarkup } from 'react-dom/server';
|
||||||
import { createElement } from 'react'
|
import { createElement } from 'react';
|
||||||
import SvgPreview from '../../lib/SvgPreview/index.tsx';
|
import SvgPreview from '../../lib/SvgPreview/index.tsx';
|
||||||
import iconNodes from '../../data/iconNodes'
|
import iconNodes from '../../data/iconNodes';
|
||||||
import createLucideIcon from 'lucide-react/src/createLucideIcon'
|
import createLucideIcon from 'lucide-react/src/createLucideIcon';
|
||||||
import Backdrop from '../../lib/SvgPreview/Backdrop.tsx';
|
import Backdrop from '../../lib/SvgPreview/Backdrop.tsx';
|
||||||
|
|
||||||
export default eventHandler((event) => {
|
export default eventHandler((event) => {
|
||||||
const { params } = event.context
|
const { params } = event.context;
|
||||||
|
|
||||||
const [name, svgData] = params.data.split('/');
|
const pathData = params.data.split('/');
|
||||||
const data = svgData.slice(0, -4);
|
const data = pathData.at(-1).slice(0, -4);
|
||||||
|
const [name] = pathData;
|
||||||
|
|
||||||
const src = Buffer.from(data, 'base64').toString('utf8');
|
const src = Buffer.from(data, 'base64').toString('utf8');
|
||||||
|
|
||||||
const children = []
|
const children = [];
|
||||||
|
|
||||||
if (name in iconNodes) {
|
// Finds the longest matching icon to be use as the backdrop.
|
||||||
const iconNode = iconNodes[name]
|
// For `square-dashed-bottom-code` it suggests `square-dashed-bottom-code`.
|
||||||
|
// For `square-dashed-bottom-i-dont-exist` it suggests `square-dashed-bottom`.
|
||||||
|
const backdropName = name
|
||||||
|
.split('-')
|
||||||
|
.map((_, idx, arr) => arr.slice(0, idx + 1).join('-'))
|
||||||
|
.reverse()
|
||||||
|
.find((groupName) => groupName in iconNodes);
|
||||||
|
if (backdropName) {
|
||||||
|
const iconNode = iconNodes[backdropName];
|
||||||
|
|
||||||
const LucideIcon = createLucideIcon(name, 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.replace(/<svg[^>]*>|<\/svg>/g, '');
|
||||||
|
|
||||||
children.push(createElement(Backdrop, { backdropString, src }))
|
children.push(
|
||||||
|
createElement(Backdrop, {
|
||||||
|
backdropString,
|
||||||
|
src,
|
||||||
|
color: name in iconNodes ? 'red' : '#777',
|
||||||
|
})
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const svg = Buffer.from(
|
const svg = Buffer.from(
|
||||||
// We can't use jsx here, is not supported here by nitro.
|
// We can't use jsx here, is not supported here by nitro.
|
||||||
renderToString(createElement(SvgPreview, {src, showGrid: true}, children)).replace(
|
renderToString(createElement(SvgPreview, { src, showGrid: true }, children))
|
||||||
/>/,
|
|
||||||
'><style>@media screen and (prefers-color-scheme: dark) { svg { stroke: #fff } }</style>'
|
|
||||||
)
|
|
||||||
).toString('utf8');
|
).toString('utf8');
|
||||||
|
|
||||||
defaultContentType(event, 'image/svg+xml')
|
defaultContentType(event, 'image/svg+xml');
|
||||||
setResponseHeader(event, 'Cache-Control', 'public,max-age=31536000')
|
setResponseHeader(event, 'Cache-Control', 'public,max-age=31536000');
|
||||||
|
|
||||||
return svg
|
return svg;
|
||||||
})
|
});
|
||||||
|
|||||||
73
docs/.vitepress/api/gh-icon/dpi/[...data].get.ts
Normal file
73
docs/.vitepress/api/gh-icon/dpi/[...data].get.ts
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
import { eventHandler, setResponseHeader, defaultContentType } from 'h3';
|
||||||
|
import { Resvg, initWasm } from '@resvg/resvg-wasm';
|
||||||
|
import wasm from './loadWasm';
|
||||||
|
|
||||||
|
var initializedResvg = initWasm(wasm);
|
||||||
|
|
||||||
|
export default eventHandler(async (event) => {
|
||||||
|
const { params = {} } = event.context;
|
||||||
|
await initializedResvg;
|
||||||
|
|
||||||
|
const imageSize = 96;
|
||||||
|
const [iconSizeString, svgData] = params.data.split('/');
|
||||||
|
const iconSize = parseInt(iconSizeString, 10);
|
||||||
|
const data = svgData.slice(0, -4);
|
||||||
|
|
||||||
|
const src = Buffer.from(data, 'base64').toString('utf8');
|
||||||
|
const svg = (src.includes('<svg') ? src : `<svg>${src}</svg>`)
|
||||||
|
.replace(/(\r\n|\n|\r)/gm, '')
|
||||||
|
.replace(
|
||||||
|
/<svg[^>]*/,
|
||||||
|
`<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width="${iconSize}"
|
||||||
|
height="${iconSize}"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
fill="none"
|
||||||
|
stroke="#fff"
|
||||||
|
stroke-width="2"
|
||||||
|
stroke-linecap="round"
|
||||||
|
stroke-linejoin="round"
|
||||||
|
`
|
||||||
|
);
|
||||||
|
|
||||||
|
const resvg = new Resvg(svg, { background: '#000' });
|
||||||
|
const pngData = resvg.render();
|
||||||
|
const pngBuffer = Buffer.from(pngData.asPng());
|
||||||
|
|
||||||
|
defaultContentType(event, 'image/svg+xml');
|
||||||
|
setResponseHeader(event, 'Cache-Control', 'public,max-age=31536000');
|
||||||
|
|
||||||
|
return `
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="${imageSize}" height="${imageSize}" viewBox="0 0 ${imageSize} ${imageSize}">
|
||||||
|
<style>
|
||||||
|
@media screen and (prefers-color-scheme: light) {
|
||||||
|
#fallback-background { fill: transparent; }
|
||||||
|
}
|
||||||
|
@media screen and (prefers-color-scheme: dark) {
|
||||||
|
#fallback-background { fill: transparent; }
|
||||||
|
rect { fill: #fff; }
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<mask id="mask">
|
||||||
|
<image
|
||||||
|
width="${imageSize}"
|
||||||
|
height="${imageSize}"
|
||||||
|
href="data:image/png;base64,${pngBuffer.toString('base64')}"
|
||||||
|
image-rendering="pixelated"
|
||||||
|
/>
|
||||||
|
</mask>
|
||||||
|
<rect
|
||||||
|
id="fallback-background"
|
||||||
|
width="${imageSize}"
|
||||||
|
height="${imageSize}" ry="${imageSize / 24}"
|
||||||
|
fill="#fff"
|
||||||
|
/>
|
||||||
|
<rect
|
||||||
|
width="${imageSize}"
|
||||||
|
height="${imageSize}"
|
||||||
|
fill="#000"
|
||||||
|
mask="url(#mask)"
|
||||||
|
/>
|
||||||
|
</svg>`;
|
||||||
|
});
|
||||||
15
docs/.vitepress/api/gh-icon/dpi/loadWasm.ts
Normal file
15
docs/.vitepress/api/gh-icon/dpi/loadWasm.ts
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
import fs from 'fs';
|
||||||
|
import module from 'node:module';
|
||||||
|
/* WASM_IMPORT */
|
||||||
|
|
||||||
|
let wasm;
|
||||||
|
|
||||||
|
if (process.env.NODE_ENV === 'development') {
|
||||||
|
const require = module.createRequire(import.meta.url);
|
||||||
|
|
||||||
|
wasm = fs.readFileSync(require.resolve('@resvg/resvg-wasm/index_bg.wasm'));
|
||||||
|
} else {
|
||||||
|
wasm = resvg_wasm;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default wasm;
|
||||||
44
docs/.vitepress/api/gh-icon/stroke-width/[...data].get.ts
Normal file
44
docs/.vitepress/api/gh-icon/stroke-width/[...data].get.ts
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
import { eventHandler, setResponseHeader, defaultContentType } from 'h3'
|
||||||
|
import { renderToString } from 'react-dom/server'
|
||||||
|
import { createElement } from 'react'
|
||||||
|
import SvgPreview from '../../../lib/SvgPreview/index.tsx';
|
||||||
|
import createLucideIcon, { IconNode } from 'lucide-react/src/createLucideIcon'
|
||||||
|
import { parseSync } from 'svgson';
|
||||||
|
|
||||||
|
export default eventHandler((event) => {
|
||||||
|
const { params } = event.context
|
||||||
|
|
||||||
|
const [strokeWidth, svgData] = params.data.split('/');
|
||||||
|
const data = svgData.slice(0, -4);
|
||||||
|
|
||||||
|
const src = Buffer.from(data, 'base64').toString('utf8');
|
||||||
|
|
||||||
|
const Icon = createLucideIcon(
|
||||||
|
'icon',
|
||||||
|
parseSync(src.includes('<svg') ? src : `<svg>${src}</svg>`).children.map(
|
||||||
|
({ name, attributes }) => [name, attributes]
|
||||||
|
) as IconNode
|
||||||
|
);
|
||||||
|
|
||||||
|
const svg = Buffer.from(
|
||||||
|
// We can't use jsx here, is not supported here by nitro.
|
||||||
|
renderToString(createElement(Icon, { strokeWidth }))
|
||||||
|
.replace(/fill\="none"/, 'fill="#fff"')
|
||||||
|
.replace(
|
||||||
|
/>/,
|
||||||
|
`><style>
|
||||||
|
@media screen and (prefers-color-scheme: light) {
|
||||||
|
svg { fill: transparent !important; }
|
||||||
|
}
|
||||||
|
@media screen and (prefers-color-scheme: dark) {
|
||||||
|
svg { stroke: #fff; fill: transparent !important; }
|
||||||
|
}
|
||||||
|
</style>`
|
||||||
|
)
|
||||||
|
).toString('utf8');
|
||||||
|
|
||||||
|
defaultContentType(event, 'image/svg+xml')
|
||||||
|
setResponseHeader(event, 'Cache-Control', 'public,max-age=31536000')
|
||||||
|
|
||||||
|
return svg
|
||||||
|
})
|
||||||
@@ -8,6 +8,7 @@ export default eventHandler((event) => {
|
|||||||
const withUniqueKeys = query.withUniqueKeys === 'true'
|
const withUniqueKeys = query.withUniqueKeys === 'true'
|
||||||
|
|
||||||
setResponseHeader(event, 'Cache-Control', 'public, max-age=86400')
|
setResponseHeader(event, 'Cache-Control', 'public, max-age=86400')
|
||||||
|
setResponseHeader(event, 'Access-Control-Allow-Origin', '*')
|
||||||
|
|
||||||
if (withUniqueKeys) {
|
if (withUniqueKeys) {
|
||||||
return iconNodes
|
return iconNodes
|
||||||
|
|||||||
@@ -38,6 +38,7 @@ export default eventHandler((event) => {
|
|||||||
|
|
||||||
defaultContentType(event, 'image/svg+xml')
|
defaultContentType(event, 'image/svg+xml')
|
||||||
setResponseHeader(event, 'Cache-Control', 'public,max-age=31536000')
|
setResponseHeader(event, 'Cache-Control', 'public,max-age=31536000')
|
||||||
|
setResponseHeader(event, 'Access-Control-Allow-Origin', '*')
|
||||||
|
|
||||||
return svg
|
return svg
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import iconMetaData from '../../data/iconMetaData'
|
|||||||
|
|
||||||
export default eventHandler((event) => {
|
export default eventHandler((event) => {
|
||||||
setResponseHeader(event, 'Cache-Control', 'public, max-age=86400')
|
setResponseHeader(event, 'Cache-Control', 'public, max-age=86400')
|
||||||
|
setResponseHeader(event, 'Access-Control-Allow-Origin', '*')
|
||||||
|
|
||||||
return Object.fromEntries(
|
return Object.fromEntries(
|
||||||
Object.entries(iconMetaData).map(([name, { tags }]) => [ name, tags ])
|
Object.entries(iconMetaData).map(([name, { tags }]) => [ name, tags ])
|
||||||
|
|||||||
@@ -1,14 +1,18 @@
|
|||||||
import { fileURLToPath, URL } from 'node:url'
|
import { fileURLToPath, URL } from 'node:url'
|
||||||
import path from 'path';
|
|
||||||
import { defineConfig } from 'vitepress'
|
import { defineConfig } from 'vitepress'
|
||||||
import sidebar from './sidebar';
|
import sidebar from './sidebar';
|
||||||
|
|
||||||
|
const title = "Lucide";
|
||||||
|
const socialTitle = "Lucide Icons";
|
||||||
|
const description = "Beautiful & consistent icon toolkit made by the community."
|
||||||
|
|
||||||
// https://vitepress.dev/reference/site-config
|
// https://vitepress.dev/reference/site-config
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
|
title,
|
||||||
|
description,
|
||||||
cleanUrls: true,
|
cleanUrls: true,
|
||||||
title: "Lucide",
|
|
||||||
description: "Beautiful & consistent icon toolkit made by the community.",
|
|
||||||
outDir: '.vercel/output/static',
|
outDir: '.vercel/output/static',
|
||||||
|
srcExclude: ['**/README.md'],
|
||||||
vite: {
|
vite: {
|
||||||
resolve: {
|
resolve: {
|
||||||
alias: [
|
alias: [
|
||||||
@@ -25,17 +29,70 @@ export default defineConfig({
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
head: [
|
head: [
|
||||||
[
|
[ 'script', {
|
||||||
'script',
|
src: 'https://analytics.lucide.dev/js/script.js',
|
||||||
{
|
'data-domain': 'lucide.dev',
|
||||||
src: 'https://plausible.io/js/script.js',
|
defer: ''
|
||||||
'data-domain': 'lucide.dev',
|
}],
|
||||||
defer: ''
|
[ 'meta', {
|
||||||
}
|
property:"og:locale",
|
||||||
],
|
content:"en_US"
|
||||||
|
}],
|
||||||
|
[ 'meta', {
|
||||||
|
property:"og:type",
|
||||||
|
content:"website"
|
||||||
|
}],
|
||||||
|
[ 'meta', {
|
||||||
|
property:"og:site_name",
|
||||||
|
content: title,
|
||||||
|
}],
|
||||||
|
[ 'meta', {
|
||||||
|
property:"og:title",
|
||||||
|
content: socialTitle,
|
||||||
|
}],
|
||||||
|
[ 'meta', {
|
||||||
|
property:"og:description",
|
||||||
|
content: description
|
||||||
|
}],
|
||||||
|
[ 'meta', {
|
||||||
|
property:"og:url",
|
||||||
|
content:"https://lucide.dev"
|
||||||
|
}],
|
||||||
|
[ 'meta', {
|
||||||
|
property:"og:image",
|
||||||
|
content: "https://lucide.dev/og.png"
|
||||||
|
}],
|
||||||
|
[ 'meta', {
|
||||||
|
property:"og:image:width",
|
||||||
|
content:"1200"
|
||||||
|
}],
|
||||||
|
[ 'meta', {
|
||||||
|
property:"og:image:height",
|
||||||
|
content:"630"
|
||||||
|
}],
|
||||||
|
[ 'meta', {
|
||||||
|
property:"og:image:type",
|
||||||
|
content:"image/png"
|
||||||
|
}],
|
||||||
|
[ 'meta', {
|
||||||
|
property:"twitter:card",
|
||||||
|
content:"summary_large_image"
|
||||||
|
}],
|
||||||
|
[ 'meta', {
|
||||||
|
property:"twitter:title",
|
||||||
|
content: socialTitle,
|
||||||
|
}],
|
||||||
|
[ 'meta', {
|
||||||
|
property:"twitter:description",
|
||||||
|
content: description
|
||||||
|
}],
|
||||||
|
[ 'meta', {
|
||||||
|
property:"twitter:image",
|
||||||
|
content:"https://lucide.dev/og.png"
|
||||||
|
}],
|
||||||
],
|
],
|
||||||
themeConfig: {
|
themeConfig: {
|
||||||
// https://vitepress.dev/reference/default-theme-config
|
// https://vitepress.dev/reference/default-theme-config
|
||||||
@@ -44,9 +101,10 @@ export default defineConfig({
|
|||||||
dark: '/logo.dark.svg'
|
dark: '/logo.dark.svg'
|
||||||
},
|
},
|
||||||
nav: [
|
nav: [
|
||||||
{ text: 'Icons', link: '/icons/index.md' },
|
{ text: 'Icons', link: '/icons/' },
|
||||||
{ text: 'Guide', link: '/guide/' },
|
{ text: 'Guide', link: '/guide/' },
|
||||||
{ text: 'Packages', link: '/packages' },
|
{ text: 'Packages', link: '/packages' },
|
||||||
|
{ text: 'Showcase', link: '/showcase' },
|
||||||
{ text: 'License', link: '/license' },
|
{ text: 'License', link: '/license' },
|
||||||
],
|
],
|
||||||
sidebar,
|
sidebar,
|
||||||
@@ -61,5 +119,8 @@ export default defineConfig({
|
|||||||
editLink: {
|
editLink: {
|
||||||
pattern: 'https://github.com/lucide-icons/lucide/edit/main/docs/:path'
|
pattern: 'https://github.com/lucide-icons/lucide/edit/main/docs/:path'
|
||||||
},
|
},
|
||||||
|
},
|
||||||
|
sitemap: {
|
||||||
|
hostname: 'https://lucide.dev/'
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
50
docs/.vitepress/data/companiesData.json
Normal file
50
docs/.vitepress/data/companiesData.json
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"name": "Vercel",
|
||||||
|
"url": "https://vercel.com",
|
||||||
|
"image": {
|
||||||
|
"light": "/company-logos/vercel-light.svg",
|
||||||
|
"dark": "/company-logos/vercel-dark.svg"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Supabase",
|
||||||
|
"url": "https://supabase.com",
|
||||||
|
"image": {
|
||||||
|
"light": "/company-logos/supabase-light.svg",
|
||||||
|
"dark": "/company-logos/supabase-dark.svg"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Obsidian",
|
||||||
|
"url": "https://obsidian.md",
|
||||||
|
"image": {
|
||||||
|
"light": "/company-logos/obsidian-light.svg",
|
||||||
|
"dark": "/company-logos/obsidian-dark.svg"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Open Collective",
|
||||||
|
"url": "https://opencollective.com",
|
||||||
|
"image": {
|
||||||
|
"light": "/company-logos/open-collective-light.svg",
|
||||||
|
"dark": "/company-logos/open-collective-dark.svg"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Super",
|
||||||
|
"url": "https://super.so",
|
||||||
|
"image": {
|
||||||
|
"light": "/company-logos/super-light.svg",
|
||||||
|
"dark": "/company-logos/super-dark.svg"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Noodle",
|
||||||
|
"url": "https://noodle.run/",
|
||||||
|
"image": {
|
||||||
|
"light": "/company-logos/noodle-light.svg",
|
||||||
|
"dark": "/company-logos/noodle-dark.svg"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
18
docs/.vitepress/data/componentLibrariesData.json
Normal file
18
docs/.vitepress/data/componentLibrariesData.json
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"name": "Shadcn/ui",
|
||||||
|
"url": "https://ui.shadcn.com/",
|
||||||
|
"image": {
|
||||||
|
"light": "/library-logos/shadcn-ui-light.svg",
|
||||||
|
"dark": "/library-logos/shadcn-ui-dark.svg"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Tamagui",
|
||||||
|
"url": "https://tamagui.dev/",
|
||||||
|
"image": {
|
||||||
|
"light": "/library-logos/tamagui.svg",
|
||||||
|
"dark": "/library-logos/tamagui.svg"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
@@ -1,11 +1,12 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
interface BackdropProps {
|
interface BackdropProps {
|
||||||
src: string
|
src: string;
|
||||||
backdropString: string
|
color?: string;
|
||||||
|
backdropString: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Backdrop = ({ src, backdropString }: BackdropProps): JSX.Element => {
|
const Backdrop = ({ src, color = 'red', backdropString }: BackdropProps): JSX.Element => {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<defs xmlns="http://www.w3.org/2000/svg">
|
<defs xmlns="http://www.w3.org/2000/svg">
|
||||||
@@ -16,8 +17,8 @@ const Backdrop = ({ src, backdropString }: BackdropProps): JSX.Element => {
|
|||||||
patternUnits="userSpaceOnUse"
|
patternUnits="userSpaceOnUse"
|
||||||
patternTransform="rotate(45 50 50)"
|
patternTransform="rotate(45 50 50)"
|
||||||
>
|
>
|
||||||
<line stroke="red" strokeWidth={0.1} y2={1} />
|
<line stroke={color} strokeWidth={0.1} y2={1} />
|
||||||
<line stroke="red" strokeWidth={0.1} y2={1} />
|
<line stroke={color} strokeWidth={0.1} y2={1} />
|
||||||
</pattern>
|
</pattern>
|
||||||
</defs>
|
</defs>
|
||||||
<mask id="svg-preview-backdrop-mask-outline" maskUnits="userSpaceOnUse">
|
<mask id="svg-preview-backdrop-mask-outline" maskUnits="userSpaceOnUse">
|
||||||
@@ -29,20 +30,8 @@ const Backdrop = ({ src, backdropString }: BackdropProps): JSX.Element => {
|
|||||||
<g dangerouslySetInnerHTML={{ __html: src }} strokeWidth={2.05} />
|
<g dangerouslySetInnerHTML={{ __html: src }} strokeWidth={2.05} />
|
||||||
<g strokeWidth={1.75} dangerouslySetInnerHTML={{ __html: backdropString }} />
|
<g strokeWidth={1.75} dangerouslySetInnerHTML={{ __html: backdropString }} />
|
||||||
</mask>
|
</mask>
|
||||||
<g
|
<g strokeWidth={2.25} stroke="url(#pattern)" mask={'url(#svg-preview-backdrop-mask-outline)'}>
|
||||||
strokeWidth={2.25}
|
<rect x="0" y="0" width="24" height="24" fill="url(#pattern)" opacity={0.5} stroke="none" />
|
||||||
stroke="url(#pattern)"
|
|
||||||
mask={'url(#svg-preview-backdrop-mask-outline)'}
|
|
||||||
>
|
|
||||||
<rect
|
|
||||||
x="0"
|
|
||||||
y="0"
|
|
||||||
width="24"
|
|
||||||
height="24"
|
|
||||||
fill="url(#pattern)"
|
|
||||||
opacity={0.5}
|
|
||||||
stroke="none"
|
|
||||||
/>
|
|
||||||
</g>
|
</g>
|
||||||
<rect
|
<rect
|
||||||
x="0"
|
x="0"
|
||||||
@@ -58,14 +47,13 @@ const Backdrop = ({ src, backdropString }: BackdropProps): JSX.Element => {
|
|||||||
y="0"
|
y="0"
|
||||||
width="24"
|
width="24"
|
||||||
height="24"
|
height="24"
|
||||||
fill="red"
|
fill={color}
|
||||||
opacity={0.5}
|
opacity={0.5}
|
||||||
stroke="none"
|
stroke="none"
|
||||||
mask={'url(#svg-preview-backdrop-mask-fill)'}
|
mask={'url(#svg-preview-backdrop-mask-fill)'}
|
||||||
/>
|
/>
|
||||||
</>
|
</>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
|
|
||||||
export default Backdrop;
|
export default Backdrop;
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import { getPaths, assert } from './utils';
|
|||||||
|
|
||||||
const Grid = ({
|
const Grid = ({
|
||||||
radius,
|
radius,
|
||||||
fill,
|
fill = '#fff',
|
||||||
...props
|
...props
|
||||||
}: {
|
}: {
|
||||||
strokeWidth: number;
|
strokeWidth: number;
|
||||||
@@ -12,6 +12,7 @@ const Grid = ({
|
|||||||
} & PathProps<'stroke', 'strokeWidth'>) => (
|
} & PathProps<'stroke', 'strokeWidth'>) => (
|
||||||
<g className="svg-preview-grid-group" strokeLinecap="butt" {...props}>
|
<g className="svg-preview-grid-group" strokeLinecap="butt" {...props}>
|
||||||
<rect
|
<rect
|
||||||
|
className="svg-preview-grid-rect"
|
||||||
width={24 - props.strokeWidth}
|
width={24 - props.strokeWidth}
|
||||||
height={24 - props.strokeWidth}
|
height={24 - props.strokeWidth}
|
||||||
x={props.strokeWidth / 2}
|
x={props.strokeWidth / 2}
|
||||||
@@ -198,6 +199,28 @@ const Radii = ({
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const Handles = ({
|
||||||
|
paths,
|
||||||
|
...props
|
||||||
|
}: { paths: Path[] } & PathProps<
|
||||||
|
'strokeWidth' | 'stroke' | 'strokeDasharray' | 'strokeOpacity',
|
||||||
|
any
|
||||||
|
>) => {
|
||||||
|
console.log(paths);
|
||||||
|
return (
|
||||||
|
<g className="svg-preview-handles-group" {...props}>
|
||||||
|
{paths.map(({ c, prev, next, cp1, cp2 }) => (
|
||||||
|
<>
|
||||||
|
{cp1 && <path d={`M${prev.x} ${prev.y} ${cp1.x} ${cp1.y}`} />}
|
||||||
|
{cp1 && <circle cy={cp1.y} cx={cp1.x} r={0.25} />}
|
||||||
|
{cp2 && <path d={`M${next.x} ${next.y} ${cp2.x} ${cp2.y}`} />}
|
||||||
|
{cp2 && <circle cy={cp2.y} cx={cp2.x} r={0.25} />}
|
||||||
|
</>
|
||||||
|
))}
|
||||||
|
</g>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
const SvgPreview = React.forwardRef<
|
const SvgPreview = React.forwardRef<
|
||||||
SVGSVGElement,
|
SVGSVGElement,
|
||||||
{
|
{
|
||||||
@@ -207,7 +230,12 @@ 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: dark) {
|
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-grid-group,
|
||||||
.svg-preview-radii-group,
|
.svg-preview-radii-group,
|
||||||
.svg-preview-shadow-mask-group,
|
.svg-preview-shadow-mask-group,
|
||||||
@@ -232,6 +260,7 @@ const SvgPreview = React.forwardRef<
|
|||||||
<style>{darkModeCss}</style>
|
<style>{darkModeCss}</style>
|
||||||
{showGrid && <Grid strokeWidth={0.1} stroke="#777" strokeOpacity={0.3} radius={1} />}
|
{showGrid && <Grid strokeWidth={0.1} stroke="#777" strokeOpacity={0.3} radius={1} />}
|
||||||
<Shadow paths={paths} strokeWidth={4} stroke="#777" radius={1} strokeOpacity={0.15} />
|
<Shadow paths={paths} strokeWidth={4} stroke="#777" radius={1} strokeOpacity={0.15} />
|
||||||
|
<Handles paths={paths} strokeWidth={0.12} stroke="#777" strokeOpacity={0.6} />
|
||||||
<ColoredPath
|
<ColoredPath
|
||||||
paths={paths}
|
paths={paths}
|
||||||
colors={[
|
colors={[
|
||||||
@@ -257,6 +286,7 @@ const SvgPreview = React.forwardRef<
|
|||||||
strokeOpacity={0.3}
|
strokeOpacity={0.3}
|
||||||
/>
|
/>
|
||||||
<ControlPath radius={1} paths={paths} pointSize={1} stroke="#fff" strokeWidth={0.125} />
|
<ControlPath radius={1} paths={paths} pointSize={1} stroke="#fff" strokeWidth={0.125} />
|
||||||
|
<Handles paths={paths} strokeWidth={0.12} stroke="#FFF" strokeOpacity={0.3} />
|
||||||
{children}
|
{children}
|
||||||
</svg>
|
</svg>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -8,7 +8,9 @@ export type Path = {
|
|||||||
prev: Point;
|
prev: Point;
|
||||||
next: Point;
|
next: Point;
|
||||||
isStart: boolean;
|
isStart: boolean;
|
||||||
circle: { x: number; y: number; r: number };
|
circle?: { x: number; y: number; r: number };
|
||||||
|
cp1?: Point;
|
||||||
|
cp2?: Point;
|
||||||
c: ReturnType<typeof getCommands>[number];
|
c: ReturnType<typeof getCommands>[number];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -63,7 +63,7 @@ export const getPaths = (src: string) => {
|
|||||||
c: typeof commands[number],
|
c: typeof commands[number],
|
||||||
next: Point,
|
next: Point,
|
||||||
d?: string,
|
d?: string,
|
||||||
circle?: Path['circle']
|
extras?: { circle?: Path['circle']; cp1?: Path['cp1']; cp2?: Path['cp2'] }
|
||||||
) => {
|
) => {
|
||||||
assert(prev);
|
assert(prev);
|
||||||
paths.push({
|
paths.push({
|
||||||
@@ -71,7 +71,7 @@ export const getPaths = (src: string) => {
|
|||||||
d: d || `M ${prev.x} ${prev.y} L ${next.x} ${next.y}`,
|
d: d || `M ${prev.x} ${prev.y} L ${next.x} ${next.y}`,
|
||||||
prev,
|
prev,
|
||||||
next,
|
next,
|
||||||
circle,
|
...extras,
|
||||||
isStart: start === prev,
|
isStart: start === prev,
|
||||||
});
|
});
|
||||||
prev = next;
|
prev = next;
|
||||||
@@ -110,7 +110,10 @@ export const getPaths = (src: string) => {
|
|||||||
}
|
}
|
||||||
case SVGPathData.CURVE_TO: {
|
case SVGPathData.CURVE_TO: {
|
||||||
assert(prev);
|
assert(prev);
|
||||||
addPath(c, c, `M ${prev.x} ${prev.y} ${encodeSVGPath(c)}`);
|
addPath(c, c, `M ${prev.x} ${prev.y} ${encodeSVGPath(c)}`, {
|
||||||
|
cp1: { x: c.x1, y: c.y1 },
|
||||||
|
cp2: { x: c.x2, y: c.y2 },
|
||||||
|
});
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SVGPathData.SMOOTH_CURVE_TO: {
|
case SVGPathData.SMOOTH_CURVE_TO: {
|
||||||
@@ -146,13 +149,20 @@ export const getPaths = (src: string) => {
|
|||||||
y1: prev.y - reflectedCp1.y,
|
y1: prev.y - reflectedCp1.y,
|
||||||
x2: c.x2,
|
x2: c.x2,
|
||||||
y2: c.y2,
|
y2: c.y2,
|
||||||
})}`
|
})}`,
|
||||||
|
{
|
||||||
|
cp1: reflectedCp1,
|
||||||
|
cp2: { x: c.x2, y: c.y2 },
|
||||||
|
}
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SVGPathData.QUAD_TO: {
|
case SVGPathData.QUAD_TO: {
|
||||||
assert(prev);
|
assert(prev);
|
||||||
addPath(c, c, `M ${prev.x} ${prev.y} ${encodeSVGPath(c)}`);
|
addPath(c, c, `M ${prev.x} ${prev.y} ${encodeSVGPath(c)}`, {
|
||||||
|
cp1: { x: c.x1, y: c.y1 },
|
||||||
|
cp2: { x: c.x1, y: c.y1 },
|
||||||
|
});
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SVGPathData.SMOOTH_QUAD_TO: {
|
case SVGPathData.SMOOTH_QUAD_TO: {
|
||||||
@@ -197,7 +207,11 @@ export const getPaths = (src: string) => {
|
|||||||
y: c.y,
|
y: c.y,
|
||||||
x1: prevCP.x,
|
x1: prevCP.x,
|
||||||
y1: prevCP.y,
|
y1: prevCP.y,
|
||||||
})}`
|
})}`,
|
||||||
|
{
|
||||||
|
cp1: { x: prevCP.x, y: prevCP.y },
|
||||||
|
cp2: { x: prevCP.x, y: prevCP.y },
|
||||||
|
}
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -218,7 +232,7 @@ export const getPaths = (src: string) => {
|
|||||||
c,
|
c,
|
||||||
c,
|
c,
|
||||||
`M ${prev.x} ${prev.y} A${c.rX} ${c.rY} ${c.xRot} ${c.lArcFlag} ${c.sweepFlag} ${c.x} ${c.y}`,
|
`M ${prev.x} ${prev.y} A${c.rX} ${c.rY} ${c.xRot} ${c.lArcFlag} ${c.sweepFlag} ${c.x} ${c.y}`,
|
||||||
c.rX === c.rY ? { ...center, r: c.rX } : undefined
|
{ circle: c.rX === c.rY ? { ...center, r: c.rX } : undefined }
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ const getIconCodes = (): CodeExampleType => {
|
|||||||
codes: [
|
codes: [
|
||||||
{
|
{
|
||||||
language: 'html',
|
language: 'html',
|
||||||
code: `<i data-lucide-name="Name"></i>
|
code: `<i data-lucide="Name"></i>
|
||||||
`,
|
`,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -8,14 +8,6 @@ const DATE_OF_FORK = '2020-06-08T16:39:52+0100';
|
|||||||
|
|
||||||
const directory = path.join(process.cwd(), "../icons");
|
const directory = path.join(process.cwd(), "../icons");
|
||||||
|
|
||||||
export function getAllNames() {
|
|
||||||
const fileNames = fs.readdirSync(directory).filter((file) => path.extname(file) === '.json');
|
|
||||||
|
|
||||||
return fileNames
|
|
||||||
.filter((fileName) => fs.existsSync(directory + '/' + path.basename(fileName, '.json') + '.svg'))
|
|
||||||
.map((fileName) => path.basename(fileName, '.json'));
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface GetDataOptions {
|
export interface GetDataOptions {
|
||||||
withChildKeys?: boolean
|
withChildKeys?: boolean
|
||||||
}
|
}
|
||||||
@@ -49,7 +41,7 @@ export async function getData(name: string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export async function getAllData(): Promise<{ name: string, iconNode: IconNodeWithKeys}[]> {
|
export async function getAllData(): Promise<{ name: string, iconNode: IconNodeWithKeys}[]> {
|
||||||
const names = getAllNames();
|
const names = Object.keys(iconNodes);
|
||||||
|
|
||||||
return Promise.all(names.map((name) => getData(name)));
|
return Promise.all(names.map((name) => getData(name)));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,26 +10,49 @@ const sidebar: UserConfig<DefaultTheme.Config>['themeConfig']['sidebar'] = {
|
|||||||
{ text: 'Comparison', link: '/guide/comparison' }
|
{ text: 'Comparison', link: '/guide/comparison' }
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
text: 'Basics',
|
||||||
|
items: [
|
||||||
|
{
|
||||||
|
text: 'Color',
|
||||||
|
link: '/guide/basics/color'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: 'Sizing',
|
||||||
|
link: '/guide/basics/sizing'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: 'Stroke width',
|
||||||
|
link: '/guide/basics/stroke-width'
|
||||||
|
},
|
||||||
|
]
|
||||||
|
},
|
||||||
|
// TODO: Add this section
|
||||||
// {
|
// {
|
||||||
// text: 'Using Icons',
|
// text: 'Advanced',
|
||||||
// items: [
|
// items: [
|
||||||
// {
|
// {
|
||||||
// text: 'How to use icons',
|
|
||||||
// link: 'how-to-use-icons'
|
|
||||||
// },
|
|
||||||
// {
|
|
||||||
// text: 'Styling icons',
|
|
||||||
// link: 'styling-icons'
|
|
||||||
// },
|
|
||||||
// {
|
|
||||||
// text: 'Accessibility',
|
// text: 'Accessibility',
|
||||||
// link: 'accessibility'
|
// link: '/guide/advanced/accessibility'
|
||||||
// },
|
// },
|
||||||
// {
|
// {
|
||||||
// text: 'What should I use',
|
// text: 'Global styling',
|
||||||
// link: 'what-should-i-use'
|
|
||||||
// },
|
// },
|
||||||
|
// {
|
||||||
|
// text: 'Animations',
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// text: 'Filled icons',
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// text: 'Combining icons',
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// text: 'Dynamic imports'
|
||||||
|
// },
|
||||||
|
// // {
|
||||||
|
// // text: 'Auto importing'
|
||||||
|
// // },
|
||||||
// ]
|
// ]
|
||||||
// },
|
// },
|
||||||
{
|
{
|
||||||
@@ -103,15 +126,9 @@ const sidebar: UserConfig<DefaultTheme.Config>['themeConfig']['sidebar'] = {
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
// This should be here to keep the sidebar shown on the icons page
|
||||||
'icons': [
|
'icons': [
|
||||||
{ text: '', link: '/' },
|
{ text: '', link: '/' },
|
||||||
// { text: 'Categorized', link: '/icons/categorized' },
|
|
||||||
// {
|
|
||||||
// text: 'Categories',
|
|
||||||
// items: [
|
|
||||||
// ...(getAllCategoryFiles().map((category) => ({ text: category, link: `/icons/category/${category}` })))
|
|
||||||
// ]
|
|
||||||
// }
|
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -7,5 +7,6 @@
|
|||||||
<style scoped>
|
<style scoped>
|
||||||
.container {
|
.container {
|
||||||
padding: 32px;
|
padding: 32px;
|
||||||
|
padding-top: 48px;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ const component = computed(() => props.href ? 'a' : 'div')
|
|||||||
border-radius: 6px;
|
border-radius: 6px;
|
||||||
background-color: var(--vp-c-bg-alt);
|
background-color: var(--vp-c-bg-alt);
|
||||||
color: var(--vp-c-text-1);
|
color: var(--vp-c-text-1);
|
||||||
|
text-decoration: none;
|
||||||
/* width: 56px;
|
/* width: 56px;
|
||||||
height: 56px; */
|
height: 56px; */
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
|
|||||||
56
docs/.vitepress/theme/components/base/Card.vue
Normal file
56
docs/.vitepress/theme/components/base/Card.vue
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { computed } from 'vue';
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
href?: string;
|
||||||
|
}>()
|
||||||
|
|
||||||
|
const isExternal = computed(() => {
|
||||||
|
return props.href?.startsWith('http') ?? false
|
||||||
|
})
|
||||||
|
|
||||||
|
const component = computed(() => {
|
||||||
|
return props.href ? 'a' : 'div'
|
||||||
|
})
|
||||||
|
|
||||||
|
const rel = computed(() => {
|
||||||
|
return isExternal.value ? 'noreferrer noopener' : undefined
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<component
|
||||||
|
:is="component"
|
||||||
|
:href="href"
|
||||||
|
:rel="rel"
|
||||||
|
class="card"
|
||||||
|
>
|
||||||
|
<slot />
|
||||||
|
</component>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.card {
|
||||||
|
border: 1px solid var(--vp-c-bg-soft);
|
||||||
|
border-radius: 12px;
|
||||||
|
background-color: var(--vp-c-bg-soft);
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
padding: 24px;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card[href] {
|
||||||
|
display: block;
|
||||||
|
border: 1px solid var(--vp-c-bg-soft);
|
||||||
|
border-radius: 12px;
|
||||||
|
height: 100%;
|
||||||
|
background-color: var(--vp-c-bg-soft);
|
||||||
|
transition: border-color .25s,background-color .25s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card[href]:hover {
|
||||||
|
border-color: var(--vp-c-brand-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
</style>
|
||||||
36
docs/.vitepress/theme/components/base/CardGrid.vue
Normal file
36
docs/.vitepress/theme/components/base/CardGrid.vue
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
<template>
|
||||||
|
<div class="grid">
|
||||||
|
<slot />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.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>
|
||||||
63
docs/.vitepress/theme/components/base/GridSection.vue
Normal file
63
docs/.vitepress/theme/components/base/GridSection.vue
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { computed } from 'vue';
|
||||||
|
import CardGrid from './CardGrid.vue';
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
title: string,
|
||||||
|
headingLevel: 1 | 2 | 3 | 4 | 5 | 6,
|
||||||
|
}>()
|
||||||
|
|
||||||
|
const headingElement = computed(() => `h${props.headingLevel}`)
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<section>
|
||||||
|
<component :is="headingElement" class="name">{{ title }}</component>
|
||||||
|
<CardGrid>
|
||||||
|
<slot />
|
||||||
|
</CardGrid>
|
||||||
|
</section>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.name {
|
||||||
|
font-size: 32px;
|
||||||
|
font-weight: bold;
|
||||||
|
text-align: center;
|
||||||
|
margin-bottom: 32px;
|
||||||
|
}
|
||||||
|
|
||||||
|
section {
|
||||||
|
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>
|
||||||
55
docs/.vitepress/theme/components/base/Tooltip.vue
Normal file
55
docs/.vitepress/theme/components/base/Tooltip.vue
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import {onMounted, ref} from 'vue';
|
||||||
|
import {useFloating, offset, shift} from '@floating-ui/vue';
|
||||||
|
|
||||||
|
const reference = ref(null);
|
||||||
|
const tooltip = ref(null);
|
||||||
|
const middleware = ref([shift(), offset(8)]);
|
||||||
|
const { floatingStyles, update } = useFloating(reference, tooltip, {
|
||||||
|
middleware,
|
||||||
|
transform: false
|
||||||
|
});
|
||||||
|
|
||||||
|
defineProps<{
|
||||||
|
title: string
|
||||||
|
}>()
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
update()
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<span ref="reference" class="reference">
|
||||||
|
<slot/>
|
||||||
|
</span>
|
||||||
|
<div ref="tooltip" class="tooltip" :style="floatingStyles">
|
||||||
|
{{title}}
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.reference:hover + .tooltip{
|
||||||
|
opacity: 1;
|
||||||
|
transform: scale(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.tooltip {
|
||||||
|
display: block;
|
||||||
|
font-size: 12px;
|
||||||
|
line-height: 20px;
|
||||||
|
transform: scale(0.9);
|
||||||
|
font-weight: 400;
|
||||||
|
background: var(--vp-c-brand-dark);
|
||||||
|
color: white;
|
||||||
|
z-index: 10;
|
||||||
|
white-space: nowrap;
|
||||||
|
padding: 2px 8px;
|
||||||
|
border-radius: 4px;
|
||||||
|
box-shadow: var(--vp-shadow-1);
|
||||||
|
opacity: 0;
|
||||||
|
pointer-events: none;
|
||||||
|
transition: cubic-bezier(0.19, 1, 0.22, 1) .2s;
|
||||||
|
transition-property: opacity, transform;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -10,7 +10,7 @@ import { data } from './HomeHeroBefore.data'
|
|||||||
:href="`https://github.com/lucide-icons/lucide/releases/tag/${data.version}`"
|
:href="`https://github.com/lucide-icons/lucide/releases/tag/${data.version}`"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
rel="noreferrer noopener"
|
rel="noreferrer noopener"
|
||||||
>{{ data.version }}</Badge>
|
>v{{ data.version }}</Badge>
|
||||||
</HomeContainer>
|
</HomeContainer>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|||||||
@@ -64,7 +64,7 @@ watch(absoluteStrokeWidth, (enabled) => {
|
|||||||
<ResetButton @click="resetStyle"></ResetButton>
|
<ResetButton @click="resetStyle"></ResetButton>
|
||||||
</h2>
|
</h2>
|
||||||
<p class="copy">
|
<p class="copy">
|
||||||
Lucide has a lot of customization options to match the icons with you UI.
|
Lucide has a lot of customization options to match the icons with your UI.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<div class="customizer">
|
<div class="customizer">
|
||||||
|
|||||||
@@ -1,48 +1,50 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { onMounted } from 'vue'
|
import { onMounted } from 'vue';
|
||||||
import { useCategoryView } from '../../composables/useCategoryView'
|
import { useCategoryView } from '../../composables/useCategoryView';
|
||||||
|
|
||||||
interface Header {
|
interface Header {
|
||||||
level: number
|
level: number;
|
||||||
title: string
|
title: string;
|
||||||
slug: string
|
slug: string;
|
||||||
iconCount: number
|
iconCount: number;
|
||||||
link: string
|
link: string;
|
||||||
children: Header[]
|
children: Header[];
|
||||||
}
|
}
|
||||||
|
|
||||||
type MenuItem = Omit<Header, 'slug' | 'children'> & {
|
type MenuItem = Omit<Header, 'slug' | 'children'> & {
|
||||||
children?: MenuItem[]
|
children?: MenuItem[];
|
||||||
}
|
};
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
headers: MenuItem[]
|
headers: MenuItem[];
|
||||||
root?: boolean
|
root?: boolean;
|
||||||
}>()
|
}>();
|
||||||
|
|
||||||
const { selectedCategory } = useCategoryView()
|
const { selectedCategory } = useCategoryView();
|
||||||
|
|
||||||
function onClick(event: Event) {
|
function onClick(event: Event) {
|
||||||
const target = (event.target as HTMLElement).nodeName === 'span' ? (event.target as HTMLElement).parentNode : event.target as HTMLElement
|
const target =
|
||||||
const id = '#' + (target as HTMLAnchorElement).href!.split('#')[1]
|
(event.target as HTMLElement).nodeName === 'span'
|
||||||
const decodedId = decodeURIComponent(id)
|
? (event.target as HTMLElement).parentNode
|
||||||
|
: (event.target as HTMLElement);
|
||||||
|
const href = (target as HTMLAnchorElement)?.href;
|
||||||
|
|
||||||
selectedCategory.value = decodedId.replace('#', '')
|
if (href) {
|
||||||
|
const id = '#' + href.split('#')[1];
|
||||||
|
const decodedId = decodeURIComponent(id);
|
||||||
|
|
||||||
const heading = document.querySelector<HTMLAnchorElement>(decodedId)
|
selectedCategory.value = decodedId.replace('#', '');
|
||||||
heading?.focus()
|
|
||||||
|
const heading = document.querySelector<HTMLAnchorElement>(decodedId);
|
||||||
|
heading?.focus();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<ul :class="root ? 'root' : 'nested'">
|
<ul :class="root ? 'root' : 'nested'">
|
||||||
<li v-for="{ children, link, title, iconCount } in headers">
|
<li v-for="{ children, link, title, iconCount } in headers">
|
||||||
<a
|
<a class="outline-link" :href="link" @click="onClick" :title="title">
|
||||||
class="outline-link"
|
|
||||||
:href="link"
|
|
||||||
@click="onClick"
|
|
||||||
:title="title"
|
|
||||||
>
|
|
||||||
<span>
|
<span>
|
||||||
{{ title }}
|
{{ title }}
|
||||||
</span>
|
</span>
|
||||||
|
|||||||
@@ -3,19 +3,9 @@ import { ref } from 'vue';
|
|||||||
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';
|
||||||
|
import getSVGIcon from '../../utils/getSVGIcon';
|
||||||
|
import downloadData from '../../utils/downloadData';
|
||||||
|
|
||||||
const allowedAttrs = [
|
|
||||||
'xmlns',
|
|
||||||
'width',
|
|
||||||
'height',
|
|
||||||
'viewBox',
|
|
||||||
'fill',
|
|
||||||
'stroke',
|
|
||||||
'stroke-width',
|
|
||||||
'stroke-linecap',
|
|
||||||
'stroke-linejoin',
|
|
||||||
'class',
|
|
||||||
]
|
|
||||||
const downloadText = 'Download!'
|
const downloadText = 'Download!'
|
||||||
const copiedText = 'Copied!'
|
const copiedText = 'Copied!'
|
||||||
const confettiText = ref(copiedText)
|
const confettiText = ref(copiedText)
|
||||||
@@ -28,24 +18,6 @@ const { size } = useIconStyleContext()
|
|||||||
|
|
||||||
const { animate, confetti } = useConfetti()
|
const { animate, confetti } = useConfetti()
|
||||||
|
|
||||||
function getSVGIcon() {
|
|
||||||
const svg = document.querySelector('#previewer svg')
|
|
||||||
if (!svg) return
|
|
||||||
|
|
||||||
const clonedSvg = svg.cloneNode(true) as SVGElement
|
|
||||||
|
|
||||||
// Filter out attributes that are not allowed in SVGs
|
|
||||||
for (const attr of Array.from(clonedSvg.attributes)) {
|
|
||||||
if (!allowedAttrs.includes(attr.name)) {
|
|
||||||
clonedSvg.removeAttribute(attr.name)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const svgString = new XMLSerializer().serializeToString(clonedSvg)
|
|
||||||
|
|
||||||
return svgString
|
|
||||||
}
|
|
||||||
|
|
||||||
function copySVG() {
|
function copySVG() {
|
||||||
confettiText.value = copiedText
|
confettiText.value = copiedText
|
||||||
const svgString = getSVGIcon()
|
const svgString = getSVGIcon()
|
||||||
@@ -70,11 +42,7 @@ function downloadSVG() {
|
|||||||
confettiText.value = downloadText
|
confettiText.value = downloadText
|
||||||
const svgString = getSVGIcon()
|
const svgString = getSVGIcon()
|
||||||
|
|
||||||
const link = document.createElement('a');
|
downloadData(`${props.name}.svg`, `data:image/svg+xml;base64,${btoa(svgString)}`)
|
||||||
link.download = `${props.name}.svg`;
|
|
||||||
link.href = `data:image/svg+xml;base64,${btoa(svgString)}`
|
|
||||||
link.click();
|
|
||||||
|
|
||||||
confetti()
|
confetti()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -91,12 +59,7 @@ function downloadPNG() {
|
|||||||
image.src = `data:image/svg+xml;base64,${btoa(svgString)}`;
|
image.src = `data:image/svg+xml;base64,${btoa(svgString)}`;
|
||||||
image.onload = function() {
|
image.onload = function() {
|
||||||
ctx.drawImage(image, 0, 0);
|
ctx.drawImage(image, 0, 0);
|
||||||
|
downloadData(`${props.name}.png`, canvas.toDataURL('image/png'))
|
||||||
const link = document.createElement('a');
|
|
||||||
link.download = `${props.name}.png`;
|
|
||||||
link.href = canvas.toDataURL('image/png')
|
|
||||||
link.click();
|
|
||||||
|
|
||||||
confetti()
|
confetti()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,30 +1,45 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import type { IconEntity } from '../../types'
|
import type { IconEntity } from '../../types'
|
||||||
import { computed, ref, watch } from 'vue'
|
import { computed, ref, watch } from 'vue'
|
||||||
import createLucideIcon from 'lucide-vue-next/src/createLucideIcon';
|
import createLucideIcon from 'lucide-vue-next/src/createLucideIcon';
|
||||||
import IconButton from '../base/IconButton.vue';
|
import IconButton from '../base/IconButton.vue';
|
||||||
import IconContributors from './IconContributors.vue';
|
import IconContributors from './IconContributors.vue';
|
||||||
import IconPreview from './IconPreview.vue';
|
import IconPreview from './IconPreview.vue';
|
||||||
import { x, expand } from '../../../data/iconNodes'
|
import { x, expand } from '../../../data/iconNodes'
|
||||||
import { useRouter } from 'vitepress';
|
import { useRouter } from 'vitepress';
|
||||||
import IconInfo from './IconInfo.vue';
|
import IconInfo from './IconInfo.vue';
|
||||||
import Badge from '../base/Badge.vue';
|
import Badge from '../base/Badge.vue';
|
||||||
|
import { computedAsync } from '@vueuse/core';
|
||||||
|
import { satisfies } from 'semver';
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
icon: IconEntity
|
iconName: string
|
||||||
}>()
|
}>()
|
||||||
|
|
||||||
const emit = defineEmits(['close'])
|
const icon = computedAsync<IconEntity | null>(async () => {
|
||||||
const isOpen = computed(() => !!props.icon)
|
if (props.iconName) {
|
||||||
|
return (await import(`../../../data/iconDetails/${props.iconName}.ts`)).default as IconEntity
|
||||||
function onClose() {
|
|
||||||
emit('close')
|
|
||||||
}
|
}
|
||||||
|
return null
|
||||||
|
}, null)
|
||||||
|
|
||||||
const { go } = useRouter()
|
const emit = defineEmits(['close'])
|
||||||
|
const isOpen = computed(() => !!icon.value)
|
||||||
|
|
||||||
const CloseIcon = createLucideIcon('Close', x)
|
function releaseTagLink(version) {
|
||||||
const Expand = createLucideIcon('Expand', expand)
|
const shouldAddV = satisfies(version, `<0.266.0`)
|
||||||
|
|
||||||
|
return `https://github.com/lucide-icons/lucide/releases/tag/${shouldAddV ? 'v' : ''}${version}`
|
||||||
|
}
|
||||||
|
|
||||||
|
function onClose() {
|
||||||
|
emit('close')
|
||||||
|
}
|
||||||
|
|
||||||
|
const { go } = useRouter()
|
||||||
|
|
||||||
|
const CloseIcon = createLucideIcon('Close', x)
|
||||||
|
const Expand = createLucideIcon('Expand', expand)
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
@@ -35,7 +50,7 @@
|
|||||||
<Badge
|
<Badge
|
||||||
v-if="icon.createdRelease"
|
v-if="icon.createdRelease"
|
||||||
class="version"
|
class="version"
|
||||||
:href="`https://github.com/lucide-icons/lucide/releases/tag/v${icon.createdRelease.version}`"
|
:href="releaseTagLink(icon.createdRelease.version)"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
rel="noreferrer noopener"
|
rel="noreferrer noopener"
|
||||||
>v{{ icon.createdRelease.version }}</Badge>
|
>v{{ icon.createdRelease.version }}</Badge>
|
||||||
@@ -109,9 +124,8 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.icon-info {
|
.icon-info {
|
||||||
padding: 0 24px;
|
padding-left: 24px;
|
||||||
flex-basis: 100%;
|
flex-basis: 100%;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.icon-tags {
|
.icon-tags {
|
||||||
|
|||||||
@@ -43,5 +43,6 @@ function setActiveIcon(name: string) {
|
|||||||
|
|
||||||
.icon {
|
.icon {
|
||||||
aspect-ratio: 1/1;
|
aspect-ratio: 1/1;
|
||||||
|
position: relative;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ const { go } = useRouter()
|
|||||||
const { page } = useData()
|
const { page } = useData()
|
||||||
|
|
||||||
const tags = computed(() => {
|
const tags = computed(() => {
|
||||||
if (!props.icon) return []
|
if (!props.icon || !props?.icon?.tags) return []
|
||||||
return props.icon.tags.join(' • ')
|
return props.icon.tags.join(' • ')
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
@@ -27,9 +27,11 @@ const tags = computed(() => {
|
|||||||
<IconDetailName class="icon-name">
|
<IconDetailName class="icon-name">
|
||||||
{{ icon.name }}
|
{{ icon.name }}
|
||||||
</IconDetailName>
|
</IconDetailName>
|
||||||
<p class="icon-tags">
|
<div class="tags-scroller" v-if="tags.length">
|
||||||
{{ tags }}
|
<p class="icon-tags horizontal-scroller">
|
||||||
</p>
|
{{ tags }}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
<div class="group">
|
<div class="group">
|
||||||
<Badge
|
<Badge
|
||||||
v-for="category in icon.categories"
|
v-for="category in icon.categories"
|
||||||
@@ -72,9 +74,61 @@ const tags = computed(() => {
|
|||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
color: var(--vp-c-text-2);
|
color: var(--vp-c-text-2);
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
margin-top: 0;;
|
|
||||||
margin-bottom: 16px;
|
|
||||||
line-height: 28px;
|
line-height: 28px;
|
||||||
|
white-space: nowrap;
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
margin-top: 0;
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tags-scroller {
|
||||||
|
position: relative;
|
||||||
|
max-width: 100%;
|
||||||
|
width: 100%;
|
||||||
|
height: 28px;
|
||||||
|
padding: 8px 0 16px;
|
||||||
|
margin-bottom: 16px;
|
||||||
|
margin-top: 8px;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
--gradient-background: var(--tags-gradient-background, var(--vp-c-bg-elv))
|
||||||
|
}
|
||||||
|
.horizontal-scroller {
|
||||||
|
overflow-x: scroll;
|
||||||
|
/* Hide Scrollbar */
|
||||||
|
-ms-overflow-style: none;
|
||||||
|
scrollbar-width: none;
|
||||||
|
scrollbar-width: thin; /* can also be normal, or none, to not render scrollbar */
|
||||||
|
scrollbar-color: currentColor transparent; /* foreground background */
|
||||||
|
}
|
||||||
|
.horizontal-scroller::-webkit-scrollbar {
|
||||||
|
width: 0;
|
||||||
|
display: none
|
||||||
|
}
|
||||||
|
|
||||||
|
.horizontal-scroller::-webkit-scrollbar-track {
|
||||||
|
background: transparent
|
||||||
|
}
|
||||||
|
|
||||||
|
.horizontal-scroller::-webkit-scrollbar-thumb {
|
||||||
|
background: transparent;
|
||||||
|
border: none
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.tags-scroller::after {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
bottom: 0;
|
||||||
|
width: 32px;
|
||||||
|
height: 100%;
|
||||||
|
/* Background Gradient left to right */
|
||||||
|
background: linear-gradient(to right, rgba(255,255,255,0) 0%,var(--gradient-background) 100%);
|
||||||
|
right: 0;
|
||||||
|
pointer-events: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.buttons {
|
.buttons {
|
||||||
|
|||||||
@@ -2,13 +2,17 @@
|
|||||||
import createLucideIcon from 'lucide-vue-next/src/createLucideIcon';
|
import createLucideIcon from 'lucide-vue-next/src/createLucideIcon';
|
||||||
import { useMediaQuery } from '@vueuse/core';
|
import { useMediaQuery } from '@vueuse/core';
|
||||||
import { useRouter } from 'vitepress';
|
import { useRouter } from 'vitepress';
|
||||||
|
import getSVGIcon from '../../utils/getSVGIcon';
|
||||||
|
import useConfetti from '../../composables/useConfetti';
|
||||||
|
import Tooltip from '../base/Tooltip.vue';
|
||||||
|
|
||||||
|
const downloadText = 'Download!'
|
||||||
|
const copiedText = 'Copied!'
|
||||||
|
|
||||||
export type IconNode = [elementName: string, attrs: Record<string, string>][]
|
export type IconNode = [elementName: string, attrs: Record<string, string>][]
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
name: string;
|
name: string;
|
||||||
// tags: string[];
|
|
||||||
// categories: string[];
|
|
||||||
iconNode: IconNode;
|
iconNode: IconNode;
|
||||||
active: boolean;
|
active: boolean;
|
||||||
customizable?: boolean;
|
customizable?: boolean;
|
||||||
@@ -20,40 +24,65 @@ const emit = defineEmits(['setActiveIcon'])
|
|||||||
|
|
||||||
const { go } = useRouter()
|
const { go } = useRouter()
|
||||||
const showOverlay = useMediaQuery('(min-width: 860px)');
|
const showOverlay = useMediaQuery('(min-width: 860px)');
|
||||||
|
const { animate, confetti, confettiText } = useConfetti()
|
||||||
|
|
||||||
|
|
||||||
const icon = createLucideIcon(props.name, props.iconNode)
|
const icon = createLucideIcon(props.name, props.iconNode)
|
||||||
|
|
||||||
function navigateToIcon() {
|
async function navigateToIcon(event) {
|
||||||
|
|
||||||
|
if (event.shiftKey) {
|
||||||
|
event.preventDefault()
|
||||||
|
const svgString = getSVGIcon(event.target.firstChild, {
|
||||||
|
class: `lucide lucide-${props.name}`,
|
||||||
|
})
|
||||||
|
|
||||||
|
await navigator.clipboard.writeText(svgString)
|
||||||
|
|
||||||
|
confettiText.value = copiedText
|
||||||
|
confetti()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
if(props.overlayMode && showOverlay.value) {
|
if(props.overlayMode && showOverlay.value) {
|
||||||
|
event.preventDefault()
|
||||||
window.history.pushState({}, '', `/icons/${props.name}`)
|
window.history.pushState({}, '', `/icons/${props.name}`)
|
||||||
emit('setActiveIcon', props.name)
|
emit('setActiveIcon', props.name)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
event.preventDefault()
|
||||||
go(`/icons/${props.name}`)
|
go(`/icons/${props.name}`)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<button
|
<Tooltip :title="name">
|
||||||
class="icon-button"
|
<a
|
||||||
@click="navigateToIcon"
|
class="icon-button confetti-button vp-raw"
|
||||||
:class="{ 'active' : active }"
|
@click="navigateToIcon"
|
||||||
:data-title="name"
|
:class="{ active, animate }"
|
||||||
:aria-label="name"
|
:aria-label="name"
|
||||||
:href="`/icons/${props.name}`"
|
:href="`/icons/${props.name}`"
|
||||||
>
|
:data-confetti-text="confettiText"
|
||||||
<KeepAlive>
|
ref="ref"
|
||||||
<component
|
>
|
||||||
v-if="!hideIcon"
|
<KeepAlive>
|
||||||
:is="icon"
|
<component
|
||||||
class="lucide-icon"
|
v-if="!hideIcon"
|
||||||
:class="{ customizable }"
|
:is="icon"
|
||||||
/>
|
class="lucide-icon"
|
||||||
</KeepAlive>
|
:class="{
|
||||||
</button>
|
customizable,
|
||||||
|
}"
|
||||||
|
/>
|
||||||
|
</KeepAlive>
|
||||||
|
</a>
|
||||||
|
</Tooltip>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
<style src="./confetti.css" />
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.icon-button {
|
.icon-button {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
@@ -72,35 +101,13 @@ function navigateToIcon() {
|
|||||||
color: var(--vp-c-text-1);
|
color: var(--vp-c-text-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
.icon-button:hover:before {
|
.confetti-button:before,
|
||||||
opacity: 1;
|
.confetti-button:after {
|
||||||
transform: translate(-50%, 48px) scale(1);
|
z-index: 100;
|
||||||
}
|
}
|
||||||
|
|
||||||
.icon-button:before {
|
.confetti-button:before {
|
||||||
content: attr(data-title);
|
line-height: 80px;
|
||||||
display: block;
|
|
||||||
font-size: 12px;
|
|
||||||
line-height: 20px;
|
|
||||||
margin-left: 27px;
|
|
||||||
transform: translate(-50%, 48px) scale(0.9);
|
|
||||||
font-weight: 400;
|
|
||||||
position: absolute;
|
|
||||||
background: var(--vp-c-brand-dark);
|
|
||||||
color: white;
|
|
||||||
z-index: 10;
|
|
||||||
white-space: nowrap;
|
|
||||||
padding: 2px 8px;
|
|
||||||
border-radius: 4px;
|
|
||||||
box-shadow: var(--vp-shadow-1);
|
|
||||||
opacity: 0;
|
|
||||||
pointer-events: none;
|
|
||||||
transition: cubic-bezier(0.19, 1, 0.22, 1) .2s;
|
|
||||||
transition-property: opacity, transform;
|
|
||||||
/* max-width: calc((32px * 2) + 56px); */
|
|
||||||
overflow: hidden;
|
|
||||||
white-space: pre-wrap;
|
|
||||||
word-break: break-word;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.icon-button:active {
|
.icon-button:active {
|
||||||
@@ -139,6 +146,7 @@ function navigateToIcon() {
|
|||||||
|
|
||||||
.lucide-icon {
|
.lucide-icon {
|
||||||
margin: auto;
|
margin: auto;
|
||||||
|
pointer-events: none;
|
||||||
}
|
}
|
||||||
.lucide-icon.customizable {
|
.lucide-icon.customizable {
|
||||||
will-change: width, height, stroke-width, stroke;
|
will-change: width, height, stroke-width, stroke;
|
||||||
|
|||||||
@@ -1,67 +1,92 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref, computed, defineAsyncComponent } from 'vue'
|
import { ref, computed, defineAsyncComponent } 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';
|
||||||
import useSearchInput from '../../composables/useSearchInput'
|
import useSearchInput from '../../composables/useSearchInput';
|
||||||
import StickyBar from './StickyBar.vue'
|
import StickyBar from './StickyBar.vue';
|
||||||
import IconsCategory from './IconsCategory.vue'
|
import IconsCategory from './IconsCategory.vue';
|
||||||
|
import { useFetch } from '@vueuse/core';
|
||||||
|
import useFetchTags from '../../composables/useFetchTags';
|
||||||
|
import useFetchCategories from '../../composables/useFetchCategories';
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
icons: IconEntity[]
|
icons: IconEntity[];
|
||||||
categories: Category[]
|
categories: Category[];
|
||||||
iconCategories: Record<string, string[]>
|
iconCategories: Record<string, string[]>;
|
||||||
}>()
|
}>();
|
||||||
|
|
||||||
const activeIconName = ref(null)
|
const activeIconName = ref(null);
|
||||||
const { searchInput, searchQuery, searchQueryThrottled } = useSearchInput()
|
const { searchInput, searchQuery, searchQueryDebounced } = useSearchInput();
|
||||||
|
|
||||||
const isSearching = computed(() => !!searchQuery.value)
|
const isSearching = computed(() => !!searchQuery.value);
|
||||||
|
|
||||||
function setActiveIconName(name: string) {
|
function setActiveIconName(name: string) {
|
||||||
activeIconName.value = name
|
activeIconName.value = name;
|
||||||
}
|
}
|
||||||
|
|
||||||
const searchResults = useSearch(searchQuery, props.icons, [
|
const { execute: fetchTags, data: tags } = useFetchTags();
|
||||||
{ name: 'name', weight: 2 },
|
const { execute: fetchCategories, data: categoriesMap } = useFetchCategories();
|
||||||
{ name: 'tags', weight: 1 },
|
|
||||||
])
|
|
||||||
|
|
||||||
const categories = computed(() => {
|
const mappedIcons = computed(() => {
|
||||||
if( !props.categories?.length || !props.icons?.length ) return []
|
if (tags.value == null) {
|
||||||
|
return props.icons;
|
||||||
return props.categories.map(({ name, title }) => {
|
}
|
||||||
const categoryIcons = props.icons.filter((icon) => {
|
return props.icons.map((icon) => {
|
||||||
const iconCategories = props.iconCategories[icon.name]
|
const iconTags = tags.value[icon.name];
|
||||||
|
const iconCategories = categoriesMap.value?.[icon.name] ?? [];
|
||||||
return iconCategories?.includes(name)
|
|
||||||
})
|
|
||||||
|
|
||||||
|
|
||||||
const searchedCategoryIcons = isSearching
|
|
||||||
? categoryIcons.filter(icon => searchResults.value.some((item) => item?.name === icon?.name))
|
|
||||||
: categoryIcons;
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
title,
|
...icon,
|
||||||
name,
|
tags: iconTags,
|
||||||
icons: searchedCategoryIcons,
|
categories: iconCategories,
|
||||||
};
|
};
|
||||||
})
|
});
|
||||||
.filter(({ icons }) => icons.length)
|
});
|
||||||
})
|
|
||||||
|
|
||||||
const activeIcon = computed(() =>
|
const searchResults = useSearch(searchQuery, mappedIcons, [
|
||||||
props.icons?.find((icon) => icon.name === activeIconName.value)
|
{ name: 'name', weight: 2 },
|
||||||
)
|
{ name: 'tags', weight: 1 },
|
||||||
|
]);
|
||||||
|
|
||||||
const NoResults = defineAsyncComponent(() =>
|
const categories = computed(() => {
|
||||||
import('./NoResults.vue')
|
if (!props.categories?.length || !props.icons?.length) return [];
|
||||||
)
|
|
||||||
|
|
||||||
const IconDetailOverlay = defineAsyncComponent(() =>
|
return props.categories
|
||||||
import('./IconDetailOverlay.vue')
|
.map(({ name, title }) => {
|
||||||
)
|
const categoryIcons = props.icons.filter((icon) => {
|
||||||
|
const iconCategories = props.iconCategories[icon.name];
|
||||||
|
|
||||||
|
return iconCategories?.includes(name);
|
||||||
|
});
|
||||||
|
|
||||||
|
const searchedCategoryIcons = isSearching
|
||||||
|
? categoryIcons.filter((icon) =>
|
||||||
|
searchResults.value.some((item) => item?.name === icon?.name)
|
||||||
|
)
|
||||||
|
: categoryIcons;
|
||||||
|
|
||||||
|
return {
|
||||||
|
title,
|
||||||
|
name,
|
||||||
|
icons: searchedCategoryIcons,
|
||||||
|
};
|
||||||
|
})
|
||||||
|
.filter(({ icons }) => icons.length);
|
||||||
|
});
|
||||||
|
|
||||||
|
function onFocusSearchInput() {
|
||||||
|
if (tags.value == null) {
|
||||||
|
fetchTags();
|
||||||
|
}
|
||||||
|
if (categoriesMap.value == null) {
|
||||||
|
fetchCategories();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const NoResults = defineAsyncComponent(() => import('./NoResults.vue'));
|
||||||
|
|
||||||
|
const IconDetailOverlay = defineAsyncComponent(() => import('./IconDetailOverlay.vue'));
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
@@ -71,13 +96,10 @@ const IconDetailOverlay = defineAsyncComponent(() =>
|
|||||||
v-model="searchQuery"
|
v-model="searchQuery"
|
||||||
class="input-wrapper"
|
class="input-wrapper"
|
||||||
ref="searchInput"
|
ref="searchInput"
|
||||||
|
@focus="onFocusSearchInput"
|
||||||
/>
|
/>
|
||||||
</StickyBar>
|
</StickyBar>
|
||||||
<NoResults
|
<NoResults v-if="categories.length === 0" :searchQuery="searchQuery" @clear="searchQuery = ''" />
|
||||||
v-if="categories.length === 0"
|
|
||||||
:searchQuery="searchQuery"
|
|
||||||
@clear="searchQuery = ''"
|
|
||||||
/>
|
|
||||||
<IconsCategory
|
<IconsCategory
|
||||||
v-for="category in categories"
|
v-for="category in categories"
|
||||||
:key="category.name"
|
:key="category.name"
|
||||||
@@ -87,7 +109,7 @@ const IconDetailOverlay = defineAsyncComponent(() =>
|
|||||||
/>
|
/>
|
||||||
<IconDetailOverlay
|
<IconDetailOverlay
|
||||||
v-if="activeIconName != null"
|
v-if="activeIconName != null"
|
||||||
:icon="activeIcon"
|
:iconName="activeIconName"
|
||||||
@close="setActiveIconName('')"
|
@close="setActiveIconName('')"
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -1,19 +1,21 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref, computed, watch, defineAsyncComponent } from 'vue'
|
import { ref, computed, watch, defineAsyncComponent } from 'vue';
|
||||||
import type { IconEntity } from '../../types'
|
import type { IconEntity } from '../../types';
|
||||||
import { useMediaQuery, useOffsetPagination } from '@vueuse/core'
|
import { useMediaQuery, useOffsetPagination } from '@vueuse/core';
|
||||||
import IconGrid from './IconGrid.vue'
|
import IconGrid from './IconGrid.vue';
|
||||||
import InputSearch from '../base/InputSearch.vue'
|
import InputSearch from '../base/InputSearch.vue';
|
||||||
import useSearch from '../../composables/useSearch'
|
import useSearch from '../../composables/useSearch';
|
||||||
import EndOfPage from '../base/EndOfPage.vue'
|
import EndOfPage from '../base/EndOfPage.vue';
|
||||||
import useSearchInput from '../../composables/useSearchInput'
|
import useSearchInput from '../../composables/useSearchInput';
|
||||||
import StickyBar from './StickyBar.vue'
|
import StickyBar from './StickyBar.vue';
|
||||||
|
import useFetchTags from '../../composables/useFetchTags';
|
||||||
|
import useFetchCategories from '../../composables/useFetchCategories';
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
icons: IconEntity[]
|
icons: IconEntity[];
|
||||||
}>()
|
}>();
|
||||||
|
|
||||||
const activeIconName = ref(null)
|
const activeIconName = ref(null);
|
||||||
|
|
||||||
const isExtraLargeScreen = useMediaQuery('(min-width: 1440px)');
|
const isExtraLargeScreen = useMediaQuery('(min-width: 1440px)');
|
||||||
const isLargeScreen = useMediaQuery('(min-width: 1280px)');
|
const isLargeScreen = useMediaQuery('(min-width: 1280px)');
|
||||||
@@ -21,57 +23,78 @@ const isMediumScreen = useMediaQuery('(min-width: 960px)');
|
|||||||
const isSmallScreen = useMediaQuery('(min-width: 640px)');
|
const isSmallScreen = useMediaQuery('(min-width: 640px)');
|
||||||
|
|
||||||
const pageSize = computed(() => {
|
const pageSize = computed(() => {
|
||||||
if(isExtraLargeScreen.value) {
|
if (isExtraLargeScreen.value) {
|
||||||
return 16 * 16;
|
return 16 * 20;
|
||||||
}
|
}
|
||||||
if(isLargeScreen.value) {
|
if (isLargeScreen.value) {
|
||||||
return 16 * 12;
|
return 16 * 12;
|
||||||
}
|
}
|
||||||
if(isMediumScreen.value) {
|
if (isMediumScreen.value) {
|
||||||
return 13 * 12;
|
return 13 * 12;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(isSmallScreen.value) {
|
if (isSmallScreen.value) {
|
||||||
return 10 * 10;
|
return 10 * 10;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 10 * 5;
|
return 10 * 5;
|
||||||
})
|
});
|
||||||
|
|
||||||
const { searchInput, searchQuery, searchQueryThrottled } = useSearchInput()
|
const { execute: fetchTags, data: tags } = useFetchTags();
|
||||||
const searchResults = useSearch(searchQueryThrottled, props.icons, [
|
const { execute: fetchCategories, data: categories } = useFetchCategories();
|
||||||
|
|
||||||
|
const mappedIcons = computed(() => {
|
||||||
|
if (tags.value == null) {
|
||||||
|
return props.icons;
|
||||||
|
}
|
||||||
|
|
||||||
|
return props.icons.map((icon) => {
|
||||||
|
const iconTags = tags.value[icon.name];
|
||||||
|
const iconCategories = categories.value?.[icon.name] ?? [];
|
||||||
|
|
||||||
|
return {
|
||||||
|
...icon,
|
||||||
|
tags: iconTags,
|
||||||
|
categories: iconCategories,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
const { searchInput, searchQuery, searchQueryDebounced } = useSearchInput();
|
||||||
|
const searchResults = useSearch(searchQueryDebounced, mappedIcons, [
|
||||||
{ name: 'name', weight: 3 },
|
{ name: 'name', weight: 3 },
|
||||||
{ name: 'tags', weight: 2 },
|
{ name: 'tags', weight: 2 },
|
||||||
{ name: 'categories', weight: 1 },
|
{ name: 'categories', weight: 1 },
|
||||||
])
|
]);
|
||||||
|
|
||||||
const { next, currentPage } = useOffsetPagination( { pageSize })
|
|
||||||
|
|
||||||
|
const { next, currentPage } = useOffsetPagination({ pageSize });
|
||||||
|
|
||||||
const paginatedIcons = computed(() => {
|
const paginatedIcons = computed(() => {
|
||||||
const end = pageSize.value * currentPage.value
|
const end = pageSize.value * currentPage.value;
|
||||||
|
|
||||||
return searchResults.value.slice(0, end)
|
return searchResults.value.slice(0, end);
|
||||||
})
|
});
|
||||||
|
|
||||||
function setActiveIconName(name: string) {
|
function setActiveIconName(name: string) {
|
||||||
activeIconName.value = name
|
activeIconName.value = name;
|
||||||
}
|
}
|
||||||
|
|
||||||
const activeIcon = computed(() => props.icons.find((icon) => icon.name === activeIconName.value))
|
watch(searchQueryDebounced, (searchString) => {
|
||||||
|
currentPage.value = 1;
|
||||||
|
});
|
||||||
|
|
||||||
watch(searchQueryThrottled, (searchString) => {
|
function onFocusSearchInput() {
|
||||||
currentPage.value = 1
|
if (tags.value == null) {
|
||||||
})
|
fetchTags();
|
||||||
|
}
|
||||||
|
if (categories.value == null) {
|
||||||
|
fetchCategories();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const NoResults = defineAsyncComponent(() =>
|
const NoResults = defineAsyncComponent(() => import('./NoResults.vue'));
|
||||||
import('./NoResults.vue')
|
|
||||||
)
|
|
||||||
|
|
||||||
const IconDetailOverlay = defineAsyncComponent(() =>
|
|
||||||
import('./IconDetailOverlay.vue')
|
|
||||||
)
|
|
||||||
|
|
||||||
|
const IconDetailOverlay = defineAsyncComponent(() => import('./IconDetailOverlay.vue'));
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
@@ -81,6 +104,7 @@ const IconDetailOverlay = defineAsyncComponent(() =>
|
|||||||
v-model="searchQuery"
|
v-model="searchQuery"
|
||||||
ref="searchInput"
|
ref="searchInput"
|
||||||
class="input-wrapper"
|
class="input-wrapper"
|
||||||
|
@focus="onFocusSearchInput"
|
||||||
/>
|
/>
|
||||||
</StickyBar>
|
</StickyBar>
|
||||||
<NoResults
|
<NoResults
|
||||||
@@ -94,10 +118,10 @@ const IconDetailOverlay = defineAsyncComponent(() =>
|
|||||||
:icons="paginatedIcons"
|
:icons="paginatedIcons"
|
||||||
@setActiveIcon="setActiveIconName"
|
@setActiveIcon="setActiveIconName"
|
||||||
/>
|
/>
|
||||||
<EndOfPage @end-of-page="next" class="bottom-page"/>
|
<EndOfPage @end-of-page="next" class="bottom-page" />
|
||||||
<IconDetailOverlay
|
<IconDetailOverlay
|
||||||
v-if="activeIconName != null"
|
v-if="activeIconName != null"
|
||||||
:icon="activeIcon"
|
:iconName="activeIconName"
|
||||||
@close="setActiveIconName('')"
|
@close="setActiveIconName('')"
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -32,8 +32,8 @@ useEventListener(document, 'mousemove', (mouseEvent) => {
|
|||||||
No icons found for '{{ searchQuery }}'
|
No icons found for '{{ searchQuery }}'
|
||||||
</h2>
|
</h2>
|
||||||
<VPButton text="Clear your search and try again" theme="alt" @click="$emit('clear')"/>
|
<VPButton text="Clear your search and try again" theme="alt" @click="$emit('clear')"/>
|
||||||
or
|
<span class="text-divider">or</span>
|
||||||
<VPButton text="Check if someone has already requested this icon"
|
<VPButton text="Search on Github issues"
|
||||||
theme="alt"
|
theme="alt"
|
||||||
:href="`https://github.com/lucide-icons/lucide/issues?q=is%3Aopen+${searchQuery}`"
|
:href="`https://github.com/lucide-icons/lucide/issues?q=is%3Aopen+${searchQuery}`"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
@@ -74,4 +74,10 @@ useEventListener(document, 'mousemove', (mouseEvent) => {
|
|||||||
margin-bottom: 32px;
|
margin-bottom: 32px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.text-divider {
|
||||||
|
margin: 12px 0;
|
||||||
|
font-size: 16px;
|
||||||
|
color: var(--vp-c-neutral);
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { shallowRef, type Ref, watch } from 'vue'
|
import { shallowRef, type Ref, watch, computed } from 'vue'
|
||||||
import { useCssVar, syncRef } from '@vueuse/core'
|
import { useCssVar, syncRef } from '@vueuse/core'
|
||||||
import { useIconStyleContext } from '../../composables/useIconStyle'
|
import { STYLE_DEFAULTS, useIconStyleContext } from '../../composables/useIconStyle'
|
||||||
import RangeSlider from '../base/RangeSlider.vue'
|
import RangeSlider from '../base/RangeSlider.vue'
|
||||||
import InputField from '../base/InputField.vue'
|
import InputField from '../base/InputField.vue'
|
||||||
import ColorPicker from '../base/ColorPicker.vue'
|
import ColorPicker from '../base/ColorPicker.vue'
|
||||||
@@ -19,7 +19,7 @@ const colorCssVar = useCssVar(
|
|||||||
'--customize-color',
|
'--customize-color',
|
||||||
props.rootEl?.value ?? documentRef.value,
|
props.rootEl?.value ?? documentRef.value,
|
||||||
{
|
{
|
||||||
initialValue: 'default'
|
initialValue: `${STYLE_DEFAULTS.color}`
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -27,7 +27,7 @@ const strokeWidthCssVar = useCssVar(
|
|||||||
'--customize-strokeWidth',
|
'--customize-strokeWidth',
|
||||||
props.rootEl?.value ?? documentRef.value,
|
props.rootEl?.value ?? documentRef.value,
|
||||||
{
|
{
|
||||||
initialValue: '2'
|
initialValue: `${STYLE_DEFAULTS.strokeWidth}`
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -35,7 +35,7 @@ const sizeCssVar = useCssVar(
|
|||||||
'--customize-size',
|
'--customize-size',
|
||||||
props.rootEl?.value ?? documentRef.value,
|
props.rootEl?.value ?? documentRef.value,
|
||||||
{
|
{
|
||||||
initialValue: '24'
|
initialValue: `${STYLE_DEFAULTS.size}`
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -44,9 +44,9 @@ syncRef(strokeWidth, strokeWidthCssVar, { direction: 'ltr' })
|
|||||||
syncRef(size, sizeCssVar, { direction: 'ltr' })
|
syncRef(size, sizeCssVar, { direction: 'ltr' })
|
||||||
|
|
||||||
function resetStyle () {
|
function resetStyle () {
|
||||||
color.value = 'currentColor'
|
color.value = STYLE_DEFAULTS.color
|
||||||
strokeWidth.value = 2
|
strokeWidth.value = STYLE_DEFAULTS.strokeWidth
|
||||||
size.value = 24
|
size.value = STYLE_DEFAULTS.size
|
||||||
}
|
}
|
||||||
|
|
||||||
watch(absoluteStrokeWidth, (enabled) => {
|
watch(absoluteStrokeWidth, (enabled) => {
|
||||||
@@ -54,10 +54,18 @@ watch(absoluteStrokeWidth, (enabled) => {
|
|||||||
|
|
||||||
htmlEl.classList.toggle('absolute-stroke-width', enabled)
|
htmlEl.classList.toggle('absolute-stroke-width', enabled)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const customizingActive = computed(() => {
|
||||||
|
return color.value !== STYLE_DEFAULTS.color
|
||||||
|
|| strokeWidth.value !== STYLE_DEFAULTS.strokeWidth
|
||||||
|
|| size.value !== STYLE_DEFAULTS.size
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="customizer-card">
|
<div class="customizer-card" :class="{ customized: customizingActive }">
|
||||||
<div class="card-header">
|
<div class="card-header">
|
||||||
<h2 class="card-title">
|
<h2 class="card-title">
|
||||||
Customizer
|
Customizer
|
||||||
@@ -142,6 +150,12 @@ watch(absoluteStrokeWidth, (enabled) => {
|
|||||||
margin-bottom: 24px;
|
margin-bottom: 24px;
|
||||||
position: relative;
|
position: relative;
|
||||||
z-index: 0;
|
z-index: 0;
|
||||||
|
border: 1px solid transparent;
|
||||||
|
transition: border-color .4s ease-in-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
.customizer-card.customized {
|
||||||
|
border-color: var(--vp-c-brand);
|
||||||
}
|
}
|
||||||
|
|
||||||
.color-picker {
|
.color-picker {
|
||||||
|
|||||||
@@ -36,15 +36,22 @@ const links = computed(() => [
|
|||||||
<template>
|
<template>
|
||||||
<footer v-if="theme.footer" class="VPFooter" :class="{ 'has-sidebar': hasSidebar }">
|
<footer v-if="theme.footer" class="VPFooter" :class="{ 'has-sidebar': hasSidebar }">
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<p v-if="theme.footer.message" class="message" v-html="theme.footer.message"></p>
|
<div class="sponsors">
|
||||||
<p v-if="theme.footer.copyright" class="copyright" v-html="theme.footer.copyright"></p>
|
<a href="https://vercel.com?utm_source=lucide&utm_campaign=oss" rel="noreferrer noopener">
|
||||||
|
<img src="/vercel.svg" alt="Powered by Vercel" width="200" />
|
||||||
|
</a>
|
||||||
|
<a href="https://www.digitalocean.com/?refcode=b0877a2caebd&utm_campaign=Referral_Invite&utm_medium=Referral_Program&utm_source=badge" rel="noreferrer noopener">
|
||||||
|
<img src="/digitalocean.svg" alt="Digital Ocean" width="200" />
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
<div class="links">
|
<div class="links">
|
||||||
<VPLink v-for="link in links" :href="link.href" :key="link.text" :rel="link.href.startsWith('http') ? 'noreferrer noopener': undefined">
|
<VPLink v-for="link in links" :href="link.href" :key="link.text" :rel="link.href.startsWith('http') ? 'noreferrer noopener': undefined">
|
||||||
{{ link.text }}
|
{{ link.text }}
|
||||||
</VPLink>
|
</VPLink>
|
||||||
<a href="https://vercel.com?utm_source=lucide&utm_campaign=oss" rel="noreferrer noopener">
|
</div>
|
||||||
<img src="/vercel.svg" alt="Powered by Vercel" width="200" />
|
<div>
|
||||||
</a>
|
<p v-if="theme.footer.message" class="message" v-html="theme.footer.message"></p>
|
||||||
|
<p v-if="theme.footer.copyright" class="copyright" v-html="theme.footer.copyright"></p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</footer>
|
</footer>
|
||||||
@@ -67,7 +74,7 @@ const links = computed(() => [
|
|||||||
|
|
||||||
.container {
|
.container {
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
max-width: var(--vp-layout-max-width);
|
max-width: calc(var(--vp-layout-max-width) - 64px);
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
@@ -85,7 +92,7 @@ const links = computed(() => [
|
|||||||
.message { order: 2; }
|
.message { order: 2; }
|
||||||
.copyright { order: 1; }
|
.copyright { order: 1; }
|
||||||
|
|
||||||
.links {
|
.links, .sponsors {
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: 32px;
|
gap: 32px;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
@@ -102,7 +109,7 @@ const links = computed(() => [
|
|||||||
flex-direction: row-reverse;
|
flex-direction: row-reverse;
|
||||||
}
|
}
|
||||||
.links {
|
.links {
|
||||||
margin-left: auto;
|
margin-right: auto;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -1,24 +1,30 @@
|
|||||||
<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 PackageListItem from "./PackageListItem.vue";</script>
|
import PackageListItem from "./PackageListItem.vue";</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<section class="package-group">
|
<GridSection
|
||||||
<h1 class="name">Packages</h1>
|
title="Packages"
|
||||||
<div class="grid package-list" ref="container">
|
:headingLevel="1"
|
||||||
<div v-for="packageData in data.packages" class="item">
|
class="package-group"
|
||||||
<PackageListItem :packageData="packageData"/>
|
>
|
||||||
</div>
|
<PackageListItem
|
||||||
</div>
|
v-for="packageData in data.packages"
|
||||||
</section>
|
:packageData="packageData"
|
||||||
<section class="package-group">
|
/>
|
||||||
<h2 class="name">Third-party packages</h2>
|
</GridSection>
|
||||||
<div class="grid package-list" ref="container">
|
|
||||||
<div v-for="packageData in data.thirdPartyPackages" class="item">
|
<GridSection
|
||||||
<PackageListItem :packageData="packageData"/>
|
title="Third-party packages"
|
||||||
</div>
|
:headingLevel="2"
|
||||||
</div>
|
class="package-group"
|
||||||
</section>
|
>
|
||||||
|
<PackageListItem
|
||||||
|
v-for="packageData in data.thirdPartyPackages"
|
||||||
|
:packageData="packageData"
|
||||||
|
/>
|
||||||
|
</GridSection>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
@@ -26,7 +32,7 @@ import PackageListItem from "./PackageListItem.vue";</script>
|
|||||||
font-size: 32px;
|
font-size: 32px;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
margin-bottom: 24px;
|
margin-bottom: 32px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.package-group {
|
.package-group {
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
import { useRouter } from 'vitepress';
|
import { useRouter } from 'vitepress';
|
||||||
import {PackageItem} from "../../types";
|
import {PackageItem} from "../../types";
|
||||||
import VPButton from 'vitepress/dist/client/theme-default/components/VPButton.vue';
|
import VPButton from 'vitepress/dist/client/theme-default/components/VPButton.vue';
|
||||||
|
import Card from '../base/Card.vue'
|
||||||
|
|
||||||
const { go } = useRouter()
|
const { go } = useRouter()
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
@@ -10,48 +11,42 @@ const props = defineProps<{
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<article class="package">
|
<div>
|
||||||
<header class="package-header">
|
<Card class="package">
|
||||||
<div class="package-icon-well">
|
<header class="package-header">
|
||||||
<img :src="packageData.icon" alt="" class="package-icon" :class="{[packageData.iconClass]: true, light: packageData.iconDark}" />
|
<div class="package-icon-well">
|
||||||
<img v-if="packageData.iconDark" :src="packageData.iconDark" alt="" class="package-icon dark" :class="packageData.iconClass" />
|
<img :src="packageData.icon" alt="" class="package-icon" :class="{[packageData.iconClass]: true, light: packageData.iconDark}" />
|
||||||
|
<img v-if="packageData.iconDark" :src="packageData.iconDark" alt="" class="package-icon dark" :class="packageData.iconClass" />
|
||||||
|
</div>
|
||||||
|
<div class="package-title">
|
||||||
|
<h2 class="title">{{ props.packageData.name }}</h2>
|
||||||
|
<a v-for="shield in props.packageData.shields" :href="shield.href" class="package-shield" rel="noreferrer noopener">
|
||||||
|
<img :src="shield.src" :alt="shield.href" />
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</header>
|
||||||
|
<div class="package-details">
|
||||||
|
{{ packageData.description }}
|
||||||
</div>
|
</div>
|
||||||
<div class="package-title">
|
<footer class="package-footer">
|
||||||
<h2 class="title">{{ props.packageData.name }}</h2>
|
<VPButton
|
||||||
<a v-for="shield in props.packageData.shields" :href="shield.href" class="package-shield" rel="noreferrer noopener">
|
:href="packageData.documentation"
|
||||||
<img :src="shield.src" :alt="shield.href" />
|
text="Guide"
|
||||||
</a>
|
theme="brand"
|
||||||
</div>
|
@click="go(packageData.documentation)"
|
||||||
</header>
|
/>
|
||||||
<div class="package-details">
|
<VPButton
|
||||||
{{ packageData.description }}
|
:href="packageData.source"
|
||||||
</div>
|
text="Source"
|
||||||
<footer class="package-footer">
|
theme="alt"
|
||||||
<VPButton
|
@click="go(packageData.source)"
|
||||||
:href="packageData.documentation"
|
/>
|
||||||
text="Guide"
|
</footer>
|
||||||
theme="brand"
|
</Card>
|
||||||
@click="go(packageData.documentation)"
|
</div>
|
||||||
/>
|
|
||||||
<VPButton
|
|
||||||
:href="packageData.source"
|
|
||||||
text="Source"
|
|
||||||
theme="alt"
|
|
||||||
@click="go(packageData.source)"
|
|
||||||
/>
|
|
||||||
</footer>
|
|
||||||
</article>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.package {
|
|
||||||
border: 1px solid var(--vp-c-bg-soft);
|
|
||||||
border-radius: 12px;
|
|
||||||
background-color: var(--vp-c-bg-soft);
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
padding: 24px;
|
|
||||||
}
|
|
||||||
.package {
|
.package {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
|||||||
72
docs/.vitepress/theme/components/showcase/ShowcaseList.vue
Normal file
72
docs/.vitepress/theme/components/showcase/ShowcaseList.vue
Normal file
@@ -0,0 +1,72 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import companies from '../../../data/companiesData.json'
|
||||||
|
import componentLibraries from '../../../data/componentLibrariesData.json'
|
||||||
|
import GridSection from '../base/GridSection.vue'
|
||||||
|
import ShowcaseListItem from "./ShowcaseListItem.vue";
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<GridSection
|
||||||
|
title="Used by"
|
||||||
|
:headingLevel="1"
|
||||||
|
class="package-group"
|
||||||
|
>
|
||||||
|
<ShowcaseListItem
|
||||||
|
v-for="company in companies"
|
||||||
|
:showcaseItem="company"
|
||||||
|
/>
|
||||||
|
</GridSection>
|
||||||
|
|
||||||
|
<GridSection
|
||||||
|
title="Used in"
|
||||||
|
:headingLevel="1"
|
||||||
|
class="package-group"
|
||||||
|
>
|
||||||
|
<ShowcaseListItem
|
||||||
|
v-for="componentLibrary in componentLibraries"
|
||||||
|
:showcaseItem="componentLibrary"
|
||||||
|
/>
|
||||||
|
</GridSection>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.name {
|
||||||
|
font-size: 32px;
|
||||||
|
font-weight: bold;
|
||||||
|
text-align: center;
|
||||||
|
margin-bottom: 32px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.package-group {
|
||||||
|
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>
|
||||||
@@ -0,0 +1,52 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { useRouter } from 'vitepress';
|
||||||
|
import { ShowcaseItem } from "../../types";
|
||||||
|
import Card from '../base/Card.vue'
|
||||||
|
|
||||||
|
const { go } = useRouter()
|
||||||
|
defineProps<{
|
||||||
|
showcaseItem: ShowcaseItem,
|
||||||
|
}>()
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<Card
|
||||||
|
class="company"
|
||||||
|
:href="showcaseItem.url"
|
||||||
|
:aria-label="showcaseItem.name"
|
||||||
|
>
|
||||||
|
<img
|
||||||
|
:src="showcaseItem.image.light"
|
||||||
|
class="logo light"
|
||||||
|
:alt="`${showcaseItem.name} logo`"
|
||||||
|
/>
|
||||||
|
<img
|
||||||
|
:src="showcaseItem.image.dark"
|
||||||
|
class="logo dark"
|
||||||
|
:alt="`${showcaseItem.name} logo`"
|
||||||
|
/>
|
||||||
|
</Card>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.company {
|
||||||
|
display: flex;
|
||||||
|
height: 100%;
|
||||||
|
padding: 48px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.logo {
|
||||||
|
height:64px;
|
||||||
|
width: 240px;
|
||||||
|
margin: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
html.dark .logo.dark {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
html:not(.dark) .logo.light {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -2,6 +2,7 @@ import { ref } from "vue";
|
|||||||
|
|
||||||
export default function useConfetti() {
|
export default function useConfetti() {
|
||||||
const animate = ref(false)
|
const animate = ref(false)
|
||||||
|
const confettiText = ref('confetti!')
|
||||||
|
|
||||||
function confetti() {
|
function confetti() {
|
||||||
animate.value = true;
|
animate.value = true;
|
||||||
@@ -13,6 +14,7 @@ export default function useConfetti() {
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
animate,
|
animate,
|
||||||
confetti
|
confetti,
|
||||||
|
confettiText
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
12
docs/.vitepress/theme/composables/useFetchCategories.ts
Normal file
12
docs/.vitepress/theme/composables/useFetchCategories.ts
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
import { useFetch } from "@vueuse/core"
|
||||||
|
|
||||||
|
const useFetchCategories = () => useFetch<Record<string, string[]>>(
|
||||||
|
`${import.meta.env.DEV ? 'http://localhost:3000' : ''}/api/categories`,
|
||||||
|
{
|
||||||
|
immediate:
|
||||||
|
typeof window !== 'undefined'
|
||||||
|
&& new URLSearchParams(window.location.search).has('search'),
|
||||||
|
}
|
||||||
|
).json()
|
||||||
|
|
||||||
|
export default useFetchCategories
|
||||||
12
docs/.vitepress/theme/composables/useFetchTags.ts
Normal file
12
docs/.vitepress/theme/composables/useFetchTags.ts
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
import { useFetch } from "@vueuse/core"
|
||||||
|
|
||||||
|
const useFetchTags = () => useFetch<Record<string, string[]>>(
|
||||||
|
`${import.meta.env.DEV ? 'http://localhost:3000' : ''}/api/tags`,
|
||||||
|
{
|
||||||
|
immediate:
|
||||||
|
typeof window !== 'undefined'
|
||||||
|
&& new URLSearchParams(window.location.search).has('search'),
|
||||||
|
}
|
||||||
|
).json()
|
||||||
|
|
||||||
|
export default useFetchTags
|
||||||
@@ -10,8 +10,16 @@ interface IconSizeContext {
|
|||||||
size: Ref<number>
|
size: Ref<number>
|
||||||
strokeWidth: Ref<number>
|
strokeWidth: Ref<number>
|
||||||
color: Ref<string>
|
color: Ref<string>
|
||||||
|
absoluteStrokeWidth: Ref<boolean>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const STYLE_DEFAULTS = {
|
||||||
|
size: 24,
|
||||||
|
strokeWidth: 2,
|
||||||
|
color: 'currentColor',
|
||||||
|
absoluteStrokeWidth: false,
|
||||||
|
};
|
||||||
|
|
||||||
export const iconStyleContext = {
|
export const iconStyleContext = {
|
||||||
size: ref(24),
|
size: ref(24),
|
||||||
strokeWidth: ref(2),
|
strokeWidth: ref(2),
|
||||||
|
|||||||
@@ -1,20 +1,22 @@
|
|||||||
import Fuse from 'fuse.js';
|
import Fuse from 'fuse.js';
|
||||||
import { shallowRef, computed, Ref } from 'vue';
|
import { shallowRef, computed, Ref } from 'vue';
|
||||||
|
|
||||||
const useSearch = <T>(query: Ref<string>, collection: T[], keys: Fuse.FuseOptionKey<T>[] = []) => {
|
const useSearch = <T>(query: Ref<string>, collection: Ref<T[]>, keys: Fuse.FuseOptionKey<T>[] = []) => {
|
||||||
const index = shallowRef(
|
const index = shallowRef(
|
||||||
new Fuse(collection, {
|
new Fuse(collection.value, {
|
||||||
threshold: 0.2,
|
threshold: 0.2,
|
||||||
keys,
|
keys,
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
|
|
||||||
const results = computed(() => {
|
const results = computed(() => {
|
||||||
|
index.value.setCollection(collection.value);
|
||||||
|
|
||||||
if (query.value) {
|
if (query.value) {
|
||||||
return index.value.search(query.value).map((result) => result.item);
|
return index.value.search(query.value).map((result) => result.item);
|
||||||
}
|
}
|
||||||
|
|
||||||
return collection;
|
return collection.value;
|
||||||
});
|
});
|
||||||
|
|
||||||
return results;
|
return results;
|
||||||
|
|||||||
@@ -1,39 +1,40 @@
|
|||||||
import { refThrottled } from '@vueuse/core';
|
import { useDebounce } from '@vueuse/core';
|
||||||
import { nextTick, onMounted, ref, watch } from 'vue';
|
import { nextTick, onMounted, ref, watch } from 'vue';
|
||||||
|
|
||||||
const useSearchInput = () => {
|
const useSearchInput = () => {
|
||||||
const searchInput = ref()
|
const searchInput = ref();
|
||||||
const searchQuery = ref(
|
const searchQuery = ref(
|
||||||
typeof window === 'undefined'
|
typeof window === 'undefined'
|
||||||
? ''
|
? ''
|
||||||
: (
|
: new URLSearchParams(window.location.search).get('search') || ''
|
||||||
new URLSearchParams(window.location.search).get('search')
|
);
|
||||||
|| ''
|
const searchQueryDebounced = useDebounce(searchQuery, 250);
|
||||||
)
|
|
||||||
)
|
|
||||||
const searchQueryThrottled = refThrottled(searchQuery, 200)
|
|
||||||
|
|
||||||
watch(searchQueryThrottled, (searchString) => {
|
watch(searchQueryDebounced, (searchString) => {
|
||||||
const newUrl = new URL(window.location.href);
|
const newUrl = new URL(window.location.href);
|
||||||
|
|
||||||
newUrl.searchParams.set('search', searchString);
|
if (searchString === '') {
|
||||||
|
newUrl.searchParams.delete('search');
|
||||||
|
} else {
|
||||||
|
newUrl.searchParams.set('search', searchString);
|
||||||
|
}
|
||||||
|
|
||||||
nextTick(() => {
|
nextTick(() => {
|
||||||
window.history.replaceState({}, '', newUrl)
|
window.history.replaceState({}, '', newUrl);
|
||||||
})
|
});
|
||||||
})
|
});
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
const searchParams = new URLSearchParams(window.location.search);
|
const searchParams = new URLSearchParams(window.location.search);
|
||||||
if(searchParams.has('focus')) {
|
if (searchParams.has('focus')) {
|
||||||
searchInput.value.focus()
|
searchInput.value.focus();
|
||||||
}
|
}
|
||||||
})
|
});
|
||||||
|
|
||||||
return {
|
return {
|
||||||
searchInput,
|
searchInput,
|
||||||
searchQuery,
|
searchQuery,
|
||||||
searchQueryThrottled
|
searchQueryDebounced,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
34
docs/.vitepress/theme/sandpackTheme.json
Normal file
34
docs/.vitepress/theme/sandpackTheme.json
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
{
|
||||||
|
"colors": {
|
||||||
|
"surface1": "var(--vp-code-block-bg)",
|
||||||
|
"surface2": "var(--vp-code-block-bg)",
|
||||||
|
"surface3": "var(--vp-code-line-highlight-color)",
|
||||||
|
"clickable": "var(--vp-c-text-2)",
|
||||||
|
"base": "#323232",
|
||||||
|
"disabled": "#C5C5C5",
|
||||||
|
"hover": "var(--vp-c-brand)",
|
||||||
|
"accent": "var(--vp-c-brand)",
|
||||||
|
"error": "var(--vp-c-red)",
|
||||||
|
"errorSurface": "#ffeceb"
|
||||||
|
},
|
||||||
|
"syntax": {
|
||||||
|
"plain": "var(--vp-code-editor-plain)",
|
||||||
|
"comment": {
|
||||||
|
"color": "var(--vp-code-editor-comment)",
|
||||||
|
"fontStyle": "italic"
|
||||||
|
},
|
||||||
|
"keyword": "var(--vp-code-editor-keyword)",
|
||||||
|
"tag": "var(--vp-code-editor-tag)",
|
||||||
|
"punctuation": "var(--vp-code-editor-punctuation)",
|
||||||
|
"definition": "var(--vp-code-editor-definition)",
|
||||||
|
"property": "var(--vp-code-editor-property)",
|
||||||
|
"static": "var(--vp-code-editor-static)",
|
||||||
|
"string": "var(--vp-code-editor-string)"
|
||||||
|
},
|
||||||
|
"font": {
|
||||||
|
"body": "var(--vp-font-family-base)",
|
||||||
|
"mono": "var(--vp-font-family-mono)",
|
||||||
|
"size": "var(--vp-code-font-size)",
|
||||||
|
"lineHeight": "var(--vp-code-line-height)"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -5,13 +5,39 @@
|
|||||||
--vp-c-brand-dark: #DC5A5A;
|
--vp-c-brand-dark: #DC5A5A;
|
||||||
--vp-c-brand-darker: #C45050;
|
--vp-c-brand-darker: #C45050;
|
||||||
|
|
||||||
|
--vp-c-brand-1: #F67373;
|
||||||
|
--vp-c-brand-2: #FF7070;
|
||||||
|
--vp-c-brand-3: #F56565;
|
||||||
|
--vp-c-brand-4: #DC5A5A;
|
||||||
|
--vp-c-brand-5: #C45050;
|
||||||
|
|
||||||
--vp-c-bg-alt-up: #fff;
|
--vp-c-bg-alt-up: #fff;
|
||||||
--vp-c-bg-alt-down: #fff;
|
--vp-c-bg-alt-down: #fff;
|
||||||
|
|
||||||
|
--vp-code-editor-plain: #24292E;
|
||||||
|
--vp-code-editor-comment: #6A737D;
|
||||||
|
--vp-code-editor-keyword: #D73A49;
|
||||||
|
--vp-code-editor-tag: #22863A;
|
||||||
|
--vp-code-editor-punctuation: #24292E;
|
||||||
|
--vp-code-editor-definition: #6F42C1;
|
||||||
|
--vp-code-editor-property: #005CC5;
|
||||||
|
--vp-code-editor-static: #F78C6C;
|
||||||
|
--vp-code-editor-string: #032F62;
|
||||||
}
|
}
|
||||||
|
|
||||||
.dark {
|
.dark {
|
||||||
--vp-c-bg-alt-up: #1B1B1D;
|
--vp-c-bg-alt-up: #1B1B1D;
|
||||||
--vp-c-bg-alt-down: #0F0F10;
|
--vp-c-bg-alt-down: #0F0F10;
|
||||||
|
|
||||||
|
--vp-code-editor-plain: #E1E4E8;
|
||||||
|
--vp-code-editor-comment: #6A737D;
|
||||||
|
--vp-code-editor-keyword: #F97583;
|
||||||
|
--vp-code-editor-tag: #85E89D;
|
||||||
|
--vp-code-editor-punctuation: #9ECBFF;
|
||||||
|
--vp-code-editor-definition: #B392F0;
|
||||||
|
--vp-code-editor-property: #79B8FF;
|
||||||
|
--vp-code-editor-static: #F78C6C;
|
||||||
|
--vp-code-editor-string: #9ECBFF;
|
||||||
}
|
}
|
||||||
|
|
||||||
.VPNavBarTitle .logo {
|
.VPNavBarTitle .logo {
|
||||||
@@ -126,3 +152,52 @@
|
|||||||
html:has(* .outline-link:target) {
|
html:has(* .outline-link:target) {
|
||||||
scroll-behavior: smooth;
|
scroll-behavior: smooth;
|
||||||
} */
|
} */
|
||||||
|
|
||||||
|
.sp-wrapper .sp-layout {
|
||||||
|
border-radius: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sp-wrapper .sp-tabs-scrollable-container {
|
||||||
|
border-radius: 8px 8px 0 0;
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
box-shadow: inset 0 -1px var(--vp-code-tab-divider);
|
||||||
|
margin-bottom: 0px;
|
||||||
|
margin-top: -1px;
|
||||||
|
height: 48px;
|
||||||
|
padding-bottom: 1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sp-wrapper .sp-preview-container {
|
||||||
|
background-color: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sp-wrapper .sp-tabs .sp-tab-button {
|
||||||
|
padding: 0 12px;
|
||||||
|
line-height: 48px;
|
||||||
|
height: 48px;
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 500;
|
||||||
|
position: relative;
|
||||||
|
/* box-sizing: content-box; */
|
||||||
|
}
|
||||||
|
|
||||||
|
.sp-wrapper .sp-tabs .sp-tab-button:after {
|
||||||
|
position: absolute;
|
||||||
|
right: 8px;
|
||||||
|
left: 8px;
|
||||||
|
bottom: 0px;
|
||||||
|
z-index: 1;
|
||||||
|
height: 1px;
|
||||||
|
content: '';
|
||||||
|
background-color: transparent;
|
||||||
|
transition: background-color 0.25s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sp-wrapper .sp-tabs .sp-tab-button[data-active="true"] {
|
||||||
|
color: var(--vp-code-tab-active-text-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.sp-wrapper .sp-tabs .sp-tab-button[data-active="true"]:after {
|
||||||
|
background-color: var(--vp-code-tab-active-bar-color);
|
||||||
|
}
|
||||||
|
|||||||
@@ -44,3 +44,14 @@ export interface Release {
|
|||||||
version: string
|
version: string
|
||||||
date: string
|
date: string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface ShowcaseItemImage {
|
||||||
|
light: string
|
||||||
|
dark: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ShowcaseItem {
|
||||||
|
name: string
|
||||||
|
url: string
|
||||||
|
image: ShowcaseItemImage
|
||||||
|
}
|
||||||
|
|||||||
6
docs/.vitepress/theme/utils/downloadData.ts
Normal file
6
docs/.vitepress/theme/utils/downloadData.ts
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
export default function downloadData(filename:string, data:string) {
|
||||||
|
const link = document.createElement('a');
|
||||||
|
link.download = filename;
|
||||||
|
link.href = data
|
||||||
|
link.click();
|
||||||
|
}
|
||||||
34
docs/.vitepress/theme/utils/getSVGIcon.ts
Normal file
34
docs/.vitepress/theme/utils/getSVGIcon.ts
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
const allowedAttrs = [
|
||||||
|
'xmlns',
|
||||||
|
'width',
|
||||||
|
'height',
|
||||||
|
'viewBox',
|
||||||
|
'fill',
|
||||||
|
'stroke',
|
||||||
|
'stroke-width',
|
||||||
|
'stroke-linecap',
|
||||||
|
'stroke-linejoin',
|
||||||
|
'class',
|
||||||
|
]
|
||||||
|
|
||||||
|
export default function getSVGIcon(element?: HTMLElement, attrs?: Record<string, string>) {
|
||||||
|
const svg = element ?? document.querySelector('#previewer svg')
|
||||||
|
if (!svg) return
|
||||||
|
|
||||||
|
const clonedSvg = svg.cloneNode(true) as SVGElement
|
||||||
|
|
||||||
|
// Filter out attributes that are not allowed in SVGs
|
||||||
|
for (const attr of Array.from(clonedSvg.attributes)) {
|
||||||
|
if (!allowedAttrs.includes(attr.name)) {
|
||||||
|
clonedSvg.removeAttribute(attr.name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const [key, value] of Object.entries(attrs ?? {})) {
|
||||||
|
clonedSvg.setAttribute(key, value)
|
||||||
|
}
|
||||||
|
|
||||||
|
const svgString = new XMLSerializer().serializeToString(clonedSvg)
|
||||||
|
|
||||||
|
return svgString
|
||||||
|
}
|
||||||
14
docs/.vitepress/vue-shim.d.ts
vendored
14
docs/.vitepress/vue-shim.d.ts
vendored
@@ -1,10 +1,18 @@
|
|||||||
declare module "*.vue" {
|
declare module '*.vue' {
|
||||||
import Vue from "vue";
|
import Vue from 'vue';
|
||||||
export default Vue;
|
export default Vue;
|
||||||
}
|
}
|
||||||
|
|
||||||
declare module "*.data.ts" {
|
declare module '*.data.ts' {
|
||||||
const data: any;
|
const data: any;
|
||||||
|
|
||||||
export { data };
|
export { data };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
declare module '*.wasm' {}
|
||||||
|
|
||||||
|
declare const resvg_wasm: RequestInfo | URL | Response | BufferSource | WebAssembly.Module;
|
||||||
|
|
||||||
|
declare module 'node:module' {
|
||||||
|
function createRequire(filename: string): NodeRequire;
|
||||||
|
}
|
||||||
|
|||||||
@@ -3,8 +3,6 @@
|
|||||||
The Lucide docs website is built with Vitepress: https://vitepress.dev/
|
The Lucide docs website is built with Vitepress: https://vitepress.dev/
|
||||||
This is Markdown-based documentation powered by Vue.
|
This is Markdown-based documentation powered by Vue.
|
||||||
|
|
||||||
This is why this file is in txt format.
|
|
||||||
|
|
||||||
## Development
|
## Development
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
4
docs/guide/advanced/accessibility.md
Normal file
4
docs/guide/advanced/accessibility.md
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
# Accessibility
|
||||||
|
|
||||||
|
<!-- Description how you should use svg icons keeping web accessible -->
|
||||||
|
<!-- See @JanTrichter comment about some information to write this: https://github.com/lucide-icons/lucide/pull/1521#discussion_r1332141390 -->
|
||||||
13
docs/guide/advanced/filled-icons.md
Normal file
13
docs/guide/advanced/filled-icons.md
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
# Filled Icons
|
||||||
|
|
||||||
|
Fills are officially not supported.
|
||||||
|
However, all SVG properties are available on all icons.
|
||||||
|
Fill can still be used and will work fine on certain icons.
|
||||||
|
|
||||||
|
Example with stars:
|
||||||
|
|
||||||
|
<!-- Code Example with stars -->
|
||||||
|
|
||||||
|
## Will Lucide have fills in the future?
|
||||||
|
|
||||||
|
This feature is requested several times and discussion is happening at: [#458](https://github.com/lucide-icons/lucide/discussions/458).
|
||||||
52
docs/guide/basics/color.md
Normal file
52
docs/guide/basics/color.md
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
<script setup>
|
||||||
|
import { Sandpack } from 'sandpack-vue3'
|
||||||
|
import sandpackTheme from '../../.vitepress/theme/sandpackTheme.json'
|
||||||
|
import buttonExampleFiles from './examples/button-example/files.ts'
|
||||||
|
import iconColorExampleFiles from './examples/color-icon/files.ts'
|
||||||
|
</script>
|
||||||
|
|
||||||
|
# Color
|
||||||
|
|
||||||
|
By default, all icons have the color value: `currentColor`. This keyword uses the element's computed text `color` value to represent the icon color.
|
||||||
|
|
||||||
|
Read more about [ `currentColor` on MDN](https://developer.mozilla.org/en-US/docs/Web/CSS/color_value#currentcolor_keyword).
|
||||||
|
|
||||||
|
## Adjust the color using the `color` prop
|
||||||
|
|
||||||
|
The color can be adjusted by passing the color prop to the element.
|
||||||
|
|
||||||
|
<Sandpack
|
||||||
|
template="react"
|
||||||
|
:theme="sandpackTheme"
|
||||||
|
:files="iconColorExampleFiles"
|
||||||
|
:customSetup='{
|
||||||
|
dependencies: {
|
||||||
|
"lucide-react": "latest"
|
||||||
|
}
|
||||||
|
}'
|
||||||
|
:options="{
|
||||||
|
editorHeight: 295,
|
||||||
|
editorWidthPercentage: 60,
|
||||||
|
}"
|
||||||
|
/>
|
||||||
|
|
||||||
|
## Using parent elements text color value
|
||||||
|
|
||||||
|
Because the color of lucide icons uses `currentColor`, the color of the icon depends on the computed `color` of the element, or it inherits it from its parent.
|
||||||
|
|
||||||
|
For example, if a parent element's color value is `#fff` and one of the children is a lucide icon, the color of the icon will be rendered as `#fff`. This is browser native behavior.
|
||||||
|
|
||||||
|
<Sandpack
|
||||||
|
template="react"
|
||||||
|
:theme="sandpackTheme"
|
||||||
|
:files="buttonExampleFiles"
|
||||||
|
:customSetup='{
|
||||||
|
dependencies: {
|
||||||
|
"lucide-react": "latest"
|
||||||
|
}
|
||||||
|
}'
|
||||||
|
:options="{
|
||||||
|
editorHeight: 320,
|
||||||
|
editorWidthPercentage: 60,
|
||||||
|
}"
|
||||||
|
/>
|
||||||
14
docs/guide/basics/examples/absolute-stroke-width-icon/App.js
Normal file
14
docs/guide/basics/examples/absolute-stroke-width-icon/App.js
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
import { RollerCoaster } from "lucide-react";
|
||||||
|
|
||||||
|
function App() {
|
||||||
|
return (
|
||||||
|
<div className="app">
|
||||||
|
<RollerCoaster
|
||||||
|
size={96}
|
||||||
|
absoluteStrokeWidth={true}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default App;
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
import App from './App.js?raw'
|
||||||
|
import styles from '../styles.css?raw'
|
||||||
|
|
||||||
|
const files = {
|
||||||
|
'App.js': {
|
||||||
|
code: App,
|
||||||
|
active: true,
|
||||||
|
},
|
||||||
|
'styles.css': {
|
||||||
|
code:styles,
|
||||||
|
hidden: true
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
export default files
|
||||||
5
docs/guide/basics/examples/button-example/App.js
Normal file
5
docs/guide/basics/examples/button-example/App.js
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
import Button from "./Button";
|
||||||
|
|
||||||
|
export default function App() {
|
||||||
|
return <Button />;
|
||||||
|
}
|
||||||
12
docs/guide/basics/examples/button-example/Button.jsx
Normal file
12
docs/guide/basics/examples/button-example/Button.jsx
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
import { ThumbsUp } from "lucide-react";
|
||||||
|
|
||||||
|
function LikeButton() {
|
||||||
|
return (
|
||||||
|
<button style={{ color: "#fff" }}>
|
||||||
|
<ThumbsUp />
|
||||||
|
Like
|
||||||
|
</button>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default LikeButton;
|
||||||
21
docs/guide/basics/examples/button-example/files.ts
Normal file
21
docs/guide/basics/examples/button-example/files.ts
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
import App from './App.js?raw'
|
||||||
|
import Button from './Button.jsx?raw'
|
||||||
|
import styles from '../styles.css?raw'
|
||||||
|
|
||||||
|
const files = {
|
||||||
|
'App.js': {
|
||||||
|
code: App,
|
||||||
|
hidden: true
|
||||||
|
},
|
||||||
|
'Button.jsx': {
|
||||||
|
code: Button,
|
||||||
|
active: true,
|
||||||
|
readOnly: false,
|
||||||
|
},
|
||||||
|
'styles.css': {
|
||||||
|
code:styles,
|
||||||
|
hidden: true
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
export default files
|
||||||
11
docs/guide/basics/examples/color-icon/App.js
Normal file
11
docs/guide/basics/examples/color-icon/App.js
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
import { Smile } from "lucide-react";
|
||||||
|
|
||||||
|
function App() {
|
||||||
|
return (
|
||||||
|
<div className="app">
|
||||||
|
<Smile color="#3e9392" />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default App;
|
||||||
15
docs/guide/basics/examples/color-icon/files.ts
Normal file
15
docs/guide/basics/examples/color-icon/files.ts
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
import App from './App.js?raw'
|
||||||
|
import styles from '../styles.css?raw'
|
||||||
|
|
||||||
|
const files = {
|
||||||
|
'App.js': {
|
||||||
|
code: App,
|
||||||
|
active: true,
|
||||||
|
},
|
||||||
|
'styles.css': {
|
||||||
|
code:styles,
|
||||||
|
hidden: true
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
export default files
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user