mirror of
https://github.com/lucide-icons/lucide.git
synced 2025-12-19 13:59:21 +01:00
Compare commits
9 Commits
angular-pa
...
package/ic
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d152818621 | ||
|
|
abff584694 | ||
|
|
5d8110882d | ||
|
|
2ea256381c | ||
|
|
b88bcae614 | ||
|
|
1bbcaf8c1c | ||
|
|
68ea9b2736 | ||
|
|
620b478a2e | ||
|
|
6c3bd53c35 |
1
.github/ISSUE_TEMPLATE/02_bug_report.yml
vendored
1
.github/ISSUE_TEMPLATE/02_bug_report.yml
vendored
@@ -23,6 +23,7 @@ body:
|
|||||||
- label: lucide-vue
|
- label: lucide-vue
|
||||||
- label: lucide-vue-next
|
- label: lucide-vue-next
|
||||||
- label: lucide-astro
|
- label: lucide-astro
|
||||||
|
- label: '@lucide/icons'
|
||||||
- label: Figma plugin
|
- label: Figma plugin
|
||||||
- label: source/main
|
- label: source/main
|
||||||
- label: other/not relevant
|
- label: other/not relevant
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ body:
|
|||||||
- label: lucide-vue
|
- label: lucide-vue
|
||||||
- label: lucide-vue-next
|
- label: lucide-vue-next
|
||||||
- label: lucide-astro
|
- label: lucide-astro
|
||||||
|
- label: '@lucide/icons'
|
||||||
- label: Figma plugin
|
- label: Figma plugin
|
||||||
- label: all JS packages
|
- label: all JS packages
|
||||||
- label: site
|
- label: site
|
||||||
|
|||||||
6
.github/labeler.yml
vendored
6
.github/labeler.yml
vendored
@@ -85,6 +85,12 @@
|
|||||||
- any-glob-to-any-file:
|
- any-glob-to-any-file:
|
||||||
- 'packages/astro/*'
|
- 'packages/astro/*'
|
||||||
|
|
||||||
|
# For changes in the @lucide/icons package
|
||||||
|
❇️ lucide-icons:
|
||||||
|
- changed-files:
|
||||||
|
- any-glob-to-any-file:
|
||||||
|
- 'packages/lucide-icons/*'
|
||||||
|
|
||||||
# For changes in the lucide static package
|
# For changes in the lucide static package
|
||||||
🪨 static package:
|
🪨 static package:
|
||||||
- changed-files:
|
- changed-files:
|
||||||
|
|||||||
43
.github/workflows/icons.yml
vendored
Normal file
43
.github/workflows/icons.yml
vendored
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
name: Lucide Icons Checks
|
||||||
|
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
paths:
|
||||||
|
- packages/icons/**
|
||||||
|
- packages/shared/**
|
||||||
|
- tools/build-icons/**
|
||||||
|
- tools/rollup-plugins/**
|
||||||
|
- pnpm-lock.yaml
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v6
|
||||||
|
- uses: pnpm/action-setup@v4
|
||||||
|
- uses: actions/setup-node@v6
|
||||||
|
with:
|
||||||
|
cache: 'pnpm'
|
||||||
|
node-version-file: 'package.json'
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
run: pnpm install --frozen-lockfile
|
||||||
|
|
||||||
|
- name: Build
|
||||||
|
run: pnpm --filter @lucide/icons build
|
||||||
|
|
||||||
|
test:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v6
|
||||||
|
- uses: pnpm/action-setup@v4
|
||||||
|
- uses: actions/setup-node@v6
|
||||||
|
with:
|
||||||
|
cache: 'pnpm'
|
||||||
|
node-version-file: 'package.json'
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
run: pnpm install --frozen-lockfile
|
||||||
|
|
||||||
|
- name: Test
|
||||||
|
run: pnpm --filter @lucide/icons test
|
||||||
1
.github/workflows/release.yml
vendored
1
.github/workflows/release.yml
vendored
@@ -60,6 +60,7 @@ jobs:
|
|||||||
'lucide-svelte',
|
'lucide-svelte',
|
||||||
'@lucide/astro',
|
'@lucide/astro',
|
||||||
'@lucide/svelte',
|
'@lucide/svelte',
|
||||||
|
'@lucide/icons',
|
||||||
]
|
]
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v6
|
- uses: actions/checkout@v6
|
||||||
|
|||||||
@@ -31,8 +31,26 @@
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"lucide-vue-next": {
|
"@lucide/icons": {
|
||||||
|
"docsAlias": "lucide-icons",
|
||||||
|
"packageDirname": "lucide-icons",
|
||||||
"order": 2,
|
"order": 2,
|
||||||
|
"icon": "ts",
|
||||||
|
"shields": [
|
||||||
|
{
|
||||||
|
"alt": "npm",
|
||||||
|
"src": "https://img.shields.io/npm/v/@lucide/icons",
|
||||||
|
"href": "https://www.npmjs.com/package/@lucide/icons"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"alt": "npm",
|
||||||
|
"src": "https://img.shields.io/npm/dw/@lucide/icons",
|
||||||
|
"href": "https://www.npmjs.com/package/@lucide/icons"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"lucide-vue-next": {
|
||||||
|
"order": 3,
|
||||||
"icon": "vue-next",
|
"icon": "vue-next",
|
||||||
"shields": [
|
"shields": [
|
||||||
{
|
{
|
||||||
@@ -48,7 +66,7 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"lucide-svelte": {
|
"lucide-svelte": {
|
||||||
"order": 3,
|
"order": 4,
|
||||||
"icon": "svelte",
|
"icon": "svelte",
|
||||||
"shields": [
|
"shields": [
|
||||||
{
|
{
|
||||||
@@ -64,7 +82,7 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"lucide-solid": {
|
"lucide-solid": {
|
||||||
"order": 4,
|
"order": 5,
|
||||||
"icon": "solid",
|
"icon": "solid",
|
||||||
"shields": [
|
"shields": [
|
||||||
{
|
{
|
||||||
@@ -80,7 +98,7 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"lucide-react-native": {
|
"lucide-react-native": {
|
||||||
"order": 5,
|
"order": 6,
|
||||||
"icon": "react-native",
|
"icon": "react-native",
|
||||||
"shields": [
|
"shields": [
|
||||||
{
|
{
|
||||||
@@ -96,7 +114,7 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"lucide-angular": {
|
"lucide-angular": {
|
||||||
"order": 6,
|
"order": 7,
|
||||||
"icon": "angular",
|
"icon": "angular",
|
||||||
"shields": [
|
"shields": [
|
||||||
{
|
{
|
||||||
@@ -112,7 +130,7 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"lucide-preact": {
|
"lucide-preact": {
|
||||||
"order": 7,
|
"order": 8,
|
||||||
"icon": "preact",
|
"icon": "preact",
|
||||||
"shields": [
|
"shields": [
|
||||||
{
|
{
|
||||||
@@ -130,7 +148,7 @@
|
|||||||
"@lucide/astro": {
|
"@lucide/astro": {
|
||||||
"docsAlias": "lucide-astro",
|
"docsAlias": "lucide-astro",
|
||||||
"packageDirname": "astro",
|
"packageDirname": "astro",
|
||||||
"order": 8,
|
"order": 9,
|
||||||
"icon": "astro",
|
"icon": "astro",
|
||||||
"iconDark": "astro-dark",
|
"iconDark": "astro-dark",
|
||||||
"shields": [
|
"shields": [
|
||||||
@@ -147,7 +165,7 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"lucide-static": {
|
"lucide-static": {
|
||||||
"order": 9,
|
"order": 10,
|
||||||
"icon": "svg",
|
"icon": "svg",
|
||||||
"shields": [
|
"shields": [
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -79,6 +79,16 @@ declare module "lucide-react-native" {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
```ts [@lucide-icons]
|
||||||
|
declare module "@lucide/icons" {
|
||||||
|
// Prefixed import names
|
||||||
|
export * from "@lucide/icons/dist/lucide-icons.prefixed";
|
||||||
|
// or
|
||||||
|
// Suffixed import names
|
||||||
|
export * from "@lucide/icons/dist/lucide-icons.suffixed";
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
:::
|
:::
|
||||||
|
|
||||||
Place this in your project root or in a folder where your tsconfig.json is located, or locate it in your defined type directory.
|
Place this in your project root or in a folder where your tsconfig.json is located, or locate it in your defined type directory.
|
||||||
|
|||||||
83
docs/guide/packages/lucide-icons.md
Normal file
83
docs/guide/packages/lucide-icons.md
Normal file
@@ -0,0 +1,83 @@
|
|||||||
|
# Lucide Icons
|
||||||
|
|
||||||
|
This is a helper library that exports icon data in a tree-shakable, dynamically importable way, but provides no real rendering logic on its own.
|
||||||
|
|
||||||
|
Some of our packages, notably [
|
||||||
|
`@lucide/angular`](http://npmjs.com/package/@lucide/angular) can leverage this functionality to allow dynamically importing icons, and utilising tree-shaking when using static imports. You can also use this package to implement a third party package for a framework we do not yet support.
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
::: code-group
|
||||||
|
|
||||||
|
```sh [pnpm]
|
||||||
|
pnpm install @lucide/icons
|
||||||
|
```
|
||||||
|
|
||||||
|
```sh [yarn]
|
||||||
|
yarn add @lucide/icons
|
||||||
|
```
|
||||||
|
|
||||||
|
```sh [npm]
|
||||||
|
npm install @lucide/icons
|
||||||
|
```
|
||||||
|
|
||||||
|
```sh [bun]
|
||||||
|
bun add @lucide/icons
|
||||||
|
```
|
||||||
|
|
||||||
|
:::
|
||||||
|
|
||||||
|
## Icon data format
|
||||||
|
|
||||||
|
Each icon is described by the following interface:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
export type LucideIconData = {
|
||||||
|
name: string;
|
||||||
|
node: LucideIconNode[];
|
||||||
|
} & ({ size: number } | { width: number; height: number; })
|
||||||
|
```
|
||||||
|
|
||||||
|
| name | type | description |
|
||||||
|
|------------------------------|--------------------|------------------------------------------------------------------------------|
|
||||||
|
| `name` | `string` | The name of the icon. |
|
||||||
|
| `node` | `LucideIconNode[]` | A list of SVG paths, each path described as a `[tagName, attributes]` tuple. |
|
||||||
|
| `size` or `width` & `height` | `number` | The dimensions of the icon. |
|
||||||
|
|
||||||
|
## How to use
|
||||||
|
|
||||||
|
Lucide is built with ES Modules, so it's completely tree-shakable.
|
||||||
|
|
||||||
|
Each icon data descriptor can be imported separately. This way, only the icons that are imported into your project are included in the final bundle. The rest of the icons are tree-shaken away.
|
||||||
|
|
||||||
|
## Building icons
|
||||||
|
|
||||||
|
`@lucide/icons` provides four ways to build icons for later rendering, these are:
|
||||||
|
|
||||||
|
### `buildLucideIconData`
|
||||||
|
|
||||||
|
Returns the icon as a `LucideIconNode` tuple: `['svg', attributes, childNodes]`.
|
||||||
|
|
||||||
|
### Building SVG strings
|
||||||
|
|
||||||
|
`buildLucideSvg(icon: LucideIcon)`
|
||||||
|
|
||||||
|
Returns the icon
|
||||||
|
|
||||||
|
## Dynamic imports
|
||||||
|
|
||||||
|
It is possible to create one generic icon component to load icons, but it is not recommended.
|
||||||
|
Since it is importing all icons during build. This increases build time and the different modules it will create.
|
||||||
|
|
||||||
|
`DynamicIcon` is useful for applications that want to show icons dynamically by icon name. For example, when using a content management system with where icon names are stored in a database.
|
||||||
|
|
||||||
|
For static use cases, it is recommended to import the icons directly.
|
||||||
|
|
||||||
|
The same props can be passed to adjust the icon appearance. The
|
||||||
|
`name` prop is required to load the correct icon.
|
||||||
|
|
||||||
|
```js
|
||||||
|
import {lucideDynamicIconImports} from '@lucide/icons/dynamic';
|
||||||
|
|
||||||
|
const icon: LucideIconData = await lucideDynamicIconImports['house']().then();
|
||||||
|
```
|
||||||
4
docs/public/framework-logos/ts.svg
Normal file
4
docs/public/framework-logos/ts.svg
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none" viewBox="0 0 24 24">
|
||||||
|
<path fill="#3178C6" d="M24 0H0v24h24V0Z"/>
|
||||||
|
<path fill="#fff" fill-rule="evenodd" d="M14.11 18.797v2.588c.421.215.918.375 1.49.487a9.45 9.45 0 0 0 1.819.16 8.35 8.35 0 0 0 1.772-.179 4.407 4.407 0 0 0 1.472-.59c.421-.272.75-.628 1.003-1.07.243-.44.365-.983.365-1.63 0-.47-.065-.882-.206-1.238a2.98 2.98 0 0 0-.61-.947 4.48 4.48 0 0 0-.946-.74 11.05 11.05 0 0 0-1.247-.62c-.338-.14-.647-.27-.919-.412a4.124 4.124 0 0 1-.684-.403 1.784 1.784 0 0 1-.44-.44.928.928 0 0 1-.15-.525c0-.178.046-.338.14-.478.093-.141.225-.263.384-.366.169-.103.375-.178.619-.234.244-.057.515-.085.806-.085.216 0 .44.019.684.047.244.028.479.084.722.15.244.066.479.15.713.253.225.103.44.225.637.356v-2.418a6.524 6.524 0 0 0-1.293-.338 10.228 10.228 0 0 0-1.604-.112c-.618 0-1.2.065-1.753.197a4.42 4.42 0 0 0-1.453.618c-.422.282-.75.638-.993 1.07-.244.43-.366.955-.366 1.555 0 .77.225 1.425.666 1.978.45.544 1.125 1.004 2.024 1.388.357.15.685.29.994.431.31.14.572.281.797.44.225.16.403.32.534.498.132.178.197.384.197.61a.921.921 0 0 1-.121.468c-.085.14-.207.262-.366.375-.16.112-.366.187-.619.244a3.957 3.957 0 0 1-.862.084 4.938 4.938 0 0 1-1.67-.3 4.752 4.752 0 0 1-1.537-.872Zm-4.313-6.45h3.328V10.22H3.844v2.128h3.31v9.497h2.633v-9.497h.01Z" clip-rule="evenodd"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 1.3 KiB |
10
packages/icons/.npmignore
Normal file
10
packages/icons/.npmignore
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
stats
|
||||||
|
node_modules
|
||||||
|
tests
|
||||||
|
scripts
|
||||||
|
build
|
||||||
|
src
|
||||||
|
babel.config.js
|
||||||
|
jest.config.js
|
||||||
|
rollup.config.js
|
||||||
|
yarn.error.log
|
||||||
83
packages/icons/README.md
Normal file
83
packages/icons/README.md
Normal file
@@ -0,0 +1,83 @@
|
|||||||
|
<p align="center">
|
||||||
|
<a href="https://github.com/lucide-icons/lucide">
|
||||||
|
<img src="https://lucide.dev/package-logos/lucide.svg" alt="Lucide icon library for web applications." width="540">
|
||||||
|
</a>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p align="center">
|
||||||
|
Lucide icon library for web applications.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div align="center">
|
||||||
|
|
||||||
|
[](https://www.npmjs.com/package/lucide)
|
||||||
|

|
||||||
|
[](https://lucide.dev/license)
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p align="center">
|
||||||
|
<a href="https://lucide.dev/guide/">About</a>
|
||||||
|
·
|
||||||
|
<a href="https://lucide.dev/icons/">Icons</a>
|
||||||
|
·
|
||||||
|
<a href="https://lucide.dev/guide/packages/lucide">Documentation</a>
|
||||||
|
·
|
||||||
|
<a href="https://lucide.dev/license">License</a>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
# Lucide
|
||||||
|
|
||||||
|
Implementation of the lucide icon library for web applications.
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
```sh
|
||||||
|
pnpm add lucide
|
||||||
|
```
|
||||||
|
|
||||||
|
```sh
|
||||||
|
npm install lucide
|
||||||
|
```
|
||||||
|
|
||||||
|
```sh
|
||||||
|
yarn add lucide
|
||||||
|
```
|
||||||
|
|
||||||
|
```sh
|
||||||
|
bun add lucide
|
||||||
|
```
|
||||||
|
|
||||||
|
### CDN
|
||||||
|
|
||||||
|
```html
|
||||||
|
<!-- Development version -->
|
||||||
|
<script src="https://unpkg.com/lucide@latest/dist/umd/lucide.js"></script>
|
||||||
|
|
||||||
|
<!-- Production version -->
|
||||||
|
<script src="https://unpkg.com/lucide@latest"></script>
|
||||||
|
```
|
||||||
|
|
||||||
|
## Documentation
|
||||||
|
|
||||||
|
For full documentation, visit [lucide.dev](https://lucide.dev/guide/packages/lucide)
|
||||||
|
|
||||||
|
## Community
|
||||||
|
|
||||||
|
Join the [Discord server](https://discord.gg/EH6nSts) to chat with the maintainers and other users.
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
Lucide is licensed under the ISC license. See [LICENSE](https://lucide.dev/license).
|
||||||
|
|
||||||
|
## Sponsors
|
||||||
|
|
||||||
|
<a href="https://vercel.com?utm_source=lucide&utm_campaign=oss">
|
||||||
|
<img src="https://lucide.dev/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"><img src="https://lucide.dev/digitalocean.svg" width="200" alt="DigitalOcean Referral Badge" /></a>
|
||||||
|
|
||||||
|
### Awesome backers 🍺
|
||||||
|
|
||||||
|
<a href="https://www.scipress.io?utm_source=lucide"><img src="https://lucide.dev/sponsors/scipress.svg" width="180" alt="Scipress sponsor badge" /></a>
|
||||||
|
<a href="https://github.com/pdfme/pdfme"><img src="../../docs/public/sponsors/pdfme.svg" width="180" alt="pdfme sponsor badge" /></a>
|
||||||
77
packages/icons/package.json
Normal file
77
packages/icons/package.json
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
{
|
||||||
|
"name": "@lucide/icons",
|
||||||
|
"description": "A Lucide icon library that contains icon data in a standard Lucide format.",
|
||||||
|
"version": "0.0.1",
|
||||||
|
"license": "ISC",
|
||||||
|
"homepage": "https://lucide.dev",
|
||||||
|
"bugs": "https://github.com/lucide-icons/lucide/issues",
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/lucide-icons/lucide.git",
|
||||||
|
"directory": "packages/lucide"
|
||||||
|
},
|
||||||
|
"keywords": [
|
||||||
|
"Lucide",
|
||||||
|
"HTML",
|
||||||
|
"Feather",
|
||||||
|
"Icons",
|
||||||
|
"Icon",
|
||||||
|
"SVG",
|
||||||
|
"Feather Icons"
|
||||||
|
],
|
||||||
|
"amdName": "lucide-icons",
|
||||||
|
"source": "src/lucide-icons.ts",
|
||||||
|
"main": "dist/cjs/lucide-icons.cjs",
|
||||||
|
"module": "dist/esm/lucide-icons.mjs",
|
||||||
|
"types": "dist/esm/lucide-icons.d.ts",
|
||||||
|
"sideEffects": false,
|
||||||
|
"exports": {
|
||||||
|
".": {
|
||||||
|
"types": "./dist/esm/lucide-icons.d.ts",
|
||||||
|
"import": "./dist/esm/lucide-icons.mjs",
|
||||||
|
"require": "./dist/cjs/lucide-icons.cjs",
|
||||||
|
"default": "./dist/esm/lucide-icons.mjs"
|
||||||
|
},
|
||||||
|
"./icons/*": {
|
||||||
|
"import": "./dist/esm/icons/*.mjs",
|
||||||
|
"default": "./dist/esm/icons/*.mjs"
|
||||||
|
},
|
||||||
|
"./dynamic": {
|
||||||
|
"types": "./dist/esm/dynamic.d.ts",
|
||||||
|
"import": "./dist/esm/dynamic.mjs",
|
||||||
|
"require": "./dist/cjs/dynamic.cjs",
|
||||||
|
"default": "./dist/esm/dynamic.mjs"
|
||||||
|
},
|
||||||
|
"./build": {
|
||||||
|
"types": "./dist/esm/build.d.ts",
|
||||||
|
"import": "./dist/esm/build.mjs",
|
||||||
|
"require": "./dist/cjs/build.cjs",
|
||||||
|
"default": "./dist/esm/build.mjs"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"scripts": {
|
||||||
|
"build": "pnpm clean && pnpm copy:license && pnpm build:icons && pnpm build:bundle",
|
||||||
|
"copy:license": "cp ../../LICENSE ./LICENSE",
|
||||||
|
"clean": "rm -rf dist && rm -rf stats && rm -rf ./src/icons/*.ts",
|
||||||
|
"build:icons": "build-icons --output=./src --templateSrc=./scripts/exportTemplate.mjs --renderUniqueKey --withAliases --withDynamicImports --separateAliasesFile --aliasesFileExtension=.ts --iconFileExtension=.ts --exportFileName=index.ts",
|
||||||
|
"build:bundle": "rollup -c rollup.config.mjs",
|
||||||
|
"test": "pnpm build:icons && vitest run",
|
||||||
|
"test:watch": "vitest watch",
|
||||||
|
"test:update": "vitest -u",
|
||||||
|
"version": "pnpm version --git-tag-version=false"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@lucide/build-icons": "workspace:*",
|
||||||
|
"@lucide/helpers": "^1.0.0",
|
||||||
|
"@lucide/rollup-plugins": "workspace:*",
|
||||||
|
"@rollup/plugin-replace": "^6.0.2",
|
||||||
|
"@testing-library/jest-dom": "^6.6.3",
|
||||||
|
"jest-serializer-html": "^7.1.0",
|
||||||
|
"rollup": "^4.53.3",
|
||||||
|
"rollup-plugin-dts": "^6.2.3",
|
||||||
|
"rollup-plugin-preserve-directives": "^0.4.0",
|
||||||
|
"typescript": "^5.8.3",
|
||||||
|
"vite": "^7.2.4",
|
||||||
|
"vitest": "^4.0.12"
|
||||||
|
}
|
||||||
|
}
|
||||||
87
packages/icons/rollup.config.mjs
Normal file
87
packages/icons/rollup.config.mjs
Normal file
@@ -0,0 +1,87 @@
|
|||||||
|
import plugins from '@lucide/rollup-plugins';
|
||||||
|
import pkg from './package.json' with { type: 'json' };
|
||||||
|
import dts from 'rollup-plugin-dts';
|
||||||
|
|
||||||
|
const packageName = '@lucide/icons';
|
||||||
|
const outputFileName = 'lucide-icons';
|
||||||
|
const inputs = [`src/lucide-icons.ts`];
|
||||||
|
const bundles = [
|
||||||
|
{
|
||||||
|
format: 'cjs',
|
||||||
|
inputs,
|
||||||
|
extension: 'cjs',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
format: 'esm',
|
||||||
|
inputs: [...inputs, './src/dynamic.ts', './src/build.ts'],
|
||||||
|
preserveModules: true,
|
||||||
|
extension: 'mjs',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
const configs = bundles
|
||||||
|
.map(
|
||||||
|
({
|
||||||
|
inputs,
|
||||||
|
outputDir = 'dist',
|
||||||
|
outputFile,
|
||||||
|
format,
|
||||||
|
minify,
|
||||||
|
preserveModules,
|
||||||
|
entryFileNames,
|
||||||
|
external = [],
|
||||||
|
paths,
|
||||||
|
extension = 'js',
|
||||||
|
}) =>
|
||||||
|
inputs.map((input) => ({
|
||||||
|
input,
|
||||||
|
plugins: [...plugins({ pkg, minify })],
|
||||||
|
external,
|
||||||
|
output: {
|
||||||
|
name: packageName,
|
||||||
|
entryFileNames,
|
||||||
|
...(preserveModules
|
||||||
|
? {
|
||||||
|
dir: `${outputDir}/${format}`,
|
||||||
|
entryFileNames: `[name].${extension}`,
|
||||||
|
}
|
||||||
|
: {
|
||||||
|
file:
|
||||||
|
outputFile ??
|
||||||
|
`${outputDir}/${format}/${outputFileName}${minify ? '.min' : ''}.${extension}`,
|
||||||
|
}),
|
||||||
|
paths,
|
||||||
|
format,
|
||||||
|
sourcemap: true,
|
||||||
|
preserveModules,
|
||||||
|
exports: 'named',
|
||||||
|
globals: {},
|
||||||
|
preserveModulesRoot: 'src',
|
||||||
|
},
|
||||||
|
})),
|
||||||
|
)
|
||||||
|
.flat();
|
||||||
|
|
||||||
|
export default [
|
||||||
|
...[
|
||||||
|
outputFileName,
|
||||||
|
`${outputFileName}.prefixed`,
|
||||||
|
`${outputFileName}.suffixed`,
|
||||||
|
'dynamic',
|
||||||
|
'build',
|
||||||
|
].map((filename) => ({
|
||||||
|
input: `./src/${filename}.ts`,
|
||||||
|
output: [
|
||||||
|
{
|
||||||
|
file: `dist/esm/${filename}.d.ts`,
|
||||||
|
format: 'esm',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
file: `dist/cjs/${filename}.d.cts`,
|
||||||
|
format: 'cjs',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
plugins: [dts()],
|
||||||
|
})),
|
||||||
|
...configs,
|
||||||
|
];
|
||||||
36
packages/icons/scripts/exportTemplate.mjs
Normal file
36
packages/icons/scripts/exportTemplate.mjs
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
/* eslint-disable import/no-extraneous-dependencies */
|
||||||
|
import base64SVG from '@lucide/build-icons/utils/base64SVG';
|
||||||
|
|
||||||
|
export default async ({
|
||||||
|
componentName,
|
||||||
|
iconName,
|
||||||
|
children,
|
||||||
|
getSvg,
|
||||||
|
deprecated,
|
||||||
|
deprecationReason,
|
||||||
|
}) => {
|
||||||
|
const svgContents = await getSvg();
|
||||||
|
const svgBase64 = base64SVG(svgContents);
|
||||||
|
|
||||||
|
return `
|
||||||
|
import type { LucideIcon } from '../types';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @name ${iconName}
|
||||||
|
* @description Lucide SVG icon node.
|
||||||
|
*
|
||||||
|
* @preview  - https://lucide.dev/icons/${iconName}
|
||||||
|
* @see https://lucide.dev/guide/packages/lucide - Documentation
|
||||||
|
*
|
||||||
|
* @returns {Array}
|
||||||
|
* ${deprecated ? `@deprecated ${deprecationReason}` : ''}
|
||||||
|
*/
|
||||||
|
const ${componentName}: LucideIcon = ${JSON.stringify({
|
||||||
|
name: iconName,
|
||||||
|
size: 24,
|
||||||
|
node: children,
|
||||||
|
})}
|
||||||
|
|
||||||
|
export default ${componentName};
|
||||||
|
`;
|
||||||
|
};
|
||||||
3
packages/icons/src/aliases/index.ts
Normal file
3
packages/icons/src/aliases/index.ts
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
export * from './aliases';
|
||||||
|
export * from './prefixed';
|
||||||
|
export * from './suffixed';
|
||||||
4
packages/icons/src/build.ts
Normal file
4
packages/icons/src/build.ts
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
export { default as buildLucideIconNode } from './buildLucideIconNode';
|
||||||
|
export { default as buildLucideDataUri } from './buildLucideDataUri';
|
||||||
|
export { default as buildLucideIconElement } from './buildLucideIconElement';
|
||||||
|
export { default as buildLucideSvg } from './buildLucideSvg';
|
||||||
14
packages/icons/src/buildLucideDataUri.ts
Normal file
14
packages/icons/src/buildLucideDataUri.ts
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
import { LucideBuildParams, LucideIcon } from './types';
|
||||||
|
import buildLucideSvg from './buildLucideSvg';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a base64 encoded data URI from a Lucide icon object.
|
||||||
|
*
|
||||||
|
* @param icon The icon to build.
|
||||||
|
* @param params Additional build parameters.
|
||||||
|
*/
|
||||||
|
function buildLucideDataUri(icon: LucideIcon, params: LucideBuildParams = {}) {
|
||||||
|
return `data:image/svg+xml;base64,${btoa(buildLucideSvg(icon, params))}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default buildLucideDataUri;
|
||||||
34
packages/icons/src/buildLucideIconElement.ts
Normal file
34
packages/icons/src/buildLucideIconElement.ts
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
import { LucideBuildParams, LucideIcon, LucideIconNode } from './types';
|
||||||
|
import buildLucideIconNode from './buildLucideIconNode';
|
||||||
|
|
||||||
|
const buildDomElement = (
|
||||||
|
document: Document,
|
||||||
|
[tagName, attributes, children = []]: LucideIconNode,
|
||||||
|
): Element => {
|
||||||
|
const element = document.createElementNS('http://www.w3.org/2000/svg', tagName);
|
||||||
|
for (const [attrName, value] of Object.entries(attributes)) {
|
||||||
|
element.setAttribute(attrName, value);
|
||||||
|
}
|
||||||
|
for (const node of children) {
|
||||||
|
const childNode = buildDomElement(document, node);
|
||||||
|
element.appendChild(childNode);
|
||||||
|
}
|
||||||
|
return element;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates an SvgElement from a Lucide icon object.
|
||||||
|
*
|
||||||
|
* @param document The document to create the Element in.
|
||||||
|
* @param icon The icon to build.
|
||||||
|
* @param params Additional build parameters.
|
||||||
|
*/
|
||||||
|
function buildLucideIconElement(
|
||||||
|
document: Document,
|
||||||
|
icon: LucideIcon,
|
||||||
|
params: LucideBuildParams = {},
|
||||||
|
) {
|
||||||
|
return buildDomElement(document, buildLucideIconNode(icon, params));
|
||||||
|
}
|
||||||
|
|
||||||
|
export default buildLucideIconElement;
|
||||||
45
packages/icons/src/buildLucideIconNode.ts
Normal file
45
packages/icons/src/buildLucideIconNode.ts
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
import { LucideBuildParams, LucideIcon, LucideIconNode } from './types';
|
||||||
|
|
||||||
|
const defaultAttributes = {
|
||||||
|
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',
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a Lucide icon node (an svgson-like format) from a Lucide icon object.
|
||||||
|
*
|
||||||
|
* @param icon The icon to build.
|
||||||
|
* @param params Additional build parameters.
|
||||||
|
*/
|
||||||
|
function buildLucideIconNode(icon: LucideIcon, params: LucideBuildParams = {}): LucideIconNode {
|
||||||
|
const viewBoxWidth = ('size' in icon ? icon.size : icon.width) ?? defaultAttributes.width;
|
||||||
|
const viewBoxHeight = ('size' in icon ? icon.size : icon.height) ?? defaultAttributes.height;
|
||||||
|
const attributes = {
|
||||||
|
...defaultAttributes,
|
||||||
|
...('color' in params && { stroke: params['color'] }),
|
||||||
|
...('size' in params &&
|
||||||
|
params['size'] && {
|
||||||
|
width: params['size'].toString(10),
|
||||||
|
height: params['size'].toString(10),
|
||||||
|
}),
|
||||||
|
...('width' in params && params['width'] && { width: params['width'].toString(10) }),
|
||||||
|
...('height' in params && params['height'] && { height: params['height'].toString(10) }),
|
||||||
|
...('strokeWidth' in params &&
|
||||||
|
params['strokeWidth'] && { 'stroke-width': params['strokeWidth'].toString(10) }),
|
||||||
|
...('absoluteStrokeWidth' in params &&
|
||||||
|
params['absoluteStrokeWidth'] && { 'vector-effect': 'non-scaling-stroke' }),
|
||||||
|
class: `lucide lucide-${icon.name} ${params['className'] ?? ''}`.trim(),
|
||||||
|
viewBox: `0 0 ${viewBoxWidth} ${viewBoxHeight}`,
|
||||||
|
...('attributes' in params && params.attributes),
|
||||||
|
};
|
||||||
|
return ['svg', attributes, icon.node];
|
||||||
|
}
|
||||||
|
|
||||||
|
export default buildLucideIconNode;
|
||||||
19
packages/icons/src/buildLucideSvg.ts
Normal file
19
packages/icons/src/buildLucideSvg.ts
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
import { LucideBuildParams, LucideIcon, LucideIconNode } from './types';
|
||||||
|
import buildLucideIconNode from './buildLucideIconNode';
|
||||||
|
|
||||||
|
const buildDomNode = ([tagName, attributes, children = []]: LucideIconNode): string =>
|
||||||
|
`<${tagName} ${Object.entries(attributes)
|
||||||
|
.map(([attrName, value]) => `${attrName}="${value}"`)
|
||||||
|
.join(' ')}>${children?.map((child) => buildDomNode(child)).join('')}</${tagName}>`;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates an SVG string from a Lucide icon object.
|
||||||
|
*
|
||||||
|
* @param icon The icon to build.
|
||||||
|
* @param params Additional build parameters.
|
||||||
|
*/
|
||||||
|
function buildLucideSvg(icon: LucideIcon, params: LucideBuildParams = {}) {
|
||||||
|
return buildDomNode(buildLucideIconNode(icon, params));
|
||||||
|
}
|
||||||
|
|
||||||
|
export default buildLucideSvg;
|
||||||
2
packages/icons/src/dynamic.ts
Normal file
2
packages/icons/src/dynamic.ts
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
export { lucideIconNames, type LucideIconName } from './dynamicIcon';
|
||||||
|
export { default as lucideDynamicIconImports } from './dynamicIconImports';
|
||||||
8
packages/icons/src/dynamicIcon.ts
Normal file
8
packages/icons/src/dynamicIcon.ts
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
import dynamicIconImports from './dynamicIconImports';
|
||||||
|
|
||||||
|
export type LucideIconName = keyof typeof dynamicIconImports;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The list of available Lucide icon names.
|
||||||
|
*/
|
||||||
|
export const lucideIconNames = Object.keys(dynamicIconImports) as Array<LucideIconName>;
|
||||||
1
packages/icons/src/icons/.gitkeep
Normal file
1
packages/icons/src/icons/.gitkeep
Normal file
@@ -0,0 +1 @@
|
|||||||
|
Folder for generated icons
|
||||||
5
packages/icons/src/lucide-icons.prefixed.ts
Normal file
5
packages/icons/src/lucide-icons.prefixed.ts
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
export * as icons from './icons';
|
||||||
|
export * from './aliases/prefixed';
|
||||||
|
export * from './types';
|
||||||
|
|
||||||
|
export * from './build';
|
||||||
3
packages/icons/src/lucide-icons.suffixed.ts
Normal file
3
packages/icons/src/lucide-icons.suffixed.ts
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
export * as icons from './icons';
|
||||||
|
export * from './aliases/suffixed';
|
||||||
|
export * from './types';
|
||||||
4
packages/icons/src/lucide-icons.ts
Normal file
4
packages/icons/src/lucide-icons.ts
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
export * as icons from './icons';
|
||||||
|
export * from './icons';
|
||||||
|
export * from './aliases/index';
|
||||||
|
export * from './types';
|
||||||
42
packages/icons/src/types.ts
Normal file
42
packages/icons/src/types.ts
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
export type SVGProps = Record<string, string>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A Lucide icon node (an svgson-like internal format)
|
||||||
|
*/
|
||||||
|
export type LucideIconNode =
|
||||||
|
| [attrName: string, attributes: SVGProps]
|
||||||
|
| [attrName: string, attributes: SVGProps, children: LucideIconNode[]];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A Lucide icon object that fully describes an icon to be displayed.
|
||||||
|
*/
|
||||||
|
export type LucideIcon = {
|
||||||
|
name: string;
|
||||||
|
node: LucideIconNode[];
|
||||||
|
} & ({ size: number } | { width: number; height: number });
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Build parameters for creating a Lucide icon instance for display.
|
||||||
|
*/
|
||||||
|
export type LucideBuildParams = {
|
||||||
|
/**
|
||||||
|
* The color of the icon.
|
||||||
|
*/
|
||||||
|
color?: string;
|
||||||
|
/**
|
||||||
|
* The stroke width.
|
||||||
|
*/
|
||||||
|
strokeWidth?: number;
|
||||||
|
/**
|
||||||
|
* @deprecated Use vector-effect: non-scaling-stroke instead.
|
||||||
|
*/
|
||||||
|
absoluteStrokeWidth?: boolean;
|
||||||
|
/**
|
||||||
|
* Extra CSS class names to pass to the SVG element.
|
||||||
|
*/
|
||||||
|
className?: string;
|
||||||
|
/**
|
||||||
|
* Any extra attributes to pass to the SVG element.
|
||||||
|
*/
|
||||||
|
attributes?: SVGProps;
|
||||||
|
} & ({ size: number } | { width: number; height: number });
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
|
||||||
|
|
||||||
|
exports[`buildLucideIconElement > should match the snapshot 1`] = `
|
||||||
|
<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"
|
||||||
|
class="lucide lucide-house"
|
||||||
|
>
|
||||||
|
<path d="M15 21v-8a1 1 0 0 0-1-1h-4a1 1 0 0 0-1 1v8"
|
||||||
|
key="5wwlr5"
|
||||||
|
>
|
||||||
|
</path>
|
||||||
|
<path d="M3 10a2 2 0 0 1 .709-1.528l7-6a2 2 0 0 1 2.582 0l7 6A2 2 0 0 1 21 10v9a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"
|
||||||
|
key="r6nss1"
|
||||||
|
>
|
||||||
|
</path>
|
||||||
|
</svg>
|
||||||
|
`;
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
|
||||||
|
|
||||||
|
exports[`buildLucideIconNode > should match the snapshot 1`] = `"{"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","class":"lucide lucide-house"}"`;
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
|
||||||
|
|
||||||
|
exports[`buildLucideSvg > should match the snapshot 1`] = `
|
||||||
|
<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"
|
||||||
|
class="lucide lucide-house"
|
||||||
|
>
|
||||||
|
<path d="M15 21v-8a1 1 0 0 0-1-1h-4a1 1 0 0 0-1 1v8"
|
||||||
|
key="5wwlr5"
|
||||||
|
>
|
||||||
|
</path>
|
||||||
|
<path d="M3 10a2 2 0 0 1 .709-1.528l7-6a2 2 0 0 1 2.582 0l7 6A2 2 0 0 1 21 10v9a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"
|
||||||
|
key="r6nss1"
|
||||||
|
>
|
||||||
|
</path>
|
||||||
|
</svg>
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`buildLucideSvgDataUri > should match the snapshot 1`] = `"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0IiBmaWxsPSJub25lIiBzdHJva2U9ImN1cnJlbnRDb2xvciIgc3Ryb2tlLXdpZHRoPSIyIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiIGNsYXNzPSJsdWNpZGUgbHVjaWRlLWhvdXNlIj48cGF0aCBkPSJNMTUgMjF2LThhMSAxIDAgMCAwLTEtMWgtNGExIDEgMCAwIDAtMSAxdjgiIGtleT0iNXd3bHI1Ij48L3BhdGg+PHBhdGggZD0iTTMgMTBhMiAyIDAgMCAxIC43MDktMS41MjhsNy02YTIgMiAwIDAgMSAyLjU4MiAwbDcgNkEyIDIgMCAwIDEgMjEgMTB2OWEyIDIgMCAwIDEtMiAySDVhMiAyIDAgMCAxLTItMnoiIGtleT0icjZuc3MxIj48L3BhdGg+PC9zdmc+"`;
|
||||||
44
packages/icons/tests/buildLucideIconElement.spec.ts
Normal file
44
packages/icons/tests/buildLucideIconElement.spec.ts
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
import { describe, expect, it } from 'vitest';
|
||||||
|
import { House } from '../src/lucide-icons';
|
||||||
|
import { getOriginalSvg, removeKeys } from './helpers';
|
||||||
|
import buildLucideIconElement from '../src/buildLucideIconElement';
|
||||||
|
|
||||||
|
describe('buildLucideIconElement', () => {
|
||||||
|
it('should create SVG Element', () => {
|
||||||
|
const HomeSVG = buildLucideIconElement(document, House);
|
||||||
|
|
||||||
|
expect(HomeSVG.tagName).toBe('svg');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should match the snapshot', () => {
|
||||||
|
const HomeSVG = buildLucideIconElement(document, House);
|
||||||
|
|
||||||
|
expect(HomeSVG.outerHTML).toMatchSnapshot();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create SVG Element with attributes', () => {
|
||||||
|
const HomeSVG = buildLucideIconElement(document, House, { attributes: { fill: 'red' } });
|
||||||
|
|
||||||
|
expect(HomeSVG.getAttribute('fill')).toBe('red');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create SVG Element with class name', () => {
|
||||||
|
const HomeSVG = buildLucideIconElement(document, House, { attributes: { class: 'icon' } });
|
||||||
|
|
||||||
|
expect(HomeSVG.getAttribute('class')).toBe('icon');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should merge classes', () => {
|
||||||
|
const HomeSVG = buildLucideIconElement(document, House, { className: 'icon' });
|
||||||
|
|
||||||
|
expect(HomeSVG.getAttribute('class')).toBe('lucide lucide-house icon');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create the correct svg element', () => {
|
||||||
|
const HomeSVG = buildLucideIconElement(document, House);
|
||||||
|
|
||||||
|
const svg = getOriginalSvg('house', undefined, true);
|
||||||
|
|
||||||
|
expect(removeKeys(HomeSVG.outerHTML)).toBe(svg);
|
||||||
|
});
|
||||||
|
});
|
||||||
84
packages/icons/tests/buildLucideIconNode.spec.ts
Normal file
84
packages/icons/tests/buildLucideIconNode.spec.ts
Normal file
@@ -0,0 +1,84 @@
|
|||||||
|
import { describe, expect, it } from 'vitest';
|
||||||
|
import { House } from '../src/lucide-icons';
|
||||||
|
import buildLucideIconNode from '../src/buildLucideIconNode';
|
||||||
|
|
||||||
|
describe('buildLucideIconNode', () => {
|
||||||
|
it('should create icon node', () => {
|
||||||
|
const HouseSVG = buildLucideIconNode(House);
|
||||||
|
|
||||||
|
expect(HouseSVG.at(0)).toBe('svg');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should match the snapshot', () => {
|
||||||
|
const HouseSVG = buildLucideIconNode(House);
|
||||||
|
|
||||||
|
expect(JSON.stringify(HouseSVG.at(1))).toMatchSnapshot();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should override dimensions, but not viewBox', () => {
|
||||||
|
const HouseSVG = buildLucideIconNode(House, { size: 12 });
|
||||||
|
|
||||||
|
expect(HouseSVG[1]['width']).toBe('12');
|
||||||
|
expect(HouseSVG[1]['height']).toBe('12');
|
||||||
|
expect(HouseSVG[1]['viewBox']).toBe('0 0 24 24');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should override width, but not height', () => {
|
||||||
|
const HouseSVG = buildLucideIconNode(House, { width: 12 });
|
||||||
|
|
||||||
|
expect(HouseSVG[1]['width']).toBe('12');
|
||||||
|
expect(HouseSVG[1]['height']).toBe('24');
|
||||||
|
expect(HouseSVG[1]['viewBox']).toBe('0 0 24 24');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should override height, but not width', () => {
|
||||||
|
const HouseSVG = buildLucideIconNode(House, { height: 12 });
|
||||||
|
|
||||||
|
expect(HouseSVG[1]['width']).toBe('24');
|
||||||
|
expect(HouseSVG[1]['height']).toBe('12');
|
||||||
|
expect(HouseSVG[1]['viewBox']).toBe('0 0 24 24');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should override color', () => {
|
||||||
|
const HouseSVG = buildLucideIconNode(House, { color: 'pink' });
|
||||||
|
|
||||||
|
expect(HouseSVG[1]['stroke']).toBe('pink');
|
||||||
|
expect(HouseSVG[1]['fill']).toBe('none');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should override stroke width', () => {
|
||||||
|
const HouseSVG = buildLucideIconNode(House, { strokeWidth: 12 });
|
||||||
|
|
||||||
|
expect(HouseSVG[1]['stroke-width']).toBe('12');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should set non-scaling-stroke', () => {
|
||||||
|
const HouseSVG = buildLucideIconNode(House, { absoluteStrokeWidth: true });
|
||||||
|
|
||||||
|
expect(HouseSVG[1]['vector-effect']).toBe('non-scaling-stroke');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not set non-scaling-stroke', () => {
|
||||||
|
const HouseSVG = buildLucideIconNode(House, { absoluteStrokeWidth: false });
|
||||||
|
|
||||||
|
expect(HouseSVG[1]['vector-effect']).toBeUndefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create icon node with attributes', () => {
|
||||||
|
const HouseSVG = buildLucideIconNode(House, { attributes: { fill: 'red' } });
|
||||||
|
|
||||||
|
expect(HouseSVG[1]['fill']).toBe('red');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create icon node with class name', () => {
|
||||||
|
const HouseSVG = buildLucideIconNode(House, { attributes: { class: 'icon' } });
|
||||||
|
|
||||||
|
expect(HouseSVG[1]['class']).toBe('icon');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should merge classes', () => {
|
||||||
|
const HouseSVG = buildLucideIconNode(House, { className: 'icon' });
|
||||||
|
|
||||||
|
expect(HouseSVG[1]['class']).toBe('lucide lucide-house icon');
|
||||||
|
});
|
||||||
|
});
|
||||||
29
packages/icons/tests/buildLucideSvg.spec.ts
Normal file
29
packages/icons/tests/buildLucideSvg.spec.ts
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
import { describe, expect, it } from 'vitest';
|
||||||
|
import { House } from '../src/lucide-icons';
|
||||||
|
import { getOriginalSvg, removeKeys } from './helpers';
|
||||||
|
import buildLucideSvg from '../src/buildLucideSvg';
|
||||||
|
import buildLucideDataUri from '../src/buildLucideDataUri';
|
||||||
|
|
||||||
|
describe('buildLucideSvg', () => {
|
||||||
|
it('should match the snapshot', () => {
|
||||||
|
const HouseSVG = buildLucideSvg(House);
|
||||||
|
|
||||||
|
expect(HouseSVG).toMatchSnapshot();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create the correct svg element', () => {
|
||||||
|
const HouseSVG = buildLucideSvg(House);
|
||||||
|
|
||||||
|
const svg = getOriginalSvg('house', undefined, true);
|
||||||
|
|
||||||
|
expect(removeKeys(HouseSVG)).toBe(svg);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('buildLucideSvgDataUri', () => {
|
||||||
|
it('should match the snapshot', () => {
|
||||||
|
const HouseDataUri = buildLucideDataUri(House);
|
||||||
|
|
||||||
|
expect(HouseDataUri).toMatchSnapshot();
|
||||||
|
});
|
||||||
|
});
|
||||||
18
packages/icons/tests/helpers.ts
Normal file
18
packages/icons/tests/helpers.ts
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
import fs from 'fs';
|
||||||
|
import path from 'path';
|
||||||
|
import { parseSync, stringify } from 'svgson';
|
||||||
|
|
||||||
|
const ICONS_DIR = path.resolve(__dirname, '../../../icons');
|
||||||
|
|
||||||
|
export const getOriginalSvg = (iconName: string, aliasName?: string, setAttrs = true) => {
|
||||||
|
const svgContent = fs.readFileSync(path.join(ICONS_DIR, `${iconName}.svg`), 'utf8');
|
||||||
|
const svgParsed = parseSync(svgContent);
|
||||||
|
|
||||||
|
if (setAttrs) {
|
||||||
|
svgParsed.attributes['class'] = `lucide lucide-${aliasName ?? iconName}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
return stringify(svgParsed, { selfClose: false });
|
||||||
|
};
|
||||||
|
|
||||||
|
export const removeKeys = (svg: string) => svg.replaceAll(/ key="[^"]+"/g, '');
|
||||||
10
packages/icons/tests/lucide-icons.spec.ts
Normal file
10
packages/icons/tests/lucide-icons.spec.ts
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
import { describe, expect, it } from 'vitest';
|
||||||
|
import { House } from '../src/lucide-icons';
|
||||||
|
|
||||||
|
describe('lucide-icons', () => {
|
||||||
|
it('should init', () => {
|
||||||
|
const HouseSVG = House;
|
||||||
|
|
||||||
|
expect(House).toMatchObject(House);
|
||||||
|
});
|
||||||
|
});
|
||||||
5
packages/icons/tests/setupVitest.js
Normal file
5
packages/icons/tests/setupVitest.js
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
import { expect } from 'vitest';
|
||||||
|
import '@testing-library/jest-dom/vitest';
|
||||||
|
import htmlSerializer from 'jest-serializer-html';
|
||||||
|
|
||||||
|
expect.addSnapshotSerializer(htmlSerializer);
|
||||||
22
packages/icons/tsconfig.json
Normal file
22
packages/icons/tsconfig.json
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"strict": true,
|
||||||
|
"declaration": false,
|
||||||
|
"noEmitOnError": true,
|
||||||
|
"noEmit": true,
|
||||||
|
"noFallthroughCasesInSwitch": true,
|
||||||
|
"moduleResolution": "node",
|
||||||
|
"module": "ESNext",
|
||||||
|
"target": "ESNext",
|
||||||
|
"esModuleInterop": true,
|
||||||
|
"isolatedModules": true,
|
||||||
|
"lib": ["esnext", "dom"],
|
||||||
|
"skipLibCheck": true,
|
||||||
|
"resolveJsonModule": true,
|
||||||
|
"allowSyntheticDefaultImports": true,
|
||||||
|
"downlevelIteration": true,
|
||||||
|
"sourceMap": true,
|
||||||
|
"outDir": "./dist",
|
||||||
|
},
|
||||||
|
"exclude": ["**/node_modules"],
|
||||||
|
}
|
||||||
9
packages/icons/vitest.config.mts
Normal file
9
packages/icons/vitest.config.mts
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
import { defineConfig } from 'vitest/config';
|
||||||
|
|
||||||
|
export default defineConfig({
|
||||||
|
test: {
|
||||||
|
globals: true,
|
||||||
|
environment: 'jsdom',
|
||||||
|
setupFiles: './tests/setupVitest.js',
|
||||||
|
}
|
||||||
|
});
|
||||||
68
pnpm-lock.yaml
generated
68
pnpm-lock.yaml
generated
@@ -385,6 +385,45 @@ importers:
|
|||||||
version: 0.11.8
|
version: 0.11.8
|
||||||
publishDirectory: dist
|
publishDirectory: dist
|
||||||
|
|
||||||
|
packages/lucide-icons:
|
||||||
|
devDependencies:
|
||||||
|
'@lucide/build-icons':
|
||||||
|
specifier: workspace:*
|
||||||
|
version: link:../../tools/build-icons
|
||||||
|
'@lucide/helpers':
|
||||||
|
specifier: ^1.0.0
|
||||||
|
version: 1.0.0
|
||||||
|
'@lucide/rollup-plugins':
|
||||||
|
specifier: workspace:*
|
||||||
|
version: link:../../tools/rollup-plugins
|
||||||
|
'@rollup/plugin-replace':
|
||||||
|
specifier: ^6.0.2
|
||||||
|
version: 6.0.3(rollup@4.53.3)
|
||||||
|
'@testing-library/jest-dom':
|
||||||
|
specifier: ^6.6.3
|
||||||
|
version: 6.9.1
|
||||||
|
jest-serializer-html:
|
||||||
|
specifier: ^7.1.0
|
||||||
|
version: 7.1.0
|
||||||
|
rollup:
|
||||||
|
specifier: ^4.53.3
|
||||||
|
version: 4.53.3
|
||||||
|
rollup-plugin-dts:
|
||||||
|
specifier: ^6.2.3
|
||||||
|
version: 6.2.3(rollup@4.53.3)(typescript@5.9.3)
|
||||||
|
rollup-plugin-preserve-directives:
|
||||||
|
specifier: ^0.4.0
|
||||||
|
version: 0.4.0(rollup@4.53.3)
|
||||||
|
typescript:
|
||||||
|
specifier: ^5.8.3
|
||||||
|
version: 5.9.3
|
||||||
|
vite:
|
||||||
|
specifier: ^7.2.4
|
||||||
|
version: 7.2.4(@types/node@24.10.1)(jiti@2.6.1)(less@4.2.0)(sass@1.77.8)(stylus@0.56.0)(terser@5.44.1)(yaml@2.8.0)
|
||||||
|
vitest:
|
||||||
|
specifier: ^4.0.12
|
||||||
|
version: 4.0.12(@types/debug@4.1.12)(@types/node@24.10.1)(jiti@2.6.1)(jsdom@20.0.3)(less@4.2.0)(sass@1.77.8)(stylus@0.56.0)(terser@5.44.1)(yaml@2.8.0)
|
||||||
|
|
||||||
packages/lucide-preact:
|
packages/lucide-preact:
|
||||||
devDependencies:
|
devDependencies:
|
||||||
'@lucide/build-icons':
|
'@lucide/build-icons':
|
||||||
@@ -3850,6 +3889,9 @@ packages:
|
|||||||
'@lezer/lr@1.4.3':
|
'@lezer/lr@1.4.3':
|
||||||
resolution: {integrity: sha512-yenN5SqAxAPv/qMnpWW0AT7l+SxVrgG+u0tNsRQWqbrz66HIl8DnEbBObvy21J5K7+I1v7gsAnlE2VQ5yYVSeA==}
|
resolution: {integrity: sha512-yenN5SqAxAPv/qMnpWW0AT7l+SxVrgG+u0tNsRQWqbrz66HIl8DnEbBObvy21J5K7+I1v7gsAnlE2VQ5yYVSeA==}
|
||||||
|
|
||||||
|
'@lucide/helpers@1.0.0':
|
||||||
|
resolution: {integrity: sha512-9dfxrgLLaoCfr3R/eh6wwlUcY+ZPdEv6SDwFMUhYoO6HhGL8yN8hb5ZwI/OfzbK9mdJpa+jYfwP4nF4ZlZwZLA==}
|
||||||
|
|
||||||
'@mapbox/node-pre-gyp@1.0.11':
|
'@mapbox/node-pre-gyp@1.0.11':
|
||||||
resolution: {integrity: sha512-Yhlar6v9WQgUp/He7BdgzOz8lqMQ8sU+jkCq7Wx8Myc5YFJLbEe7lgui/V7G1qB1DJykHSGwreceSaD60Y0PUQ==}
|
resolution: {integrity: sha512-Yhlar6v9WQgUp/He7BdgzOz8lqMQ8sU+jkCq7Wx8Myc5YFJLbEe7lgui/V7G1qB1DJykHSGwreceSaD60Y0PUQ==}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
@@ -15834,7 +15876,7 @@ snapshots:
|
|||||||
'@babel/parser': 7.28.5
|
'@babel/parser': 7.28.5
|
||||||
'@babel/template': 7.27.2
|
'@babel/template': 7.27.2
|
||||||
'@babel/types': 7.28.5
|
'@babel/types': 7.28.5
|
||||||
debug: 4.3.5
|
debug: 4.4.3
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
|
|
||||||
@@ -17066,6 +17108,8 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
'@lezer/common': 1.3.0
|
'@lezer/common': 1.3.0
|
||||||
|
|
||||||
|
'@lucide/helpers@1.0.0': {}
|
||||||
|
|
||||||
'@mapbox/node-pre-gyp@1.0.11(encoding@0.1.13)':
|
'@mapbox/node-pre-gyp@1.0.11(encoding@0.1.13)':
|
||||||
dependencies:
|
dependencies:
|
||||||
detect-libc: 2.1.2
|
detect-libc: 2.1.2
|
||||||
@@ -17880,7 +17924,7 @@ snapshots:
|
|||||||
|
|
||||||
'@rollup/pluginutils@5.1.0(rollup@4.53.3)':
|
'@rollup/pluginutils@5.1.0(rollup@4.53.3)':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@types/estree': 1.0.6
|
'@types/estree': 1.0.8
|
||||||
estree-walker: 2.0.2
|
estree-walker: 2.0.2
|
||||||
picomatch: 2.3.1
|
picomatch: 2.3.1
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
@@ -18175,7 +18219,7 @@ snapshots:
|
|||||||
'@sveltejs/vite-plugin-svelte-inspector@4.0.1(@sveltejs/vite-plugin-svelte@5.1.1(svelte@5.43.14)(vite@6.4.1(@types/node@24.10.1)(jiti@2.6.1)(less@4.2.0)(sass@1.77.8)(stylus@0.56.0)(terser@5.44.1)(yaml@2.8.0)))(svelte@5.43.14)(vite@6.4.1(@types/node@24.10.1)(jiti@2.6.1)(less@4.2.0)(sass@1.77.8)(stylus@0.56.0)(terser@5.44.1)(yaml@2.8.0))':
|
'@sveltejs/vite-plugin-svelte-inspector@4.0.1(@sveltejs/vite-plugin-svelte@5.1.1(svelte@5.43.14)(vite@6.4.1(@types/node@24.10.1)(jiti@2.6.1)(less@4.2.0)(sass@1.77.8)(stylus@0.56.0)(terser@5.44.1)(yaml@2.8.0)))(svelte@5.43.14)(vite@6.4.1(@types/node@24.10.1)(jiti@2.6.1)(less@4.2.0)(sass@1.77.8)(stylus@0.56.0)(terser@5.44.1)(yaml@2.8.0))':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@sveltejs/vite-plugin-svelte': 5.1.1(svelte@5.43.14)(vite@6.4.1(@types/node@24.10.1)(jiti@2.6.1)(less@4.2.0)(sass@1.77.8)(stylus@0.56.0)(terser@5.44.1)(yaml@2.8.0))
|
'@sveltejs/vite-plugin-svelte': 5.1.1(svelte@5.43.14)(vite@6.4.1(@types/node@24.10.1)(jiti@2.6.1)(less@4.2.0)(sass@1.77.8)(stylus@0.56.0)(terser@5.44.1)(yaml@2.8.0))
|
||||||
debug: 4.4.1
|
debug: 4.4.3
|
||||||
svelte: 5.43.14
|
svelte: 5.43.14
|
||||||
vite: 6.4.1(@types/node@24.10.1)(jiti@2.6.1)(less@4.2.0)(sass@1.77.8)(stylus@0.56.0)(terser@5.44.1)(yaml@2.8.0)
|
vite: 6.4.1(@types/node@24.10.1)(jiti@2.6.1)(less@4.2.0)(sass@1.77.8)(stylus@0.56.0)(terser@5.44.1)(yaml@2.8.0)
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
@@ -18486,11 +18530,11 @@ snapshots:
|
|||||||
'@types/eslint-scope@3.7.7':
|
'@types/eslint-scope@3.7.7':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@types/eslint': 9.6.0
|
'@types/eslint': 9.6.0
|
||||||
'@types/estree': 0.0.51
|
'@types/estree': 1.0.8
|
||||||
|
|
||||||
'@types/eslint@9.6.0':
|
'@types/eslint@9.6.0':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@types/estree': 0.0.51
|
'@types/estree': 1.0.8
|
||||||
'@types/json-schema': 7.0.15
|
'@types/json-schema': 7.0.15
|
||||||
|
|
||||||
'@types/estree@0.0.39': {}
|
'@types/estree@0.0.39': {}
|
||||||
@@ -19311,7 +19355,7 @@ snapshots:
|
|||||||
|
|
||||||
acorn-walk@8.3.3:
|
acorn-walk@8.3.3:
|
||||||
dependencies:
|
dependencies:
|
||||||
acorn: 8.14.1
|
acorn: 8.15.0
|
||||||
|
|
||||||
acorn@8.12.1: {}
|
acorn@8.12.1: {}
|
||||||
|
|
||||||
@@ -20365,7 +20409,7 @@ snapshots:
|
|||||||
code-red@1.0.4:
|
code-red@1.0.4:
|
||||||
dependencies:
|
dependencies:
|
||||||
'@jridgewell/sourcemap-codec': 1.5.5
|
'@jridgewell/sourcemap-codec': 1.5.5
|
||||||
'@types/estree': 1.0.6
|
'@types/estree': 1.0.8
|
||||||
acorn: 8.14.0
|
acorn: 8.14.0
|
||||||
estree-walker: 3.0.3
|
estree-walker: 3.0.3
|
||||||
periscopic: 3.1.0
|
periscopic: 3.1.0
|
||||||
@@ -22628,7 +22672,7 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
'@tootallnate/once': 1.1.2
|
'@tootallnate/once': 1.1.2
|
||||||
agent-base: 6.0.2
|
agent-base: 6.0.2
|
||||||
debug: 4.3.3
|
debug: 4.4.3
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
|
|
||||||
@@ -22997,7 +23041,7 @@ snapshots:
|
|||||||
|
|
||||||
is-reference@3.0.3:
|
is-reference@3.0.3:
|
||||||
dependencies:
|
dependencies:
|
||||||
'@types/estree': 1.0.6
|
'@types/estree': 1.0.8
|
||||||
|
|
||||||
is-regex@1.2.1:
|
is-regex@1.2.1:
|
||||||
dependencies:
|
dependencies:
|
||||||
@@ -25392,7 +25436,7 @@ snapshots:
|
|||||||
|
|
||||||
periscopic@3.1.0:
|
periscopic@3.1.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
'@types/estree': 1.0.6
|
'@types/estree': 1.0.8
|
||||||
estree-walker: 3.0.3
|
estree-walker: 3.0.3
|
||||||
is-reference: 3.0.3
|
is-reference: 3.0.3
|
||||||
|
|
||||||
@@ -26991,7 +27035,7 @@ snapshots:
|
|||||||
socks-proxy-agent@6.2.1:
|
socks-proxy-agent@6.2.1:
|
||||||
dependencies:
|
dependencies:
|
||||||
agent-base: 6.0.2
|
agent-base: 6.0.2
|
||||||
debug: 4.3.3
|
debug: 4.4.3
|
||||||
socks: 2.8.3
|
socks: 2.8.3
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
@@ -26999,7 +27043,7 @@ snapshots:
|
|||||||
socks-proxy-agent@7.0.0:
|
socks-proxy-agent@7.0.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
agent-base: 6.0.2
|
agent-base: 6.0.2
|
||||||
debug: 4.3.3
|
debug: 4.4.3
|
||||||
socks: 2.8.3
|
socks: 2.8.3
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
|
|||||||
Reference in New Issue
Block a user