Compare commits

...

21 Commits

Author SHA1 Message Date
Daniel Bayley
36725eeed9 Add mailbox icon (#1000)
Update icons/mailbox.svg

Co-authored-by: Karsa <contact@karsa.org>
2023-04-08 17:11:36 +02:00
Eric Fennis
ee7ee203e6 Add details summary markdown GitHub comment (#1024)
* Add details and summary github comment

* optimize icons

* test

* replace back main domain

* Revert "optimize icons"

This reverts commit a7e9186a09.
2023-04-08 12:21:35 +02:00
Lucide Bot
7a26dddbcb 📦 Bump lucide package versions to 0.131.0 2023-04-08 09:40:17 +00:00
Karsa
408c683a13 Adds receipt icon (#974)
* Add more music icons and another mic icon (#746)

* Revert "Add more music icons and another mic icon (#746)" (#750)

This reverts commit 57cba6ae0e.

* adds receipt icon

* Update icons/receipt.svg

---------

Co-authored-by: it-is-not <72697755+it-is-not@users.noreply.github.com>
Co-authored-by: Karsa <karsa@karsa.org>
2023-04-08 11:35:09 +02:00
Lucide Bot
546cf61a2e 📦 Bump lucide package versions to 0.130.1 2023-04-05 10:35:22 +00:00
Eric Fennis
a7496aa454 Fix alias support (#1008)
* minor improvements

* minor improvements

* Enable icons aliases CJS

* Add aliasesSupport to configs

* Add link to pnpm-workspace.yaml
2023-04-03 21:54:18 +02:00
Jakob Guddas
93cfd3d27d Added github comment icon workflow (#946)
* feat: added github comment icon workflow

* feat: improved segment node styling

* feat: improved segment node styling

* fix: fixed grid alignment issue

* chore: cleanup

* fix: added ref forwarding to SvgPreview component

* chore: removed svg preview from icon detail overlay

* chore: updated tj-actions/changed-files

* chore: switched to pull_request_target

* chore: simplified path segment highlighting logic

* Fixes incorrect relative links in documentation pages (#973)

* Fixes incorrect relative links in documentation pages

* Unifies documentation page names to avoid 404 links

---------

Co-authored-by: Karsa <karsa@karsa.org>

* Add forklift icon (#943)

* Fix vercel build

* Add forklift icon

Co-Authored-By: willythewizard <119956499+willythewizard@users.noreply.github.com>

---------

Co-authored-by: willythewizard <119956499+willythewizard@users.noreply.github.com>

* adds utility-pole icon (#971)

Co-authored-by: Karsa <karsa@karsa.org>

* 📦 Bump lucide package versions to 0.123.0

* Adds `nfc` icons (#960)

* added nfc icons

* fixes smartphone-nfc

* Update icons/nfc.svg

Co-authored-by: Jakob Guddas <github@jguddas.de>

* Update icons/smartphone-nfc.svg

Co-authored-by: Jakob Guddas <github@jguddas.de>

---------

Co-authored-by: Karsa <karsa@karsa.org>
Co-authored-by: Jakob Guddas <github@jguddas.de>

* 📦 Bump lucide package versions to 0.124.0

* fix: updated pnpm-lock.yaml

* fix: added missing api endpoint file

* chore: fixed nextjs path name parsing in production

* chore: only run workflow when path includes icons/*.svg

* chore: added Cache-Control header to gh-icon api route response

* feat: added dark mode support to gh-icon

* feat: switched to using picture tag for gh-icon

* feat: added space between gh-icons in pr comment

* fix: changed icon size base back to 24x24

* feat: added title to gh-icon comment image

* fix: changed gh-icon url

* chore: added groups with class names

* feat: improved shadow masking

* Removes need for building duplicate icons by supporting CSS based dark mode

* chore: resolved type issues

* feat: changed image width from 48% to 400px

---------

Co-authored-by: Karsa <contact@karsa.org>
Co-authored-by: Karsa <karsa@karsa.org>
Co-authored-by: Eric Fennis <eric.fennis@gmail.com>
Co-authored-by: willythewizard <119956499+willythewizard@users.noreply.github.com>
Co-authored-by: Lucide Bot <lucide-bot@users.noreply.github.com>
2023-04-03 21:05:59 +02:00
Daniel Bayley
76ce22ef14 Improve infinity icon (#993)
Update icons/infinity.svg

Co-authored-by: Karsa <contact@karsa.org>
2023-04-02 21:16:56 +02:00
Lucide Bot
873997b48e 📦 Bump lucide package versions to 0.130.0 2023-04-02 19:06:34 +00:00
Daniel Bayley
03276eee9d Add chevron-*-square (including terminal alternate) icons (#996)
* Add `terminal-square` alternate icon

* Add `chevron-right-square` (alternate `terminal`) icon

* Add `chevron-left-square` icon

* Add `chevron-up-square` icon

* Add `chevron-down-square` icon

* Add metadata for `chevron-right`
2023-04-02 21:00:40 +02:00
Daniel Bayley
cf5aa0534b Improve refresh-* metadata (#999)
Update icons/refresh-ccw.json


Update icons/refresh-cw.json

Co-authored-by: Karsa <contact@karsa.org>
2023-04-02 17:29:38 +02:00
Eric Fennis
cccf89e7bb Update ci.yml 2023-04-02 17:29:24 +02:00
Lucide Bot
2d4676160b 📦 Bump lucide package versions to 0.129.0 2023-03-29 06:46:00 +00:00
Daniel Bayley
6346d80ee7 Fix package icon (#989)
Centre line is extended too far.
2023-03-29 08:40:40 +02:00
Lucide Bot
e983ccf974 📦 Bump lucide package versions to 0.128.0 2023-03-27 14:02:39 +00:00
Karsa
f0fe196872 Adds plane-takeoff & plane-landing icons (#964)
* Add more music icons and another mic icon (#746)

* Revert "Add more music icons and another mic icon (#746)" (#750)

This reverts commit 57cba6ae0e.

* adds plane-takeoff & plane-landing icons

---------

Co-authored-by: it-is-not <72697755+it-is-not@users.noreply.github.com>
Co-authored-by: Karsa <karsa@karsa.org>
2023-03-27 15:55:17 +02:00
Lucide Bot
85eaa5fc50 📦 Bump lucide package versions to 0.127.0 2023-03-20 19:48:30 +00:00
Karsa
6a7732077a Adds parking-* and parking-*-off icons (#972)
* adds parking and parking-off icons

* Update icons/parking-square.svg

Co-authored-by: Jakob Guddas <github@jguddas.de>

* Update icons/parking-circle.svg

Co-authored-by: Jakob Guddas <github@jguddas.de>

---------

Co-authored-by: Karsa <karsa@karsa.org>
Co-authored-by: Jakob Guddas <github@jguddas.de>
2023-03-20 20:42:08 +01:00
Lucide Bot
c1c0f99d65 📦 Bump lucide package versions to 0.126.0 2023-03-19 20:12:27 +00:00
Karsa
ee2bfaff0d Adds brain (ai) icons (#967)
* Add more music icons and another mic icon (#746)

* Revert "Add more music icons and another mic icon (#746)" (#750)

This reverts commit 57cba6ae0e.

* adds brain icons

* adds extra AI tags

* Update icons/brain-circuit.svg

Co-authored-by: Jakob Guddas <github@jguddas.de>

* Update brain.svg

* Update brain-circuit.svg

---------

Co-authored-by: it-is-not <72697755+it-is-not@users.noreply.github.com>
Co-authored-by: Karsa <karsa@karsa.org>
Co-authored-by: Jakob Guddas <github@jguddas.de>
2023-03-19 21:06:44 +01:00
Lucide Bot
9370449d7e 📦 Bump lucide package versions to 0.125.0 2023-03-10 21:18:55 +00:00
62 changed files with 1854 additions and 1291 deletions

View File

@@ -5,7 +5,7 @@ on:
branches: branches:
- main - main
paths: paths:
- icons/** - icons/**/*.svg
jobs: jobs:
create-release: create-release:

57
.github/workflows/pull-request.yml vendored Normal file
View File

@@ -0,0 +1,57 @@
name: Add Changed Icons comment
on:
pull_request_target:
paths:
- 'icons/*.svg'
permissions:
pull-requests: write
contents: write
jobs:
add-changed-icons-comment:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
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/*.svg
- name: Generate comment
id: generate-comment
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 width=\"400\" title=\"$file\" alt=\"$file\" src=\"https://lucide.dev/api/gh-icon/&.svg\"/> |"
done | tr '\n' ' ' >> $GITHUB_OUTPUT
echo >> $GITHUB_OUTPUT
echo "$delimiter" >> $GITHUB_OUTPUT
- name: Find Comment
uses: peter-evans/find-comment@v2
id: fc
with:
issue-number: ${{ github.event.pull_request.number }}
comment-author: 'github-actions[bot]'
body-includes: Added or changed icons
- name: Create or update comment
uses: peter-evans/create-or-update-comment@v2
with:
comment-id: ${{ steps.fc.outputs.comment-id }}
issue-number: ${{ github.event.pull_request.number }}
body: |
### Added or changed icons
<details>
<summary>Icon X-rays</summary>
${{ steps.generate-comment.outputs.body }}
</details>
edit-mode: replace

View File

@@ -59,13 +59,13 @@ If you are a designer who wants to contribute to Lucide but you don't know what
## Development ## Development
You will need minimum version of [Nodejs 16.4+](https://nodejs.org) You will need minimum version of [Nodejs 16.4+](https://nodejs.org)
For packagemanagement you will need [yarn v1](https://yarnpkg.com/getting-started/install). For package management you will need [PNPM](https://pnpm.io/installation).
For flutter package development, you need [Flutter 1.17+](https://docs.flutter.dev/get-started/install). For flutter package development, you need [Flutter 1.17+](https://docs.flutter.dev/get-started/install).
After cloning the project you need to run: After cloning the project you need to run:
```sh ```sh
yarn # Install dependencies, including the workspace packages pnpm install # Install dependencies, including the workspace packages
``` ```
### Packages -> PNPM Workspaces ### Packages -> PNPM Workspaces
@@ -73,6 +73,7 @@ yarn # Install dependencies, including the workspace packages
To distribute different packages we use PNPM workspaces. Before you start make sure you are familiar with this concept. The concept of working in workspaces is created by Yarn, they have a well written introduction: [yarn workspaces](https://classic.yarnpkg.com/lang/en/docs/workspaces). To distribute different packages we use PNPM workspaces. Before you start make sure you are familiar with this concept. The concept of working in workspaces is created by Yarn, they have a well written introduction: [yarn workspaces](https://classic.yarnpkg.com/lang/en/docs/workspaces).
The configured directory for workspaces is the [packages](./packages) directory, located in the root directory. There you will find all the current packages from lucide. The configured directory for workspaces is the [packages](./packages) directory, located in the root directory. There you will find all the current packages from lucide.
There are more workspaces defined, see [`pnpm-workspace.yaml`](./pnpm-workspace.yaml).
> Note: One package is not managed by pnpm: **lucide-flutter**, this package is written in Dart and used pub for publishing. > Note: One package is not managed by pnpm: **lucide-flutter**, this package is written in Dart and used pub for publishing.

16
icons/brain-circuit.json Normal file
View File

@@ -0,0 +1,16 @@
{
"$schema": "../icon.schema.json",
"tags": [
"mind",
"intellect",
"artificial intelligence",
"ai",
"deep learning",
"machine learning",
"computing"
],
"categories": [
"science",
"development"
]
}

21
icons/brain-circuit.svg Normal file
View File

@@ -0,0 +1,21 @@
<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"
>
<path d="M12 4.5a2.5 2.5 0 0 0-4.96-.46 2.5 2.5 0 0 0-1.98 3 2.5 2.5 0 0 0-1.32 4.24 3 3 0 0 0 .34 5.58 2.5 2.5 0 0 0 2.96 3.08 2.5 2.5 0 0 0 4.91.05L12 20V4.5Z" />
<path d="M16 8V5c0-1.1.9-2 2-2" />
<path d="M12 13h4" />
<path d="M12 18h6a2 2 0 0 1 2 2v1" />
<path d="M12 8h8" />
<path d="M20.5 8a.5.5 0 1 1-1 0 .5.5 0 0 1 1 0Z" />
<path d="M16.5 13a.5.5 0 1 1-1 0 .5.5 0 0 1 1 0Z" />
<path d="M20.5 21a.5.5 0 1 1-1 0 .5.5 0 0 1 1 0Z" />
<path d="M18.5 3a.5.5 0 1 1-1 0 .5.5 0 0 1 1 0Z" />
</svg>

After

Width:  |  Height:  |  Size: 721 B

16
icons/brain-cog.json Normal file
View File

@@ -0,0 +1,16 @@
{
"$schema": "../icon.schema.json",
"tags": [
"mind",
"intellect",
"artificial intelligence",
"ai",
"deep learning",
"machine learning",
"computing"
],
"categories": [
"science",
"development"
]
}

20
icons/brain-cog.svg Normal file
View File

@@ -0,0 +1,20 @@
<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"
>
<path d="M12 4.5a2.5 2.5 0 0 0-4.96-.46 2.5 2.5 0 0 0-1.98 3 2.5 2.5 0 0 0-1.32 4.24 3 3 0 0 0 .34 5.58 2.5 2.5 0 0 0 2.96 3.08A2.5 2.5 0 0 0 9.5 22c1.21 0 2.5-.74 2.5-2.5m0-15a2.5 2.5 0 0 1 4.96-.46 2.5 2.5 0 0 1 1.98 3 2.5 2.5 0 0 1 1.32 4.24 3 3 0 0 1-.34 5.58 2.5 2.5 0 0 1-2.96 3.08A2.5 2.5 0 0 1 14.5 22c-1.21 0-2.5-.74-2.5-2.5m0-15V5m0 14.5V19" />
<circle cx="12" cy="12" r="2" />
<path d="M12 9v1" />
<path d="M12 14v1" />
<path d="m14.6 10.5-.87.5" />
<path d="m10.27 13-.87.5" />
<path d="m14.6 13.5-.87-.5" />
<path d="m10.27 11-.87-.5" />
</svg>

After

Width:  |  Height:  |  Size: 775 B

17
icons/brain.json Normal file
View File

@@ -0,0 +1,17 @@
{
"$schema": "../icon.schema.json",
"tags": [
"medical",
"mind",
"intellect",
"cerebral",
"consciousness",
"genius",
"artificial intelligence",
"ai"
],
"categories": [
"medical",
"science"
]
}

14
icons/brain.svg Normal file
View File

@@ -0,0 +1,14 @@
<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"
>
<path d="M9.5 2A2.5 2.5 0 0 1 12 4.5v15a2.5 2.5 0 0 1-4.96.44 2.5 2.5 0 0 1-2.96-3.08 3 3 0 0 1-.34-5.58 2.5 2.5 0 0 1 1.32-4.24 2.5 2.5 0 0 1 1.98-3A2.5 2.5 0 0 1 9.5 2Z" />
<path d="M14.5 2A2.5 2.5 0 0 0 12 4.5v15a2.5 2.5 0 0 0 4.96.44 2.5 2.5 0 0 0 2.96-3.08 3 3 0 0 0 .34-5.58 2.5 2.5 0 0 0-1.32-4.24 2.5 2.5 0 0 0-1.98-3A2.5 2.5 0 0 0 14.5 2Z" />
</svg>

After

Width:  |  Height:  |  Size: 564 B

View File

@@ -0,0 +1,10 @@
{
"$schema": "../icon.schema.json",
"tags": [
"arrow"
],
"categories": [
"arrows",
"shapes"
]
}

View File

@@ -0,0 +1,14 @@
<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"
>
<rect x="3" y="3" width="18" height="18" rx="2" ry="2" />
<polyline points="16,10 12,14 8,10" />
</svg>

After

Width:  |  Height:  |  Size: 309 B

View File

@@ -0,0 +1,10 @@
{
"$schema": "../icon.schema.json",
"tags": [
"arrow"
],
"categories": [
"arrows",
"shapes"
]
}

View File

@@ -0,0 +1,14 @@
<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"
>
<rect x="3" y="3" width="18" height="18" rx="2" ry="2" />
<polyline points="14,16 10,12 14,8 " />
</svg>

After

Width:  |  Height:  |  Size: 310 B

View File

@@ -0,0 +1,15 @@
{
"$schema": "../icon.schema.json",
"tags": [
"code",
"command line",
"terminal",
"prompt",
"shell"
],
"categories": [
"coding",
"development",
"shapes"
]
}

View File

@@ -0,0 +1,14 @@
<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"
>
<rect x="3" y="3" width="18" height="18" rx="2" ry="2" />
<polyline points="10,8 14,12 10,16" />
</svg>

After

Width:  |  Height:  |  Size: 309 B

View File

@@ -1,9 +1,17 @@
{ {
"$schema": "../icon.schema.json", "$schema": "../icon.schema.json",
"tags": [ "tags": [
"arrow" "arrow",
"code",
"command line",
"terminal",
"prompt",
"shell"
], ],
"categories": [ "categories": [
"arrows" "arrows",
"coding",
"development",
"shapes"
] ]
} }

View File

@@ -0,0 +1,10 @@
{
"$schema": "../icon.schema.json",
"tags": [
"arrow"
],
"categories": [
"arrows",
"shapes"
]
}

View File

@@ -0,0 +1,14 @@
<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"
>
<rect x="3" y="3" width="18" height="18" rx="2" ry="2" />
<polyline points="8,14 12,10 16,14" />
</svg>

After

Width:  |  Height:  |  Size: 309 B

View File

@@ -9,5 +9,5 @@
stroke-linecap="round" stroke-linecap="round"
stroke-linejoin="round" stroke-linejoin="round"
> >
<path d="M18.178 8c5.096 0 5.096 8 0 8-5.095 0-7.133-8-12.739-8-4.585 0-4.585 8 0 8 5.606 0 7.644-8 12.74-8z" /> <path d="M12 12c-2-2.67-4-4-6-4a4 4 0 1 0 0 8c2 0 4-1.33 6-4Zm0 0c2 2.67 4 4 6 4a4 4 0 0 0 0-8c-2 0-4 1.33-6 4Z" />
</svg> </svg>

Before

Width:  |  Height:  |  Size: 323 B

After

Width:  |  Height:  |  Size: 326 B

13
icons/mailbox.json Normal file
View File

@@ -0,0 +1,13 @@
{
"$schema": "../icon.schema.json",
"tags": [
"emails",
"messages",
"letters",
"mailing list",
"newsletter"
],
"categories": [
"mail"
]
}

16
icons/mailbox.svg Normal file
View File

@@ -0,0 +1,16 @@
<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"
>
<path d="M22 17a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V9.5C2 7 4 5 6.5 5H18c2.2 0 4 1.8 4 4v8Z" />
<polyline points="15,9 18,9 18,11" />
<path d="M6.5 5C9 5 11 7 11 9.5V17a2 2 0 0 1-2 2v0" />
<line x1="6" y1="10" x2="7" y2="10" />
</svg>

After

Width:  |  Height:  |  Size: 438 B

View File

@@ -9,7 +9,7 @@
stroke-linecap="round" stroke-linecap="round"
stroke-linejoin="round" stroke-linejoin="round"
> >
<line x1="16.5" y1="9.4" x2="7.5" y2="4.21" /> <path d="M16.5 9.4 7.55 4.24" />
<path d="M21 16V8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16z" /> <path d="M21 16V8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16z" />
<polyline points="3.29 7 12 12 20.71 7" /> <polyline points="3.29 7 12 12 20.71 7" />
<line x1="12" y1="22" x2="12" y2="12" /> <line x1="12" y1="22" x2="12" y2="12" />

Before

Width:  |  Height:  |  Size: 482 B

After

Width:  |  Height:  |  Size: 468 B

View File

@@ -0,0 +1,12 @@
{
"$schema": "../icon.schema.json",
"tags": [
"parking lot",
"car park",
"no parking"
],
"categories": [
"transportation",
"maps"
]
}

View File

@@ -0,0 +1,16 @@
<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"
>
<circle cx="12" cy="12" r="10" />
<path d="m5 5 14 14" />
<path d="M13 13a3 3 0 1 0 0-6H9v2" />
<path d="M9 17v-2.34" />
</svg>

After

Width:  |  Height:  |  Size: 337 B

11
icons/parking-circle.json Normal file
View File

@@ -0,0 +1,11 @@
{
"$schema": "../icon.schema.json",
"tags": [
"parking lot",
"car park"
],
"categories": [
"transportation",
"maps"
]
}

14
icons/parking-circle.svg Normal file
View File

@@ -0,0 +1,14 @@
<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"
>
<circle cx="12" cy="12" r="10" />
<path d="M9 17V7h4a3 3 0 0 1 0 6H9" />
</svg>

After

Width:  |  Height:  |  Size: 285 B

View File

@@ -0,0 +1,12 @@
{
"$schema": "../icon.schema.json",
"tags": [
"parking lot",
"car park",
"no parking"
],
"categories": [
"transportation",
"maps"
]
}

View File

@@ -0,0 +1,17 @@
<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"
>
<path d="M3.59 3.59A2 2 0 0 1 5 3h14a2 2 0 0 1 2 2v14a2 2 0 0 1-.59 1.41" />
<path d="M3 8.66V19c0 1.1.9 2 2 2h10.34" />
<path d="m2 2 20 20" />
<path d="M13 13a3 3 0 1 0 0-6H9v2" />
<path d="M9 17v-2.34" />
</svg>

After

Width:  |  Height:  |  Size: 426 B

11
icons/parking-square.json Normal file
View File

@@ -0,0 +1,11 @@
{
"$schema": "../icon.schema.json",
"tags": [
"parking lot",
"car park"
],
"categories": [
"transportation",
"maps"
]
}

14
icons/parking-square.svg Normal file
View File

@@ -0,0 +1,14 @@
<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"
>
<rect width="18" height="18" x="3" y="3" rx="2" />
<path d="M9 17V7h4a3 3 0 0 1 0 6H9" />
</svg>

After

Width:  |  Height:  |  Size: 302 B

14
icons/plane-landing.json Normal file
View File

@@ -0,0 +1,14 @@
{
"$schema": "../icon.schema.json",
"tags": [
"arrival",
"plane",
"trip",
"airplane",
"landing"
],
"categories": [
"transportation",
"travel"
]
}

14
icons/plane-landing.svg Normal file
View File

@@ -0,0 +1,14 @@
<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"
>
<path d="M2 22h20" />
<path d="M3.77 10.77 2 9l2-4.5 1.1.55c.55.28.9.84.9 1.45s.35 1.17.9 1.45L8 8.5l3-6 1.05.53a2 2 0 0 1 1.09 1.52l.72 5.4a2 2 0 0 0 1.09 1.52l4.4 2.2c.42.22.78.55 1.01.96l.6 1.03c.49.88-.06 1.98-1.06 2.1l-1.18.15c-.47.06-.95-.02-1.37-.24L4.29 11.15a2 2 0 0 1-.52-.38Z" />
</svg>

After

Width:  |  Height:  |  Size: 503 B

14
icons/plane-takeoff.json Normal file
View File

@@ -0,0 +1,14 @@
{
"$schema": "../icon.schema.json",
"tags": [
"departure",
"plane",
"trip",
"airplane",
"takeoff"
],
"categories": [
"transportation",
"travel"
]
}

14
icons/plane-takeoff.svg Normal file
View File

@@ -0,0 +1,14 @@
<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"
>
<path d="M2 22h20" />
<path d="M6.36 17.4 4 17l-2-4 1.1-.55a2 2 0 0 1 1.8 0l.17.1a2 2 0 0 0 1.8 0L8 12 5 6l.9-.45a2 2 0 0 1 2.09.2l4.02 3a2 2 0 0 0 2.1.2l4.19-2.06a2.41 2.41 0 0 1 1.73-.17L21 7a1.4 1.4 0 0 1 .87 1.99l-.38.76c-.23.46-.6.84-1.07 1.08L7.58 17.2a2 2 0 0 1-1.22.18Z" />
</svg>

After

Width:  |  Height:  |  Size: 494 B

14
icons/receipt.json Normal file
View File

@@ -0,0 +1,14 @@
{
"$schema": "../icon.schema.json",
"tags": [
"bill",
"voucher",
"slip",
"check",
"counterfoil"
],
"categories": [
"money",
"travel"
]
}

15
icons/receipt.svg Normal file
View File

@@ -0,0 +1,15 @@
<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"
>
<path d="M4 2v20l2-1 2 1 2-1 2 1 2-1 2 1 2-1 2 1V2l-2 1-2-1-2 1-2-1-2 1-2-1-2 1-2-1Z" />
<path d="M16 8h-6a2 2 0 1 0 0 4h4a2 2 0 1 1 0 4H8" />
<path d="M12 17V7" />
</svg>

After

Width:  |  Height:  |  Size: 379 B

View File

@@ -2,7 +2,12 @@
"$schema": "../icon.schema.json", "$schema": "../icon.schema.json",
"tags": [ "tags": [
"arrows", "arrows",
"reload" "rotate",
"reload",
"synchronise",
"synchronize",
"circular",
"cycle"
], ],
"categories": [ "categories": [
"arrows" "arrows"

View File

@@ -1,10 +1,13 @@
{ {
"$schema": "../icon.schema.json", "$schema": "../icon.schema.json",
"tags": [ "tags": [
"rotate",
"reload", "reload",
"synchronise", "synchronise",
"synchronize", "synchronize",
"arrows" "arrows",
"circular",
"cycle"
], ],
"categories": [ "categories": [
"arrows" "arrows"

View File

@@ -29,17 +29,17 @@
"gi": "node ./scripts/generate/generateIcons.mjs" "gi": "node ./scripts/generate/generateIcons.mjs"
}, },
"devDependencies": { "devDependencies": {
"eslint": "^8.26.0", "eslint": "^8.36.0",
"eslint-config-airbnb-base": "^15.0.0", "eslint-config-airbnb-base": "^15.0.0",
"eslint-config-prettier": "^8.5.0", "eslint-config-prettier": "^8.8.0",
"eslint-plugin-import": "^2.26.0", "eslint-plugin-import": "^2.27.5",
"eslint-plugin-prettier": "^4.2.1", "eslint-plugin-prettier": "^4.2.1",
"husky": "^8.0.1", "husky": "^8.0.3",
"lint-staged": "^13.0.3", "lint-staged": "^13.2.0",
"minimist": "^1.2.7", "minimist": "^1.2.8",
"node-fetch": "^3.2.10", "node-fetch": "^3.3.1",
"prettier": "2.7.1", "prettier": "2.7.1",
"svgo": "^3.0.0", "svgo": "^3.0.2",
"svgson": "^5.2.1" "svgson": "^5.2.1"
}, },
"lint-staged": { "lint-staged": {

View File

@@ -1,7 +1,7 @@
{ {
"name": "lucide-angular", "name": "lucide-angular",
"description": "A Lucide icon library package for Angular applications", "description": "A Lucide icon library package for Angular applications",
"version": "0.124.0", "version": "0.131.0",
"author": "SMAH1", "author": "SMAH1",
"license": "ISC", "license": "ISC",
"homepage": "https://lucide.dev", "homepage": "https://lucide.dev",

View File

@@ -1,6 +1,6 @@
name: lucide_icons name: lucide_icons
description: A Lucide icon library package for Flutter applications. Fork of Feather Icons, open for anyone to contribute icons. description: A Lucide icon library package for Flutter applications. Fork of Feather Icons, open for anyone to contribute icons.
version: 0.124.0 version: 0.131.0
homepage: https://lucide.dev homepage: https://lucide.dev
repository: https://github.com/lucide-icons/lucide repository: https://github.com/lucide-icons/lucide

View File

@@ -1,7 +1,7 @@
{ {
"name": "lucide-preact", "name": "lucide-preact",
"description": "A Lucide icon library package for Preact applications", "description": "A Lucide icon library package for Preact applications",
"version": "0.124.0", "version": "0.131.0",
"license": "ISC", "license": "ISC",
"homepage": "https://lucide.dev", "homepage": "https://lucide.dev",
"bugs": "https://github.com/lucide-icons/lucide/issues", "bugs": "https://github.com/lucide-icons/lucide/issues",

View File

@@ -21,27 +21,24 @@ const bundles = [
format: 'cjs', format: 'cjs',
inputs, inputs,
outputDir, outputDir,
}, aliasesSupport: true
{
format: 'es',
inputs,
outputDir,
}, },
{ {
format: 'esm', format: 'esm',
inputs, inputs,
outputDir, outputDir,
preserveModules: true, preserveModules: true,
aliasesSupport: true
}, },
]; ];
const configs = bundles const configs = bundles
.map(({ inputs, outputDir, format, minify, preserveModules }) => .map(({ inputs, outputDir, format, minify, preserveModules, aliasesSupport }) =>
inputs.map(input => ({ inputs.map(input => ({
input, input,
plugins: [ plugins: [
...( ...(
format !== 'esm' ? [ !aliasesSupport ? [
replace({ replace({
"export * from './aliases';": '', "export * from './aliases';": '',
"export * as icons from './icons';": '', "export * as icons from './icons';": '',

View File

@@ -1,7 +1,7 @@
{ {
"name": "lucide-react-native", "name": "lucide-react-native",
"description": "A Lucide icon library package for React Native applications", "description": "A Lucide icon library package for React Native applications",
"version": "0.124.0", "version": "0.131.0",
"license": "ISC", "license": "ISC",
"homepage": "https://lucide.dev", "homepage": "https://lucide.dev",
"bugs": "https://github.com/lucide-icons/lucide/issues", "bugs": "https://github.com/lucide-icons/lucide/issues",
@@ -29,7 +29,7 @@
"build:icons": "build-icons --output=./src --templateSrc=./scripts/exportTemplate.mjs --renderUniqueKey --iconFileExtension=.ts --exportFileName=index.ts --withAliases --aliasesFileExtension=.ts", "build:icons": "build-icons --output=./src --templateSrc=./scripts/exportTemplate.mjs --renderUniqueKey --iconFileExtension=.ts --exportFileName=index.ts --withAliases --aliasesFileExtension=.ts",
"build:types": "node ./scripts/buildTypes.mjs", "build:types": "node ./scripts/buildTypes.mjs",
"build:bundles": "rollup -c ./rollup.config.mjs", "build:bundles": "rollup -c ./rollup.config.mjs",
"test": "vitest", "test": "vitest run",
"version": "pnpm version --git-tag-version=false" "version": "pnpm version --git-tag-version=false"
}, },
"devDependencies": { "devDependencies": {

View File

@@ -1,7 +1,7 @@
{ {
"name": "lucide-react", "name": "lucide-react",
"description": "A Lucide icon library package for React applications", "description": "A Lucide icon library package for React applications",
"version": "0.124.0", "version": "0.131.0",
"license": "ISC", "license": "ISC",
"homepage": "https://lucide.dev", "homepage": "https://lucide.dev",
"bugs": "https://github.com/lucide-icons/lucide/issues", "bugs": "https://github.com/lucide-icons/lucide/issues",

View File

@@ -21,28 +21,24 @@ const bundles = [
format: 'cjs', format: 'cjs',
inputs, inputs,
outputDir, outputDir,
}, aliasesSupport: true
{
format: 'es',
inputs,
outputDir,
}, },
{ {
format: 'esm', format: 'esm',
inputs, inputs,
outputDir, outputDir,
preserveModules: true, preserveModules: true,
aliasesSupport: true
}, },
]; ];
const configs = bundles const configs = bundles
.map(({ inputs, outputDir, format, minify, preserveModules }) => .map(({ inputs, outputDir, format, minify, preserveModules, aliasesSupport }) =>
inputs.map(input => ({ inputs.map(input => ({
input, input,
plugins: [ plugins: [
// This for aliases, only for esm
...( ...(
format !== 'esm' ? [ !aliasesSupport ? [
replace({ replace({
"export * from './aliases';": '', "export * from './aliases';": '',
"export * as icons from './icons';": '', "export * as icons from './icons';": '',

View File

@@ -342,6 +342,10 @@ export { default as LucideBatteryLow } from './icons/battery-low';
export { default as BatteryMediumIcon } from './icons/battery-medium'; export { default as BatteryMediumIcon } from './icons/battery-medium';
export { default as LucideBatteryMedium } from './icons/battery-medium'; export { default as LucideBatteryMedium } from './icons/battery-medium';
// BatteryWarning aliases
export { default as BatteryWarningIcon } from './icons/battery-warning';
export { default as LucideBatteryWarning } from './icons/battery-warning';
// Battery aliases // Battery aliases
export { default as BatteryIcon } from './icons/battery'; export { default as BatteryIcon } from './icons/battery';
export { default as LucideBattery } from './icons/battery'; export { default as LucideBattery } from './icons/battery';
@@ -370,6 +374,10 @@ export { default as LucideBedSingle } from './icons/bed-single';
export { default as BedIcon } from './icons/bed'; export { default as BedIcon } from './icons/bed';
export { default as LucideBed } from './icons/bed'; export { default as LucideBed } from './icons/bed';
// Beef aliases
export { default as BeefIcon } from './icons/beef';
export { default as LucideBeef } from './icons/beef';
// Beer aliases // Beer aliases
export { default as BeerIcon } from './icons/beer'; export { default as BeerIcon } from './icons/beer';
export { default as LucideBeer } from './icons/beer'; export { default as LucideBeer } from './icons/beer';
@@ -402,10 +410,18 @@ export { default as LucideBike } from './icons/bike';
export { default as BinaryIcon } from './icons/binary'; export { default as BinaryIcon } from './icons/binary';
export { default as LucideBinary } from './icons/binary'; export { default as LucideBinary } from './icons/binary';
// Bird aliases
export { default as BirdIcon } from './icons/bird';
export { default as LucideBird } from './icons/bird';
// Bitcoin aliases // Bitcoin aliases
export { default as BitcoinIcon } from './icons/bitcoin'; export { default as BitcoinIcon } from './icons/bitcoin';
export { default as LucideBitcoin } from './icons/bitcoin'; export { default as LucideBitcoin } from './icons/bitcoin';
// Blinds aliases
export { default as BlindsIcon } from './icons/blinds';
export { default as LucideBlinds } from './icons/blinds';
// BluetoothConnected aliases // BluetoothConnected aliases
export { default as BluetoothConnectedIcon } from './icons/bluetooth-connected'; export { default as BluetoothConnectedIcon } from './icons/bluetooth-connected';
export { default as LucideBluetoothConnected } from './icons/bluetooth-connected'; export { default as LucideBluetoothConnected } from './icons/bluetooth-connected';
@@ -474,6 +490,18 @@ export { default as LucideBox } from './icons/box';
export { default as BoxesIcon } from './icons/boxes'; export { default as BoxesIcon } from './icons/boxes';
export { default as LucideBoxes } from './icons/boxes'; export { default as LucideBoxes } from './icons/boxes';
// BrainCircuit aliases
export { default as BrainCircuitIcon } from './icons/brain-circuit';
export { default as LucideBrainCircuit } from './icons/brain-circuit';
// BrainCog aliases
export { default as BrainCogIcon } from './icons/brain-cog';
export { default as LucideBrainCog } from './icons/brain-cog';
// Brain aliases
export { default as BrainIcon } from './icons/brain';
export { default as LucideBrain } from './icons/brain';
// Briefcase aliases // Briefcase aliases
export { default as BriefcaseIcon } from './icons/briefcase'; export { default as BriefcaseIcon } from './icons/briefcase';
export { default as LucideBriefcase } from './icons/briefcase'; export { default as LucideBriefcase } from './icons/briefcase';
@@ -906,6 +934,10 @@ export { default as LucideComponent } from './icons/component';
export { default as ConciergeBellIcon } from './icons/concierge-bell'; export { default as ConciergeBellIcon } from './icons/concierge-bell';
export { default as LucideConciergeBell } from './icons/concierge-bell'; export { default as LucideConciergeBell } from './icons/concierge-bell';
// Construction aliases
export { default as ConstructionIcon } from './icons/construction';
export { default as LucideConstruction } from './icons/construction';
// Contact aliases // Contact aliases
export { default as ContactIcon } from './icons/contact'; export { default as ContactIcon } from './icons/contact';
export { default as LucideContact } from './icons/contact'; export { default as LucideContact } from './icons/contact';
@@ -966,6 +998,10 @@ export { default as LucideCornerUpRight } from './icons/corner-up-right';
export { default as CpuIcon } from './icons/cpu'; export { default as CpuIcon } from './icons/cpu';
export { default as LucideCpu } from './icons/cpu'; export { default as LucideCpu } from './icons/cpu';
// CreativeCommons aliases
export { default as CreativeCommonsIcon } from './icons/creative-commons';
export { default as LucideCreativeCommons } from './icons/creative-commons';
// CreditCard aliases // CreditCard aliases
export { default as CreditCardIcon } from './icons/credit-card'; export { default as CreditCardIcon } from './icons/credit-card';
export { default as LucideCreditCard } from './icons/credit-card'; export { default as LucideCreditCard } from './icons/credit-card';
@@ -1002,6 +1038,10 @@ export { default as LucideCurlyBraces } from './icons/curly-braces';
export { default as CurrencyIcon } from './icons/currency'; export { default as CurrencyIcon } from './icons/currency';
export { default as LucideCurrency } from './icons/currency'; export { default as LucideCurrency } from './icons/currency';
// DatabaseBackup aliases
export { default as DatabaseBackupIcon } from './icons/database-backup';
export { default as LucideDatabaseBackup } from './icons/database-backup';
// Database aliases // Database aliases
export { default as DatabaseIcon } from './icons/database'; export { default as DatabaseIcon } from './icons/database';
export { default as LucideDatabase } from './icons/database'; export { default as LucideDatabase } from './icons/database';
@@ -1425,6 +1465,10 @@ export { default as LucideFiles } from './icons/files';
export { default as FilmIcon } from './icons/film'; export { default as FilmIcon } from './icons/film';
export { default as LucideFilm } from './icons/film'; export { default as LucideFilm } from './icons/film';
// FilterX aliases
export { default as FilterXIcon } from './icons/filter-x';
export { default as LucideFilterX } from './icons/filter-x';
// Filter aliases // Filter aliases
export { default as FilterIcon } from './icons/filter'; export { default as FilterIcon } from './icons/filter';
export { default as LucideFilter } from './icons/filter'; export { default as LucideFilter } from './icons/filter';
@@ -1433,6 +1477,14 @@ export { default as LucideFilter } from './icons/filter';
export { default as FingerprintIcon } from './icons/fingerprint'; export { default as FingerprintIcon } from './icons/fingerprint';
export { default as LucideFingerprint } from './icons/fingerprint'; export { default as LucideFingerprint } from './icons/fingerprint';
// FishOff aliases
export { default as FishOffIcon } from './icons/fish-off';
export { default as LucideFishOff } from './icons/fish-off';
// Fish aliases
export { default as FishIcon } from './icons/fish';
export { default as LucideFish } from './icons/fish';
// FlagOff aliases // FlagOff aliases
export { default as FlagOffIcon } from './icons/flag-off'; export { default as FlagOffIcon } from './icons/flag-off';
export { default as LucideFlagOff } from './icons/flag-off'; export { default as LucideFlagOff } from './icons/flag-off';
@@ -1597,6 +1649,14 @@ export { default as LucideFolder } from './icons/folder';
export { default as FoldersIcon } from './icons/folders'; export { default as FoldersIcon } from './icons/folders';
export { default as LucideFolders } from './icons/folders'; export { default as LucideFolders } from './icons/folders';
// Footprints aliases
export { default as FootprintsIcon } from './icons/footprints';
export { default as LucideFootprints } from './icons/footprints';
// Forklift aliases
export { default as ForkliftIcon } from './icons/forklift';
export { default as LucideForklift } from './icons/forklift';
// FormInput aliases // FormInput aliases
export { default as FormInputIcon } from './icons/form-input'; export { default as FormInputIcon } from './icons/form-input';
export { default as LucideFormInput } from './icons/form-input'; export { default as LucideFormInput } from './icons/form-input';
@@ -1737,6 +1797,10 @@ export { default as LucideGripHorizontal } from './icons/grip-horizontal';
export { default as GripVerticalIcon } from './icons/grip-vertical'; export { default as GripVerticalIcon } from './icons/grip-vertical';
export { default as LucideGripVertical } from './icons/grip-vertical'; export { default as LucideGripVertical } from './icons/grip-vertical';
// Grip aliases
export { default as GripIcon } from './icons/grip';
export { default as LucideGrip } from './icons/grip';
// Hammer aliases // Hammer aliases
export { default as HammerIcon } from './icons/hammer'; export { default as HammerIcon } from './icons/hammer';
export { default as LucideHammer } from './icons/hammer'; export { default as LucideHammer } from './icons/hammer';
@@ -1821,6 +1885,10 @@ export { default as LucideHeart } from './icons/heart';
export { default as HelpCircleIcon } from './icons/help-circle'; export { default as HelpCircleIcon } from './icons/help-circle';
export { default as LucideHelpCircle } from './icons/help-circle'; export { default as LucideHelpCircle } from './icons/help-circle';
// HelpingHand aliases
export { default as HelpingHandIcon } from './icons/helping-hand';
export { default as LucideHelpingHand } from './icons/helping-hand';
// Hexagon aliases // Hexagon aliases
export { default as HexagonIcon } from './icons/hexagon'; export { default as HexagonIcon } from './icons/hexagon';
export { default as LucideHexagon } from './icons/hexagon'; export { default as LucideHexagon } from './icons/hexagon';
@@ -1849,6 +1917,10 @@ export { default as LucideHop } from './icons/hop';
export { default as HourglassIcon } from './icons/hourglass'; export { default as HourglassIcon } from './icons/hourglass';
export { default as LucideHourglass } from './icons/hourglass'; export { default as LucideHourglass } from './icons/hourglass';
// IceCream2 aliases
export { default as IceCream2Icon } from './icons/ice-cream-2';
export { default as LucideIceCream2 } from './icons/ice-cream-2';
// IceCream aliases // IceCream aliases
export { default as IceCreamIcon } from './icons/ice-cream'; export { default as IceCreamIcon } from './icons/ice-cream';
export { default as LucideIceCream } from './icons/ice-cream'; export { default as LucideIceCream } from './icons/ice-cream';
@@ -2377,6 +2449,10 @@ export { default as LucideNetwork } from './icons/network';
export { default as NewspaperIcon } from './icons/newspaper'; export { default as NewspaperIcon } from './icons/newspaper';
export { default as LucideNewspaper } from './icons/newspaper'; export { default as LucideNewspaper } from './icons/newspaper';
// Nfc aliases
export { default as NfcIcon } from './icons/nfc';
export { default as LucideNfc } from './icons/nfc';
// NutOff aliases // NutOff aliases
export { default as NutOffIcon } from './icons/nut-off'; export { default as NutOffIcon } from './icons/nut-off';
export { default as LucideNutOff } from './icons/nut-off'; export { default as LucideNutOff } from './icons/nut-off';
@@ -2453,6 +2529,22 @@ export { default as LucidePalmtree } from './icons/palmtree';
export { default as PaperclipIcon } from './icons/paperclip'; export { default as PaperclipIcon } from './icons/paperclip';
export { default as LucidePaperclip } from './icons/paperclip'; export { default as LucidePaperclip } from './icons/paperclip';
// ParkingCircleOff aliases
export { default as ParkingCircleOffIcon } from './icons/parking-circle-off';
export { default as LucideParkingCircleOff } from './icons/parking-circle-off';
// ParkingCircle aliases
export { default as ParkingCircleIcon } from './icons/parking-circle';
export { default as LucideParkingCircle } from './icons/parking-circle';
// ParkingSquareOff aliases
export { default as ParkingSquareOffIcon } from './icons/parking-square-off';
export { default as LucideParkingSquareOff } from './icons/parking-square-off';
// ParkingSquare aliases
export { default as ParkingSquareIcon } from './icons/parking-square';
export { default as LucideParkingSquare } from './icons/parking-square';
// PartyPopper aliases // PartyPopper aliases
export { default as PartyPopperIcon } from './icons/party-popper'; export { default as PartyPopperIcon } from './icons/party-popper';
export { default as LucidePartyPopper } from './icons/party-popper'; export { default as LucidePartyPopper } from './icons/party-popper';
@@ -2513,6 +2605,14 @@ export { default as LucidePhoneOutgoing } from './icons/phone-outgoing';
export { default as PhoneIcon } from './icons/phone'; export { default as PhoneIcon } from './icons/phone';
export { default as LucidePhone } from './icons/phone'; export { default as LucidePhone } from './icons/phone';
// PictureInPicture2 aliases
export { default as PictureInPicture2Icon } from './icons/picture-in-picture-2';
export { default as LucidePictureInPicture2 } from './icons/picture-in-picture-2';
// PictureInPicture aliases
export { default as PictureInPictureIcon } from './icons/picture-in-picture';
export { default as LucidePictureInPicture } from './icons/picture-in-picture';
// PieChart aliases // PieChart aliases
export { default as PieChartIcon } from './icons/pie-chart'; export { default as PieChartIcon } from './icons/pie-chart';
export { default as LucidePieChart } from './icons/pie-chart'; export { default as LucidePieChart } from './icons/pie-chart';
@@ -2525,6 +2625,10 @@ export { default as LucidePiggyBank } from './icons/piggy-bank';
export { default as PilcrowIcon } from './icons/pilcrow'; export { default as PilcrowIcon } from './icons/pilcrow';
export { default as LucidePilcrow } from './icons/pilcrow'; export { default as LucidePilcrow } from './icons/pilcrow';
// Pill aliases
export { default as PillIcon } from './icons/pill';
export { default as LucidePill } from './icons/pill';
// PinOff aliases // PinOff aliases
export { default as PinOffIcon } from './icons/pin-off'; export { default as PinOffIcon } from './icons/pin-off';
export { default as LucidePinOff } from './icons/pin-off'; export { default as LucidePinOff } from './icons/pin-off';
@@ -2541,6 +2645,14 @@ export { default as LucidePipette } from './icons/pipette';
export { default as PizzaIcon } from './icons/pizza'; export { default as PizzaIcon } from './icons/pizza';
export { default as LucidePizza } from './icons/pizza'; export { default as LucidePizza } from './icons/pizza';
// PlaneLanding aliases
export { default as PlaneLandingIcon } from './icons/plane-landing';
export { default as LucidePlaneLanding } from './icons/plane-landing';
// PlaneTakeoff aliases
export { default as PlaneTakeoffIcon } from './icons/plane-takeoff';
export { default as LucidePlaneTakeoff } from './icons/plane-takeoff';
// Plane aliases // Plane aliases
export { default as PlaneIcon } from './icons/plane'; export { default as PlaneIcon } from './icons/plane';
export { default as LucidePlane } from './icons/plane'; export { default as LucidePlane } from './icons/plane';
@@ -2661,6 +2773,10 @@ export { default as LucideRefrigerator } from './icons/refrigerator';
export { default as RegexIcon } from './icons/regex'; export { default as RegexIcon } from './icons/regex';
export { default as LucideRegex } from './icons/regex'; export { default as LucideRegex } from './icons/regex';
// RemoveFormatting aliases
export { default as RemoveFormattingIcon } from './icons/remove-formatting';
export { default as LucideRemoveFormatting } from './icons/remove-formatting';
// Repeat1 aliases // Repeat1 aliases
export { default as Repeat1Icon } from './icons/repeat-1'; export { default as Repeat1Icon } from './icons/repeat-1';
export { default as LucideRepeat1 } from './icons/repeat-1'; export { default as LucideRepeat1 } from './icons/repeat-1';
@@ -2701,6 +2817,10 @@ export { default as LucideRotateCcw } from './icons/rotate-ccw';
export { default as RotateCwIcon } from './icons/rotate-cw'; export { default as RotateCwIcon } from './icons/rotate-cw';
export { default as LucideRotateCw } from './icons/rotate-cw'; export { default as LucideRotateCw } from './icons/rotate-cw';
// Router aliases
export { default as RouterIcon } from './icons/router';
export { default as LucideRouter } from './icons/router';
// Rss aliases // Rss aliases
export { default as RssIcon } from './icons/rss'; export { default as RssIcon } from './icons/rss';
export { default as LucideRss } from './icons/rss'; export { default as LucideRss } from './icons/rss';
@@ -2717,6 +2837,14 @@ export { default as LucideRussianRuble } from './icons/russian-ruble';
export { default as SailboatIcon } from './icons/sailboat'; export { default as SailboatIcon } from './icons/sailboat';
export { default as LucideSailboat } from './icons/sailboat'; export { default as LucideSailboat } from './icons/sailboat';
// Salad aliases
export { default as SaladIcon } from './icons/salad';
export { default as LucideSalad } from './icons/salad';
// Sandwich aliases
export { default as SandwichIcon } from './icons/sandwich';
export { default as LucideSandwich } from './icons/sandwich';
// Save aliases // Save aliases
export { default as SaveIcon } from './icons/save'; export { default as SaveIcon } from './icons/save';
export { default as LucideSave } from './icons/save'; export { default as LucideSave } from './icons/save';
@@ -2833,6 +2961,10 @@ export { default as LucideShieldOff } from './icons/shield-off';
export { default as ShieldIcon } from './icons/shield'; export { default as ShieldIcon } from './icons/shield';
export { default as LucideShield } from './icons/shield'; export { default as LucideShield } from './icons/shield';
// Ship aliases
export { default as ShipIcon } from './icons/ship';
export { default as LucideShip } from './icons/ship';
// Shirt aliases // Shirt aliases
export { default as ShirtIcon } from './icons/shirt'; export { default as ShirtIcon } from './icons/shirt';
export { default as LucideShirt } from './icons/shirt'; export { default as LucideShirt } from './icons/shirt';
@@ -2941,6 +3073,10 @@ export { default as LucideSliders } from './icons/sliders';
export { default as SmartphoneChargingIcon } from './icons/smartphone-charging'; export { default as SmartphoneChargingIcon } from './icons/smartphone-charging';
export { default as LucideSmartphoneCharging } from './icons/smartphone-charging'; export { default as LucideSmartphoneCharging } from './icons/smartphone-charging';
// SmartphoneNfc aliases
export { default as SmartphoneNfcIcon } from './icons/smartphone-nfc';
export { default as LucideSmartphoneNfc } from './icons/smartphone-nfc';
// Smartphone aliases // Smartphone aliases
export { default as SmartphoneIcon } from './icons/smartphone'; export { default as SmartphoneIcon } from './icons/smartphone';
export { default as LucideSmartphone } from './icons/smartphone'; export { default as LucideSmartphone } from './icons/smartphone';
@@ -2969,6 +3105,10 @@ export { default as LucideSortAsc } from './icons/sort-asc';
export { default as SortDescIcon } from './icons/sort-desc'; export { default as SortDescIcon } from './icons/sort-desc';
export { default as LucideSortDesc } from './icons/sort-desc'; export { default as LucideSortDesc } from './icons/sort-desc';
// Soup aliases
export { default as SoupIcon } from './icons/soup';
export { default as LucideSoup } from './icons/soup';
// Speaker aliases // Speaker aliases
export { default as SpeakerIcon } from './icons/speaker'; export { default as SpeakerIcon } from './icons/speaker';
export { default as LucideSpeaker } from './icons/speaker'; export { default as LucideSpeaker } from './icons/speaker';
@@ -2977,6 +3117,14 @@ export { default as LucideSpeaker } from './icons/speaker';
export { default as SplineIcon } from './icons/spline'; export { default as SplineIcon } from './icons/spline';
export { default as LucideSpline } from './icons/spline'; export { default as LucideSpline } from './icons/spline';
// SplitSquareHorizontal aliases
export { default as SplitSquareHorizontalIcon } from './icons/split-square-horizontal';
export { default as LucideSplitSquareHorizontal } from './icons/split-square-horizontal';
// SplitSquareVertical aliases
export { default as SplitSquareVerticalIcon } from './icons/split-square-vertical';
export { default as LucideSplitSquareVertical } from './icons/split-square-vertical';
// Sprout aliases // Sprout aliases
export { default as SproutIcon } from './icons/sprout'; export { default as SproutIcon } from './icons/sprout';
export { default as LucideSprout } from './icons/sprout'; export { default as LucideSprout } from './icons/sprout';
@@ -2985,6 +3133,10 @@ export { default as LucideSprout } from './icons/sprout';
export { default as SquareIcon } from './icons/square'; export { default as SquareIcon } from './icons/square';
export { default as LucideSquare } from './icons/square'; export { default as LucideSquare } from './icons/square';
// Stamp aliases
export { default as StampIcon } from './icons/stamp';
export { default as LucideStamp } from './icons/stamp';
// StarHalf aliases // StarHalf aliases
export { default as StarHalfIcon } from './icons/star-half'; export { default as StarHalfIcon } from './icons/star-half';
export { default as LucideStarHalf } from './icons/star-half'; export { default as LucideStarHalf } from './icons/star-half';
@@ -3097,6 +3249,10 @@ export { default as LucideTable } from './icons/table';
export { default as TabletIcon } from './icons/tablet'; export { default as TabletIcon } from './icons/tablet';
export { default as LucideTablet } from './icons/tablet'; export { default as LucideTablet } from './icons/tablet';
// Tablets aliases
export { default as TabletsIcon } from './icons/tablets';
export { default as LucideTablets } from './icons/tablets';
// Tag aliases // Tag aliases
export { default as TagIcon } from './icons/tag'; export { default as TagIcon } from './icons/tag';
export { default as LucideTag } from './icons/tag'; export { default as LucideTag } from './icons/tag';
@@ -3177,6 +3333,10 @@ export { default as LucideToggleRight } from './icons/toggle-right';
export { default as TornadoIcon } from './icons/tornado'; export { default as TornadoIcon } from './icons/tornado';
export { default as LucideTornado } from './icons/tornado'; export { default as LucideTornado } from './icons/tornado';
// TowerControl aliases
export { default as TowerControlIcon } from './icons/tower-control';
export { default as LucideTowerControl } from './icons/tower-control';
// ToyBrick aliases // ToyBrick aliases
export { default as ToyBrickIcon } from './icons/toy-brick'; export { default as ToyBrickIcon } from './icons/toy-brick';
export { default as LucideToyBrick } from './icons/toy-brick'; export { default as LucideToyBrick } from './icons/toy-brick';
@@ -3325,6 +3485,10 @@ export { default as LucideUtensilsCrossed } from './icons/utensils-crossed';
export { default as UtensilsIcon } from './icons/utensils'; export { default as UtensilsIcon } from './icons/utensils';
export { default as LucideUtensils } from './icons/utensils'; export { default as LucideUtensils } from './icons/utensils';
// UtilityPole aliases
export { default as UtilityPoleIcon } from './icons/utility-pole';
export { default as LucideUtilityPole } from './icons/utility-pole';
// Vegan aliases // Vegan aliases
export { default as VeganIcon } from './icons/vegan'; export { default as VeganIcon } from './icons/vegan';
export { default as LucideVegan } from './icons/vegan'; export { default as LucideVegan } from './icons/vegan';
@@ -3377,6 +3541,10 @@ export { default as LucideVolumeX } from './icons/volume-x';
export { default as VolumeIcon } from './icons/volume'; export { default as VolumeIcon } from './icons/volume';
export { default as LucideVolume } from './icons/volume'; export { default as LucideVolume } from './icons/volume';
// Vote aliases
export { default as VoteIcon } from './icons/vote';
export { default as LucideVote } from './icons/vote';
// Wallet aliases // Wallet aliases
export { default as WalletIcon } from './icons/wallet'; export { default as WalletIcon } from './icons/wallet';
export { default as LucideWallet } from './icons/wallet'; export { default as LucideWallet } from './icons/wallet';

View File

@@ -1,7 +1,7 @@
{ {
"name": "lucide-svelte", "name": "lucide-svelte",
"description": "A Lucide icon library package for Svelte applications", "description": "A Lucide icon library package for Svelte applications",
"version": "0.124.0", "version": "0.131.0",
"license": "ISC", "license": "ISC",
"homepage": "https://lucide.dev", "homepage": "https://lucide.dev",
"bugs": "https://github.com/lucide-icons/lucide/issues", "bugs": "https://github.com/lucide-icons/lucide/issues",
@@ -29,7 +29,7 @@
"build:types": "node ./scripts/buildTypes.mjs", "build:types": "node ./scripts/buildTypes.mjs",
"build:bundles": "rollup -c ./rollup.config.mjs", "build:bundles": "rollup -c ./rollup.config.mjs",
"build:strip": "svelte-strip strip src/ dist/svelte", "build:strip": "svelte-strip strip src/ dist/svelte",
"test": "vitest", "test": "vitest run",
"version": "pnpm version --git-tag-version=false" "version": "pnpm version --git-tag-version=false"
}, },
"devDependencies": { "devDependencies": {

View File

@@ -10,17 +10,6 @@ const outputFileName = 'lucide-svelte';
const outputDir = 'dist'; const outputDir = 'dist';
const inputs = ['./src/lucide-svelte.ts']; const inputs = ['./src/lucide-svelte.ts'];
const bundles = [ const bundles = [
// Not sure if this one is needed for Svelte
// {
// format: 'cjs',
// inputs,
// outputDir,
// },
{
format: 'es',
inputs,
outputDir,
},
{ {
format: 'esm', format: 'esm',
inputs, inputs,

View File

@@ -1,6 +1,6 @@
{ {
"name": "lucide-vue-next", "name": "lucide-vue-next",
"version": "0.124.0", "version": "0.131.0",
"author": "Eric Fennis", "author": "Eric Fennis",
"description": "A Lucide icon library package for Vue 3 applications", "description": "A Lucide icon library package for Vue 3 applications",
"license": "ISC", "license": "ISC",
@@ -30,7 +30,7 @@
"build:icons": "build-icons --output=./src --templateSrc=./scripts/exportTemplate.mjs --renderUniqueKey --withAliases --aliasesFileExtension=.ts --iconFileExtension=.ts --exportFileName=index.ts", "build:icons": "build-icons --output=./src --templateSrc=./scripts/exportTemplate.mjs --renderUniqueKey --withAliases --aliasesFileExtension=.ts --iconFileExtension=.ts --exportFileName=index.ts",
"build:types": "node ./scripts/buildTypes.mjs", "build:types": "node ./scripts/buildTypes.mjs",
"build:bundles": "rollup -c ./rollup.config.mjs", "build:bundles": "rollup -c ./rollup.config.mjs",
"test": "vitest", "test": "vitest run",
"version": "pnpm version --git-tag-version=false" "version": "pnpm version --git-tag-version=false"
}, },
"devDependencies": { "devDependencies": {

View File

@@ -21,28 +21,25 @@ const bundles = [
format: 'cjs', format: 'cjs',
inputs, inputs,
outputDir, outputDir,
}, aliasesSupport: true
{
format: 'es',
inputs,
outputDir,
}, },
{ {
format: 'esm', format: 'esm',
inputs, inputs,
outputDir, outputDir,
preserveModules: true, preserveModules: true,
aliasesSupport: true
}, },
]; ];
const configs = bundles const configs = bundles
.map(({ inputs, outputDir, format, minify, preserveModules }) => .map(({ inputs, outputDir, format, minify, preserveModules, aliasesSupport }) =>
inputs.map(input => ({ inputs.map(input => ({
input, input,
plugins: [ plugins: [
// This for aliases, only for esm // This for aliases, only for esm
...( ...(
format !== 'esm' ? [ !aliasesSupport ? [
replace({ replace({
"export * from './aliases';": '', "export * from './aliases';": '',
"export * as icons from './icons';": '', "export * as icons from './icons';": '',

View File

@@ -1,6 +1,6 @@
{ {
"name": "lucide-vue", "name": "lucide-vue",
"version": "0.124.0", "version": "0.131.0",
"author": "Eric Fennis", "author": "Eric Fennis",
"description": "A Lucide icon library package for Vue 2 applications", "description": "A Lucide icon library package for Vue 2 applications",
"license": "ISC", "license": "ISC",
@@ -28,7 +28,7 @@
"clean": "rm -rf dist && rm -rf stats && rm -rf ./src/icons/*.js", "clean": "rm -rf dist && rm -rf stats && rm -rf ./src/icons/*.js",
"build:icons": "build-icons --output=./src --templateSrc=./scripts/exportTemplate.mjs --renderUniqueKey --withAliases --aliasesFileExtension=.ts --iconFileExtention=.ts --exportFileName=index.ts", "build:icons": "build-icons --output=./src --templateSrc=./scripts/exportTemplate.mjs --renderUniqueKey --withAliases --aliasesFileExtension=.ts --iconFileExtention=.ts --exportFileName=index.ts",
"build:bundles": "rollup -c ./rollup.config.mjs", "build:bundles": "rollup -c ./rollup.config.mjs",
"test": "vitest", "test": "vitest run",
"version": "pnpm version --git-tag-version=false" "version": "pnpm version --git-tag-version=false"
}, },
"devDependencies": { "devDependencies": {

View File

@@ -21,28 +21,25 @@ const bundles = [
format: 'cjs', format: 'cjs',
inputs, inputs,
outputDir, outputDir,
}, aliasesSupport: true
{
format: 'es',
inputs,
outputDir,
}, },
{ {
format: 'esm', format: 'esm',
inputs, inputs,
outputDir, outputDir,
preserveModules: true, preserveModules: true,
aliasesSupport: true
}, },
]; ];
const configs = bundles const configs = bundles
.map(({ inputs, outputDir, format, minify, preserveModules }) => .map(({ inputs, outputDir, format, minify, preserveModules, aliasesSupport }) =>
inputs.map(input => ({ inputs.map(input => ({
input, input,
plugins: [ plugins: [
// This for aliases, only for esm // This for aliases, only for esm
...( ...(
format !== 'esm' ? [ !aliasesSupport ? [
replace({ replace({
"export * from './aliases';": '', "export * from './aliases';": '',
"export * as icons from './icons';": '', "export * as icons from './icons';": '',

View File

@@ -1,7 +1,7 @@
{ {
"name": "lucide", "name": "lucide",
"description": "A Lucide icon library package for web and javascript applications.", "description": "A Lucide icon library package for web and javascript applications.",
"version": "0.124.0", "version": "0.131.0",
"license": "ISC", "license": "ISC",
"homepage": "https://lucide.dev", "homepage": "https://lucide.dev",
"bugs": "https://github.com/lucide-icons/lucide/issues", "bugs": "https://github.com/lucide-icons/lucide/issues",
@@ -28,7 +28,7 @@
"build:icons": "build-icons --output=./src --templateSrc=./scripts/exportTemplate.mjs --iconFileExtension=.ts", "build:icons": "build-icons --output=./src --templateSrc=./scripts/exportTemplate.mjs --iconFileExtension=.ts",
"build:types": "node ./scripts/buildTypes.mjs", "build:types": "node ./scripts/buildTypes.mjs",
"build:bundles": "rollup -c rollup.config.mjs", "build:bundles": "rollup -c rollup.config.mjs",
"test": "vitest", "test": "vitest run",
"version": "pnpm version --git-tag-version=false" "version": "pnpm version --git-tag-version=false"
}, },
"devDependencies": { "devDependencies": {

View File

@@ -23,11 +23,6 @@ const bundles = [
inputs, inputs,
outputDir, outputDir,
}, },
{
format: 'es',
inputs,
outputDir,
},
{ {
format: 'esm', format: 'esm',
inputs, inputs,
@@ -75,7 +70,7 @@ const typesFileConfig = {
output: [ output: [
{ {
file: `${outputDir}/${outputFileName}.d.ts`, file: `${outputDir}/${outputFileName}.d.ts`,
format: 'es', format: 'esm',
}, },
], ],
plugins: [ plugins: [

1891
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

View File

@@ -24,6 +24,7 @@
"@next/mdx": "^11.0.0", "@next/mdx": "^11.0.0",
"@svgr/webpack": "^6.3.1", "@svgr/webpack": "^6.3.1",
"downloadjs": "^1.4.7", "downloadjs": "^1.4.7",
"element-to-path": "^1.2.1",
"framer-motion": "^4", "framer-motion": "^4",
"fuse.js": "^6.5.3", "fuse.js": "^6.5.3",
"gray-matter": "^4.0.3", "gray-matter": "^4.0.3",
@@ -38,7 +39,8 @@
"react-color": "^2.19.3", "react-color": "^2.19.3",
"react-dom": "17.0.2", "react-dom": "17.0.2",
"react-svg-loader": "^3.0.3", "react-svg-loader": "^3.0.3",
"svgson": "^5.2.1" "svgson": "^5.2.1",
"svg-pathdata": "^6.0.3"
}, },
"devDependencies": { "devDependencies": {
"@next/eslint-plugin-next": "^12.2.5", "@next/eslint-plugin-next": "^12.2.5",

View File

@@ -5,7 +5,7 @@ interface IconWrapperProps extends SVGProps<SVGSVGElement> {
} }
export const IconWrapper = forwardRef<SVGSVGElement, IconWrapperProps>((props, ref) => { export const IconWrapper = forwardRef<SVGSVGElement, IconWrapperProps>((props, ref) => {
const defaultAttrs : SVGProps<SVGSVGElement>= { const defaultAttrs: SVGProps<SVGSVGElement> = {
xmlns: 'http://www.w3.org/2000/svg', xmlns: 'http://www.w3.org/2000/svg',
width: '24px', width: '24px',
height: '24px', height: '24px',

View File

@@ -0,0 +1,225 @@
import React from 'react';
import { PathProps, Path } from './types';
import { getPaths, assert } from './utils';
const Grid = ({
radius,
fill,
...props
}: {
strokeWidth: number;
radius: number;
} & PathProps<'stroke', 'strokeWidth'>) => (
<g className="svg-preview-grid-group" strokeLinecap="butt" {...props}>
<rect
width={24 - props.strokeWidth}
height={24 - props.strokeWidth}
x={props.strokeWidth / 2}
y={props.strokeWidth / 2}
rx={radius}
fill={fill}
/>
<path
d={
props.d ||
new Array(Math.floor(24 - 1))
.fill(null)
.flatMap((_, i) => [
`M${props.strokeWidth} ${i + 1}h${24 - props.strokeWidth * 2}`,
`M${i + 1} ${props.strokeWidth}v${24 - props.strokeWidth * 2}`,
])
.join('')
}
/>
</g>
);
const Shadow = ({
radius,
paths,
...props
}: {
radius: number;
paths: Path[];
} & PathProps<'stroke' | 'strokeWidth' | 'strokeOpacity', 'd'>) => {
const groupedPaths = Object.entries(
paths.reduce((groups, val) => {
const key = val.c.id;
groups[key] = [...(groups[key] || []), val];
return groups;
}, {} as Record<number, Path[]>)
);
return (
<>
<g className="svg-preview-shadow-mask-group" {...props}>
{groupedPaths.map(([id, paths]) => (
<mask
id={`svg-preview-shadow-mask-${id}`}
maskUnits="userSpaceOnUse"
strokeOpacity="1"
strokeWidth={props.strokeWidth}
stroke="#000"
>
<rect x={0} y={0} width={24} height={24} fill="#fff" stroke="none" rx={radius} />
<path
d={paths
.flatMap(({ prev, next }) => [
`M${prev.x} ${prev.y}h.01`,
`M${next.x} ${next.y}h.01`,
])
.filter((val, idx, arr) => arr.indexOf(val) === idx)
.join('')}
/>
</mask>
))}
</g>
<g className="svg-preview-shadow-group" {...props}>
{paths.map(({ d, c: { id } }, i) => (
<path key={i} mask={`url(#svg-preview-shadow-mask-${id})`} d={d} />
))}
<path
d={paths
.flatMap(({ prev, next }) => [`M${prev.x} ${prev.y}h.01`, `M${next.x} ${next.y}h.01`])
.filter((val, idx, arr) => arr.indexOf(val) === idx)
.join('')}
/>
</g>
</>
);
};
const ColoredPath = ({
colors,
paths,
...props
}: { paths: Path[]; colors: string[] } & PathProps<never, 'd' | 'stroke'>) => (
<g className="svg-preview-colored-path-group" {...props}>
{paths.map(({ d, c }, i) => (
<path key={i} d={d} stroke={colors[(c.name === 'path' ? i : c.id) % colors.length]} />
))}
</g>
);
const ControlPath = ({
paths,
radius,
pointSize,
...props
}: { pointSize: number; paths: Path[]; radius: number } & PathProps<
'stroke' | 'strokeWidth',
'd'
>) => {
const controlPaths = paths.map((path, i) => {
const element = paths.filter((p) => p.c.id === path.c.id);
const lastElement = element.at(-1)?.next;
assert(lastElement);
const isClosed = element[0].prev.x === lastElement.x && element[0].prev.y === lastElement.y;
const showMarker = !['rect', 'circle', 'ellipse'].includes(path.c.name);
return {
...path,
showMarker,
startMarker: showMarker && path.isStart && !isClosed,
endMarker: showMarker && paths[i + 1]?.isStart !== false && !isClosed,
};
});
return (
<>
<g
className="svg-preview-control-path-marker-mask-group"
strokeWidth={pointSize}
stroke="#000"
>
{controlPaths.map(({ prev, next, showMarker }, i) => {
return (
showMarker && (
<mask
id={`svg-preview-control-path-marker-mask-${i}`}
key={i}
maskUnits="userSpaceOnUse"
>
<rect x="0" y="0" width="24" height="24" fill="#fff" stroke="none" rx={radius} />
<path d={`M${prev.x} ${prev.y}h.01`} />
<path d={`M${next.x} ${next.y}h.01`} />
</mask>
)
);
})}
</g>
<g className="svg-preview-control-path-group" {...props}>
{controlPaths.map(({ d, showMarker }, i) => (
<path
key={i}
mask={showMarker ? `url(#svg-preview-control-path-marker-mask-${i})` : undefined}
d={d}
/>
))}
</g>
<g className="svg-preview-control-path-marker-group" {...props}>
<path
d={controlPaths
.flatMap(({ prev, next, showMarker }) =>
showMarker ? [`M${prev.x} ${prev.y}h.01`, `M${next.x} ${next.y}h.01`] : []
)
.join('')}
/>
{controlPaths.map(({ d, prev, next, startMarker, endMarker }, i) => (
<React.Fragment key={i}>
{startMarker && <circle cx={prev.x} cy={prev.y} r={pointSize / 2} />}
{endMarker && <circle cx={next.x} cy={next.y} r={pointSize / 2} />}
</React.Fragment>
))}
</g>
</>
);
};
const SvgPreview = React.forwardRef<SVGSVGElement, { src: string; showGrid?: boolean }>(
({ src, showGrid = false }, ref) => {
const paths = getPaths(src);
const darkModeCss = `@media screen and (prefers-color-scheme: dark) {
.svg-preview-grid-group,
.svg-preview-shadow-mask-group,
.svg-preview-shadow-group {
stroke: #fff;
}
}`;
return (
<svg
ref={ref}
xmlns="http://www.w3.org/2000/svg"
width={24}
height={24}
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
strokeWidth={2}
strokeLinecap="round"
strokeLinejoin="round"
>
<style>{darkModeCss}</style>
{showGrid && <Grid strokeWidth={0.1} stroke="#777" strokeOpacity={0.3} radius={1} />}
<Shadow paths={paths} strokeWidth={4} stroke="#777" radius={1} strokeOpacity={0.15} />
<ColoredPath
paths={paths}
colors={[
'#1982c4',
'#4267AC',
'#6a4c93',
'#B55379',
'#FF595E',
'#FF7655',
'#ff924c',
'#FFAE43',
'#ffca3a',
'#C5CA30',
'#8ac926',
'#52A675',
]}
/>
<ControlPath radius={1} paths={paths} pointSize={1} stroke="#fff" strokeWidth={0.125} />
</svg>
);
}
);
export default SvgPreview;

View File

@@ -0,0 +1,21 @@
import { SVGProps } from 'react';
import { getCommands } from './utils';
export type Point = { x: number; y: number };
export type Path = {
d: string;
prev: Point;
next: Point;
isStart: boolean;
c: ReturnType<typeof getCommands>[number];
};
export type PathProps<
RequiredProps extends keyof SVGProps<SVGPathElement | SVGRectElement | SVGCircleElement>,
NeverProps extends keyof SVGProps<SVGPathElement | SVGRectElement | SVGCircleElement>
> = Required<Pick<React.SVGProps<SVGElement & SVGRectElement & SVGCircleElement>, RequiredProps>> &
Omit<
React.SVGProps<SVGPathElement & SVGRectElement & SVGCircleElement>,
RequiredProps & NeverProps
>;

View File

@@ -0,0 +1,186 @@
import { INode, parseSync } from 'svgson';
import toPath from 'element-to-path';
import { SVGPathData, encodeSVGPath } from 'svg-pathdata';
import { Path, Point } from './types';
function assertNever(x: never): never {
throw new Error('Unknown type: ' + x['type']);
}
export function assert(value: unknown): asserts value {
if (value === undefined) {
throw new Error('value must be defined');
}
}
const extractPaths = (node: INode): { d: string; name: typeof node.name }[] => {
if (/(rect|circle|ellipse|polygon|polyline|line|path)/.test(node.name)) {
return [{ d: toPath(node), name: node.name }];
} else if (node.children && Array.isArray(node.children)) {
return node.children.flatMap(extractPaths);
}
return [];
};
export const getCommands = (src: string) =>
extractPaths(parseSync(src)).flatMap(({ d, name }, idx) =>
new SVGPathData(d).toAbs().commands.map((c) => ({ ...c, id: idx, name }))
);
export const getPaths = (src: string) => {
const commands = getCommands(src);
const paths: Path[] = [];
let prev: Point | undefined = undefined;
let start: Point | undefined = undefined;
const addPath = (c: (typeof commands)[number], next: Point, d?: string) => {
assert(prev);
paths.push({
c,
d: d || `M${prev.x} ${prev.y}L${next.x} ${next.y}`,
prev,
next,
isStart: start === prev,
});
prev = next;
};
let prevCP: Point | undefined = undefined;
for (let i = 0; i < commands.length; i++) {
const previousCommand = commands[i - 1];
const c = commands[i];
switch (c.type) {
case SVGPathData.MOVE_TO: {
prev = c;
start = c;
break;
}
case SVGPathData.LINE_TO: {
assert(prev);
addPath(c, c);
break;
}
case SVGPathData.HORIZ_LINE_TO: {
assert(prev);
addPath(c, { x: c.x, y: prev.y });
break;
}
case SVGPathData.VERT_LINE_TO: {
assert(prev);
addPath(c, { x: prev.x, y: c.y });
break;
}
case SVGPathData.CLOSE_PATH: {
assert(prev);
assert(start);
addPath(c, start);
start = undefined;
break;
}
case SVGPathData.CURVE_TO: {
assert(prev);
addPath(c, c, `M ${prev.x},${prev.y} ${encodeSVGPath(c)}`);
break;
}
case SVGPathData.SMOOTH_CURVE_TO: {
assert(prev);
assert(previousCommand);
const reflectedCp1 = {
x:
previousCommand &&
(previousCommand.type === SVGPathData.SMOOTH_CURVE_TO ||
previousCommand.type === SVGPathData.CURVE_TO)
? previousCommand.relative
? previousCommand.x2 - previousCommand.x
: previousCommand.x2 - prev.x
: 0,
y:
previousCommand &&
(previousCommand.type === SVGPathData.SMOOTH_CURVE_TO ||
previousCommand.type === SVGPathData.CURVE_TO)
? previousCommand.relative
? previousCommand.y2 - previousCommand.y
: previousCommand.y2 - prev.y
: 0,
};
addPath(
c,
c,
`M ${prev.x},${prev.y} ${encodeSVGPath({
type: SVGPathData.CURVE_TO,
relative: false,
x: c.x,
y: c.y,
x1: prev.x - reflectedCp1.x,
y1: prev.y - reflectedCp1.y,
x2: c.x2,
y2: c.y2,
})}`
);
break;
}
case SVGPathData.QUAD_TO: {
assert(prev);
addPath(c, c, `M ${prev.x},${prev.y} ${encodeSVGPath(c)}`);
break;
}
case SVGPathData.SMOOTH_QUAD_TO: {
assert(prev);
const backTrackCP = (
index: number,
currentPoint: { x: number; y: number }
): { x: number; y: number } => {
const previousCommand = commands[index - 1];
if (!previousCommand) {
return currentPoint;
}
if (previousCommand.type === SVGPathData.QUAD_TO) {
return {
x: previousCommand.relative
? currentPoint.x - (previousCommand.x1 - previousCommand.x)
: currentPoint.x - (previousCommand.x1 - currentPoint.x),
y: previousCommand.relative
? currentPoint.y - (previousCommand.y1 - previousCommand.y)
: currentPoint.y - (previousCommand.y1 - currentPoint.y),
};
}
if (previousCommand.type === SVGPathData.SMOOTH_QUAD_TO) {
if (!prevCP) {
return currentPoint;
}
return {
x: currentPoint.x - (prevCP.x - currentPoint.x),
y: currentPoint.y - (prevCP.y - currentPoint.y),
};
}
return currentPoint;
};
prevCP = backTrackCP(i, prev);
addPath(
c,
c,
`M ${prev.x},${prev.y} ${encodeSVGPath({
type: SVGPathData.QUAD_TO,
relative: false,
x: c.x,
y: c.y,
x1: prevCP.x,
y1: prevCP.y,
})}`
);
break;
}
case SVGPathData.ARC: {
assert(prev);
addPath(
c,
c,
`M ${prev.x},${prev.y} A ${c.rX} ${c.rY} ${c.xRot} ${c.lArcFlag} ${c.sweepFlag} ${c.x} ${c.y}`
);
break;
}
default: {
assertNever(c);
}
}
}
return paths;
};

View File

@@ -0,0 +1,19 @@
import SvgPreview from '../../../components/SvgPreview';
export default async function handler(req, res) {
// ReactDOMServer needs to be imported dynamically
// https://github.com/vercel/next.js/issues/43810
const ReactDOMServer = (await import('react-dom/server')).default;
const url = req.url.split('/').at(-1);
const data = url.slice(0, -4);
const src = Buffer.from(data, 'base64').toString('utf8');
const svg = Buffer.from(
ReactDOMServer.renderToString(<SvgPreview src={src} showGrid />)
);
res.setHeader('Cache-Control', 'public,max-age=31536000');
res.setHeader('Content-Type', 'image/svg+xml');
res.status(200).end(svg);
}