Compare commits

...

35 Commits

Author SHA1 Message Date
Eric Fennis
36232cd771 Fix release workflow 2021-03-23 20:15:01 +01:00
Eric Fennis
87863402ea Fix version 2021-03-23 19:49:34 +01:00
Eric Fennis
b4e4f002f2 Lucide 0.15.0 (#272)
* add configs

* Add vue components

* Add documentation

* add alpha release version

* improve npm ignore files

* add tests

* Make style and class attrs work

* 📦 bump version

* Add Icon suffix for component names

* bump version

* Add icon component example

* remove space

* add new build strategy

* Write a better intro

* add other node design

* fix

* add new default template

* add tempalte

* improve code

* small improvements

* small improvements

* move files

* Connect lucide with lucide-react

* Add support for vue

* Add licenses to packages

* Fix tests

* refactor build scripts

* Minor code fixes

* update homepage readme

* Update footer text

* Add a better introduction to packages

* Split up in tempaltes

* Add new types build file

* Setup workflow file

* update readme

* update

* Fix build

* remove debug code

* Add check if svgs have duplicated children

* Add check if their are no children

* small fixes

* last fixes in the build

* Move script to packages folder

* Fix tests and add types for lucide

* Add rule to package.json

* add types in build

* add npm ignore

* update package.jsons
2021-03-23 19:26:50 +01:00
SMAH1
9d101a5275 Generate index.d.ts when build (#269) 2021-03-22 21:50:14 +01:00
Eric Fennis
3e50bf13e4 Fix cloud icons (#271) 2021-03-20 09:38:12 +01:00
Eric Fennis
da946d5657 add new thermometer icons (#259) 2021-03-19 18:10:59 +01:00
R
16a1ffc40e lucide-react - Generate types for all exported icons (#243)
* Generate types for all exported icons

* renderUniqueKey will generate duplicate keys if the SVG attributse are identical.
Fixed by adding an index attribute to the hash.

* Revert "renderUniqueKey will generate duplicate keys if the SVG attributse are identical. Fixed by adding an index attribute to the hash."

This reverts commit 1c42b39e

* Update packages/lucide-react/build-types.js

* Update packages/lucide-react/build-types.js

Co-authored-by: Eric Fennis <eric.fennis@gmail.com>
2021-03-17 20:35:57 +01:00
Andreas Törnkvist
b4c034e729 file-input and file-output (#251)
* add file input and output icons

* Update icons/file-output.svg

* Update icons/file-input.svg

Co-authored-by: Eric Fennis <eric.fennis@gmail.com>
2021-03-16 21:14:29 +01:00
Eric Fennis
cb61706968 refactor sun icons (#247) 2021-03-16 21:13:54 +01:00
Eric Fennis
17bdd7aa91 Refactor plus and minus size (#262) 2021-03-16 20:54:19 +01:00
Yashu Mittal
0f3551e9c7 add mouse-pointer-click icon (#216) 2021-03-16 20:49:07 +01:00
0xflotus
4a5898a458 fix: small error (#265) 2021-03-16 20:44:33 +01:00
Eric Fennis
3aa2521c37 Refactor redo & undo (#257)
* refactor redo

* refactor undo
2021-03-13 22:05:00 +01:00
dependabot[bot]
5f6d20ad82 chore(deps): Bump elliptic from 6.5.3 to 6.5.4 in /site (#260)
Bumps [elliptic](https://github.com/indutny/elliptic) from 6.5.3 to 6.5.4.
- [Release notes](https://github.com/indutny/elliptic/releases)
- [Commits](https://github.com/indutny/elliptic/compare/v6.5.3...v6.5.4)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-03-13 22:03:27 +01:00
Eric Fennis
4bc8aae6bb Add more tags (#255) 2021-03-09 10:38:19 +01:00
Yashu Mittal
d582a980d7 Add loader-2 icon (#229) 2021-03-08 18:09:22 +01:00
Eric Fennis
1513f61522 Fix duplicated contributors (#254) 2021-03-07 20:57:28 +01:00
Andreas Törnkvist
103d4aa3a4 fix spelling errors in tags.json (#249)
* fix spelling errors in tags.json

* US and UK spelling

Co-authored-by: Eric Fennis <eric.fennis@gmail.com>
2021-03-07 10:32:11 +01:00
Yashu Mittal
303ad629fc add clipboard-list icon (#240) 2021-03-04 11:24:59 +01:00
Eric Fennis
32cef3bdbb New cloud icons (#246)
* refactor cloud icons

* Add new cloud icons
2021-03-03 16:16:35 +01:00
delnyn
f45ea99192 💱 Add Johnletey's currencies and banknote icons (#234)
* 💱 Add Johnletey's currencies and banknote icons

Create banknote.svg, bitcoin.svg, euro.svg, pound-sterling.svg, indian-rupee.svg, jersey-pound.svg, russian-ruble.svg, swiss-franc.svg, and update tags.json

* Add files via upload

* Update icons/euro.svg

Co-authored-by: Eric Fennis <eric.fennis@gmail.com>

Co-authored-by: Eric Fennis <eric.fennis@gmail.com>
2021-03-02 22:24:03 +01:00
Andreas Törnkvist
78690fb9ed droplets (#248)
* droplets icon

* Update icons/droplets.svg

Co-authored-by: Eric Fennis <eric.fennis@gmail.com>
2021-03-01 19:47:09 +01:00
Eric Fennis
f67eb1897a Merge branch 'hotfix/fix-react-component' 2021-02-27 11:39:14 +01:00
Eric Fennis
285f9446b4 Merge branch 'master' of github.com:lucide-icons/lucide 2021-02-27 11:38:49 +01:00
Eric Fennis
95a7d8648f v0.14.1 2021-02-27 11:31:24 +01:00
Eric Fennis
b07eb8c00d Merge branch 'master' of github.com:lucide-icons/lucide into hotfix/fix-react-component 2021-02-27 11:23:36 +01:00
Eric Fennis
40cb396a6c Fix proptypes 2021-02-27 11:21:35 +01:00
Eric Fennis
87ab0bfb62 Figma plugin! (#227)
* initialize figma plugin

* Add icons to view

* Make the plugin work

* Fix search hook

* Finialize figma plugin

* Finish up icons

* remove unused code

* Add cover and icon
2021-02-26 16:35:18 +01:00
Yashu Mittal
c4f50417d5 maintain 1px border spacing in languages icon (#232) 2021-02-26 13:32:07 +01:00
Lucide Bot
0ca1b98689 📦 Bump version to 0.14.0 2021-02-22 19:46:47 +00:00
Eric Fennis
7ce35bac34 Merge branch 'master' of github.com:ericfennis/featherity 2021-02-22 20:36:44 +01:00
Eric Fennis
5ec34cb249 Merge branch 'master' of github.com:lucide-icons/lucide 2021-02-22 20:32:02 +01:00
Eric Fennis
313b46ecc1 update tags 2021-02-08 22:17:56 +01:00
Eric Fennis
367f89ef1f add tags 2021-02-08 21:55:48 +01:00
Eric Fennis
32ba19d591 Add script to add more tags 2021-02-08 21:18:43 +01:00
127 changed files with 10960 additions and 1654 deletions

View File

@@ -20,13 +20,9 @@ jobs:
- name: Install FontForge
run: sudo apt-get install zlib1g-dev fontforge
- name: Install NodeJS and Yarn
run: sudo apt-get install nodejs yarn
- name: Clone sfnt2woff-zopfli repo
run: git clone https://github.com/bramstein/sfnt2woff-zopfli.git sfnt2woff-zopfli
- name: Install and move sfnt2woff-zopfli
run: |
cd sfnt2woff-zopfli
@@ -36,7 +32,6 @@ jobs:
- name: Clone woff2
run: git clone --recursive https://github.com/google/woff2.git
- name: Install woff2
run: |
cd woff2
@@ -47,16 +42,14 @@ jobs:
run: sudo gem install fontcustom
- name: Install "outline-stroke"
run: sudo yarn add svg-outline-stroke svgson
run: sudo yarn add svg-outline-stroke -W
- name: "Outline SVG"
run: mkdir converted_icons && node scripts/outline_svg.js
- name: Build 'Lucide'
run: echo "Building Lucide font" && fontcustom compile ./converted_icons -h -n Lucide -o build -F
- name: Zip 'Lucide'
run: zip -r Lucide.zip build

View File

@@ -1,4 +1,4 @@
name: Release to NPM
name: Release Packages
on:
push:
@@ -6,94 +6,153 @@ on:
- 'v*'
jobs:
build-and-deploy:
pre-build:
if: github.repository == 'lucide-icons/lucide'
runs-on: ubuntu-latest
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
outputs:
VERSION: ${{ steps.get_version.outputs.VERSION }}
YARN_CACHE_DIR: ${{ steps.yarn_cache.outputs.YARN_CACHE_DIR }}
steps:
- name: Get the version
id: get_version
run: echo ::set-output name=VERSION::${GITHUB_REF/refs\/tags\/\v}
- name: Get yarn cache directory path
id: yarn_cache
run: echo "::set-output name=YARN_CACHE_DIR::$(yarn cache dir)"
lucide:
if: github.repository == 'lucide-icons/lucide'
runs-on: ubuntu-latest
needs: pre-build
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v2
with:
clean: true
node-version: '12.x'
- uses: actions/cache@v2
id: yarn-cache
with:
path: ${{ needs.pre-build.outputs.YARN_CACHE_DIR }}
key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}
restore-keys: |
${{ runner.os }}-yarn-
- name: Install dependencies
if: steps.yarn-cache.outputs.cache-hit != 'true'
run: yarn --pure-lockfile
- name: Set Auth Token
run: npm config set //registry.npmjs.org/:_authToken ${{ secrets.NPM_TOKEN }}
# Build lucide
- name: Install Dependencies Lucide
run: yarn --pure-lockfile
- name: Set new version
run: yarn workspace lucide version --new-version ${{ needs.pre-build.outputs.VERSION }} --no-git-tag-version
- name: Build lucide package
run: yarn build
- name: Build
run: yarn workspace lucide build
- name: Test lucide package
run: yarn test
- name: Test
run: yarn workspace lucide test
# Build lucide-react
- name: Install Dependencies lucide-react
run: yarn --pure-lockfile
working-directory: packages/lucide-react
- name: Build lucide-react
run: yarn build
working-directory: packages/lucide-react
- name: Test lucide-react
run: yarn test
working-directory: packages/lucide-react
# Build lucide-vue
- name: Install Dependencies lucide-vue
run: yarn --pure-lockfile
working-directory: packages/lucide-vue
- name: Build lucide-vue
run: yarn build
working-directory: packages/lucide-vue
- name: Test lucide-vue
run: yarn test
working-directory: packages/lucide-vue
# Publish lucide
- name: Set package.json version lucide
run: yarn version --new-version ${{ steps.get_version.outputs.VERSION }} --no-git-tag-version
- name: publish lucide
run: yarn publish
# Publish lucide-react
- name: Set package.json version lucide-react
run: yarn version --new-version ${{ steps.get_version.outputs.VERSION }} --no-git-tag-version
working-directory: packages/lucide-react
- name: publish lucide-react
run: yarn publish
working-directory: packages/lucide-react
# Publish lucide-vue
- name: Set package.json version lucide-vue
run: yarn version --new-version ${{ steps.get_version.outputs.VERSION }} --no-git-tag-version
working-directory: packages/lucide-vue
- name: publish lucide-vue
run: yarn publish
working-directory: packages/lucide-vue
- name: Publish
run: yarn workspace lucide publish
- name: Commit package.json
run: |
git add package.json
git add packages/lucide-react/package.json
git add packages/lucide-vue/package.json
git add packages/lucide/package.json
git -c user.name="Lucide Bot" -c user.email="lucide-bot@users.noreply.github.com" \
commit -m ":package: Bump version to ${{ steps.get_version.outputs.VERSION }}" --no-verify --quiet
git remote set-url --push origin https://lucide-bot:$GITHUB_TOKEN@github.com/$GITHUB_REPOSITORY.git
commit -m ":package: Bump version lucide to ${{ needs.pre-build.outputs.VERSION }}" --no-verify --quiet
git remote set-url --push origin https://lucide-bot:${{ secrets.GITHUB_TOKEN }}@github.com/$GITHUB_REPOSITORY.git
git push origin HEAD:master
lucide-react:
if: github.repository == 'lucide-icons/lucide'
runs-on: ubuntu-latest
needs: pre-build
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v2
with:
node-version: '12.x'
- uses: actions/cache@v2
id: yarn-cache
with:
path: ${{ needs.pre-build.outputs.YARN_CACHE_DIR }}
key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}
restore-keys: |
${{ runner.os }}-yarn-
- name: Install dependencies
if: steps.yarn-cache.outputs.cache-hit != 'true'
run: yarn --pure-lockfile
- name: Set Auth Token
run: npm config set //registry.npmjs.org/:_authToken ${{ secrets.NPM_TOKEN }}
- name: Set package.json version lucide
run: yarn workspace lucide-react version --new-version ${{ needs.pre-build.outputs.VERSION }} --no-git-tag-version
- name: Build
run: yarn workspace lucide-react build
- name: Test
run: yarn workspace lucide-react test
- name: Publish
run: yarn workspace lucide-react publish
- name: Commit package.json
run: |
git add packages/lucide-react/package.json
git -c user.name="Lucide Bot" -c user.email="lucide-bot@users.noreply.github.com" \
commit -m ":package: Bump version lucide-react to ${{ needs.pre-build.outputs.VERSION }}" --no-verify --quiet
git remote set-url --push origin https://lucide-bot:${{ secrets.GITHUB_TOKEN }}@github.com/$GITHUB_REPOSITORY.git
git push origin HEAD:master
lucide-vue:
if: github.repository == 'lucide-icons/lucide'
runs-on: ubuntu-latest
needs: pre-build
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v2
with:
node-version: '12.x'
- uses: actions/cache@v2
id: yarn-cache
with:
path: ${{ needs.pre-build.outputs.YARN_CACHE_DIR }}
key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}
restore-keys: |
${{ runner.os }}-yarn-
- name: Install dependencies
if: steps.yarn-cache.outputs.cache-hit != 'true'
run: yarn --pure-lockfile
- name: Set Auth Token
run: npm config set //registry.npmjs.org/:_authToken ${{ secrets.NPM_TOKEN }}
- name: Set new version
run: yarn workspace lucide-vue version --new-version ${{ needs.pre-build.outputs.VERSION }} --no-git-tag-version
- name: Build
run: yarn workspace lucide-vue build
- name: Test
run: yarn workspace lucide-vue test
- name: Publish
run: yarn workspace lucide-vue publish
- name: Commit package.json
run: |
git add packages/lucide-vue/package.json
git -c user.name="Lucide Bot" -c user.email="lucide-bot@users.noreply.github.com" \
commit -m ":package: Bump version lucide-vue to ${{ needs.pre-build.outputs.VERSION }}" --no-verify --quiet
git remote set-url --push origin https://lucide-bot:${{ secrets.GITHUB_TOKEN }}@github.com/$GITHUB_REPOSITORY.git
git push origin HEAD:master

2
.gitignore vendored
View File

@@ -4,9 +4,9 @@
node_modules
dist
build
/lib
sandbox
stash
coverage
stats
*.log
packages/**/src/icons/*.js

166
README.md
View File

@@ -9,6 +9,15 @@
## What is Lucide?
Lucide is a community-run fork of [Feather Icons](https://github.com/feathericons/feather), open for anyone to contribute icons.
Started after growing disaffection of the moderation of the [Feather Icons](https://github.com/feathericons/feather) project, with over 300+ open issues and over 100+ open PRs, this project is no longer maintained. The owner of the project stopped merging icons and want to keep the project like it now is. Hundreds of developers/designer wasted their time trying to contribute, what a shame.
We're trying to expanding the icon set as much as possible while keeping it nice-looking, we do it as a community of devs and designers, join us!
### Why choose Lucide over Feather Icons
- Lucide already expended the icon set by 130+ in less then a year, so more icons to work with.
- Well maintained code base.
- Active community.
## Table of Contents
@@ -16,38 +25,14 @@ Lucide is a community-run fork of [Feather Icons](https://github.com/feathericon
* [Package managers](#package-managers)
* [CDN](#cdn)
* [Usage](#usage)
* [Unpkg](#with-unpkg)
* [ESModules](#with-esmodules)
* [Options](#additional-options)
* [Treeshake library](#treeshake-the-library-only-use-the-icons-you-use)
* [Custom binding](#custom-element-binding)
* [React](#with-react)
* [Vue](#with-vue)
* [Web](#web)
* [React](#react)
* [Vue](#vue)
* [Figma](#figma)
* [Contributing](#contributing)
* [Community](#community)
* [License](#license)
## Installation
### Package Managers
``` bash
npm install lucide
#or
yarn 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>
```
## Usage
At its core, Lucide is a collection of [SVG](https://svgontheweb.com/#svg) files. This means that you can use Feather icons in all the same ways you can use SVGs (e.g. `img`, `background-image`, `inline`, `object`, `embed`, `iframe`). Here's a helpful article detailing the many ways SVGs can be used on the web: [SVG on the Web Implementation Options](https://svgontheweb.com/#implementation)
@@ -55,104 +40,23 @@ At its core, Lucide is a collection of [SVG](https://svgontheweb.com/#svg) files
The following are additional ways you can use Lucide.
With the Javascript library you can easily incorporate the icon you want in your webpage.
### With unpkg
### Web
Here is a complete example with unpkg
Implementation of the lucide icon library for web applications.
```html
<!DOCTYPE html>
<body>
<i icon-name="volume-2" class="my-class"></i>
<i icon-name="x"></i>
<i icon-name="menu"></i>
```sh
npm install lucide
<script src="https://unpkg.com/lucide@latest"></script>
<script>
lucide.createIcons();
</script>
</body>
#or
yarn add lucide
```
### With ESModules
For more details, see the [documentation](https://github.com/lucide-icons/lucide/blob/master/packages/lucide-react/README.md).
To reduce bundle size, lucide is built to be fully treeshakable.
The `createIcons` function will search for HTMLElements with the attribute `icon-name` and replace it with the svg from the given icon name.
### React
```html
<!-- Your HTML file -->
<i icon-name="menu"></i>
```
```js
import { createIcons, icons } from 'lucide';
// Caution, this will import all the icons and bundle them.
createIcons({icons});
// Recommended way, to include only the icons you need.
import { createIcons, Menu, ArrowRight, Globe } from 'lucide';
createIcons({
icons: {
Menu,
ArrowRight,
Globe,
},
});
```
#### Additional Options
In the `createIcons` function you can pass some extra parameters to adjust the `nameAttr` or add custom attributes like for example classes.
Here is a full example:
```js
import { createIcons } from 'lucide';
createIcons({
attrs: {
class: ['my-custom-class', 'icon'],
'stroke-width': 1,
stroke: '#333',
},
nameAttr: 'icon-name', // atrribute for the icon name.
});
```
#### Treeshake the library, only use the icons you use
```js
import { createIcons, Menu, ArrowRight, Globe } from 'lucide';
createIcons({
icons: {
Menu,
ArrowRight,
Globe,
},
});
```
#### Custom Element binding
```js
import { createElement, Menu } from 'lucide';
const menuIcon = createElement(Menu); // Returns HTMLElement (svg)
// set custom attributes with browser native functions
menuIcon.setAttribute('stroke', '#333');
menuIcon.classList.add('my-icon-class');
// Append HTMLElement in webpage
const myApp = document.getElementById('app');
myApp.appendChild(menuIcon);
```
### With React
You can also use the Lucide library using the react package.
Implementation of the lucide icon library for react applications.
```sh
yarn add lucide-react
@@ -162,11 +66,11 @@ yarn add lucide-react
npm install lucide-react
```
For more details, see the [documentation](https://github.com/lucide-icons/lucide/blob/master/packages/lucide-react/README.md).
For more details, see the [documentation](https://github.com/lucide-icons/lucide/tree/master/packages/lucide-react#lucide-react).
### With Vue
### Vue
You can also use the Lucide library using the Vue package.
Implementation of the lucide icon library for vue applications.
```sh
yarn add lucide-vue
@@ -176,11 +80,15 @@ yarn add lucide-vue
npm install lucide-vue
```
For more details, see the [documentation](https://github.com/lucide-icons/lucide/blob/master/packages/lucide-vue/README.md).
For more details, see the [documentation](https://github.com/lucide-icons/lucide/tree/master/packages/lucide-vue#lucide-vue).
### Figma
You can use the components from [this Figma file](https://www.figma.com/file/g0UipfQlRfGrntKPxZknM7/Featherity).
The lucide figma plugin.
Visit [Figma community page](https://www.figma.com/community/plugin/939567362549682242/Lucide-Icons) to install the plugin.
<img width="420" src="https://www.figma.com/community/plugin/939567362549682242/thumbnail" alt="Figma Lucide Cover">
## Contributing
@@ -194,10 +102,10 @@ Join the community on our [Discord](https://discord.gg/EH6nSts) server!
## License
Lucide is licensed under the [ISC License](https://github.com/lucide-icons/lucide/blob/master/LICENSE).
Lucide is totally free for commercial use and personally use, this software is licensed under the [ISC License](https://github.com/lucide-icons/lucide/blob/master/LICENSE).
<p align="center">
<a href="https://vercel.com?utm_source=lucide&utm_campaign=oss">
<img src="./site/public/vercel.svg" alt="Powered by Vercel" width="200" />
</a>
</p>
## Sponsors
<a href="https://vercel.com?utm_source=lucide&utm_campaign=oss">
<img src="./site/public/vercel.svg" alt="Powered by Vercel" width="200" />
</a>

View File

@@ -1,13 +1,5 @@
module.exports = {
presets: [
[
'@babel/env',
{
loose: true,
modules: false,
},
],
],
presets: ['@babel/env'],
env: {
test: {
presets: ['@babel/env'],

View File

@@ -14,5 +14,5 @@
<path d="M22 6l-3-3" />
<path d="M6 19l-2 2" />
<path d="M18 19l2 2" />
<path d="M8 13h8" />
<path d="M9 13h6" />
</svg>

Before

Width:  |  Height:  |  Size: 382 B

After

Width:  |  Height:  |  Size: 382 B

View File

@@ -14,6 +14,6 @@
<path d="M22 6l-3-3" />
<path d="M6 19l-2 2" />
<path d="M18 19l2 2" />
<path d="M12 9v8" />
<path d="M8 13h8" />
<path d="M12 10v6" />
<path d="M9 13h6" />
</svg>

Before

Width:  |  Height:  |  Size: 405 B

After

Width:  |  Height:  |  Size: 406 B

15
icons/banknote.svg Normal file
View File

@@ -0,0 +1,15 @@
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
width="24"
height="24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<rect x="2" y="6" width="20" height="12" rx="2" />
<circle cx="12" cy="12" r="2" />
<path d="M6 12h.01M18 12h.01" />
</svg>

After

Width:  |  Height:  |  Size: 331 B

13
icons/bitcoin.svg Normal file
View File

@@ -0,0 +1,13 @@
<svg
width="24"
height="24"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path d="M11.767 19.089c4.924.868 6.14-6.025 1.216-6.894m-1.216 6.894L5.86 18.047m5.908 1.042l-.347 1.97m1.563-8.864c4.924.869 6.14-6.025 1.215-6.893m-1.215 6.893l-3.94-.694m5.155-6.2L8.29 4.26m5.908 1.042l.348-1.97M7.48 20.364l3.126-17.727" />
</svg>

After

Width:  |  Height:  |  Size: 455 B

18
icons/clipboard-list.svg Normal file
View File

@@ -0,0 +1,18 @@
<svg
width="24"
height="24"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path d="M16 4h2a2 2 0 012 2v14a2 2 0 01-2 2H6a2 2 0 01-2-2V6a2 2 0 012-2h2" />
<path d="M15 2H9a1 1 0 00-1 1v2a1 1 0 001 1h6a1 1 0 001-1V3a1 1 0 00-1-1z" />
<path d="M12 11h4" />
<path d="M12 16h4" />
<path d="M8 11h.01" />
<path d="M8 16h.01" />
</svg>

After

Width:  |  Height:  |  Size: 468 B

View File

@@ -9,11 +9,11 @@
stroke-linecap="round"
stroke-linejoin="round"
>
<line x1="8" y1="19" x2="8" y2="21" />
<line x1="8" y1="13" x2="8" y2="15" />
<line x1="16" y1="19" x2="16" y2="21" />
<line x1="16" y1="13" x2="16" y2="15" />
<line x1="12" y1="21" x2="12" y2="23" />
<line x1="12" y1="15" x2="12" y2="17" />
<path d="M20 16.58A5 5 0 0018 7h-1.26A8 8 0 104 15.25" />
<path d="M20 16.2A4.5 4.5 0 0017.5 8h-1.8A7 7 0 104 14.9" />
<path d="M8 19v1" />
<path d="M8 14v1" />
<path d="M16 19v1" />
<path d="M16 14v1" />
<path d="M12 21v1" />
<path d="M12 16v1" />
</svg>

Before

Width:  |  Height:  |  Size: 522 B

After

Width:  |  Height:  |  Size: 413 B

19
icons/cloud-hail.svg Normal file
View File

@@ -0,0 +1,19 @@
<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="M20 16.2A4.5 4.5 0 0017.5 8h-1.8A7 7 0 104 14.9" />
<path d="M16 14v2" />
<path d="M8 14v2" />
<path d="M16 20h0" />
<path d="M8 20h0" />
<path d="M12 16v2" />
<path d="M12 22h0" />
</svg>

After

Width:  |  Height:  |  Size: 413 B

View File

@@ -9,6 +9,6 @@
stroke-linecap="round"
stroke-linejoin="round"
>
<path d="M19 16.9A5 5 0 0018 7h-1.26a8 8 0 10-11.62 9" />
<polyline points="13 11 9 17 15 17 11 23" />
<path d="M17.5 17a4.5 4.5 0 100-9h-1.8a7 7 0 10-10.3 8" />
<path d="M12 12l-3 5h5l-3 5" />
</svg>

Before

Width:  |  Height:  |  Size: 315 B

After

Width:  |  Height:  |  Size: 303 B

View File

@@ -9,6 +9,7 @@
stroke-linecap="round"
stroke-linejoin="round"
>
<path d="M22.61 16.95A5 5 0 0018 10h-1.26a8 8 0 00-7.05-6M5 5a8 8 0 004 15h9a5 5 0 001.7-.3" />
<line x1="1" y1="1" x2="23" y2="23" />
<path d="M2 2l20 20" />
<path d="M10 5a7 7 0 015.7 5h1.8a4.5 4.5 0 014 6.5" />
<path d="M18.8 18.8c-.4.2-.8.2-1.3.2H9A7 7 0 015.8 5.8" />
</svg>

Before

Width:  |  Height:  |  Size: 347 B

After

Width:  |  Height:  |  Size: 352 B

16
icons/cloud-rain-wind.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="M20 16.2A4.5 4.5 0 0017.5 8h-1.8A7 7 0 104 14.9" />
<path d="M9.2 22l3-7" />
<path d="M9 13l-3 7" />
<path d="M17 13l-3 7" />
</svg>

After

Width:  |  Height:  |  Size: 351 B

View File

@@ -9,8 +9,8 @@
stroke-linecap="round"
stroke-linejoin="round"
>
<line x1="16" y1="13" x2="16" y2="21" />
<line x1="8" y1="13" x2="8" y2="21" />
<line x1="12" y1="15" x2="12" y2="23" />
<path d="M20 16.58A5 5 0 0018 7h-1.26A8 8 0 104 15.25" />
<path d="M20 16.2A4.5 4.5 0 0017.5 8h-1.8A7 7 0 104 14.9" />
<path d="M16 14v6" />
<path d="M8 14v6" />
<path d="M12 16v6" />
</svg>

Before

Width:  |  Height:  |  Size: 395 B

After

Width:  |  Height:  |  Size: 342 B

View File

@@ -9,11 +9,11 @@
stroke-linecap="round"
stroke-linejoin="round"
>
<path d="M20 17.58A5 5 0 0018 8h-1.26A8 8 0 104 16.25" />
<line x1="8" y1="16" x2="8.01" y2="16" />
<line x1="8" y1="20" x2="8.01" y2="20" />
<line x1="12" y1="18" x2="12.01" y2="18" />
<line x1="12" y1="22" x2="12.01" y2="22" />
<line x1="16" y1="16" x2="16.01" y2="16" />
<line x1="16" y1="20" x2="16.01" y2="20" />
<path d="M20 16.2A4.5 4.5 0 0017.5 8h-1.8A7 7 0 104 14.9" />
<path d="M8 15h0" />
<path d="M8 19h0" />
<path d="M12 17h0" />
<path d="M12 21h0" />
<path d="M16 15h0" />
<path d="M16 19h0" />
</svg>

Before

Width:  |  Height:  |  Size: 540 B

After

Width:  |  Height:  |  Size: 413 B

View File

@@ -9,5 +9,5 @@
stroke-linecap="round"
stroke-linejoin="round"
>
<path d="M18 10h-1.26A8 8 0 109 20h9a5 5 0 000-10z" />
<path d="M17.5 19a4.5 4.5 0 100-9h-1.8A7 7 0 109 19h8.5z" />
</svg>

Before

Width:  |  Height:  |  Size: 265 B

After

Width:  |  Height:  |  Size: 271 B

View File

@@ -9,7 +9,7 @@
stroke-linecap="round"
stroke-linejoin="round"
>
<polyline points="8 17 12 21 16 17" />
<line x1="12" y1="12" x2="12" y2="21" />
<path d="M20.88 18.09A5 5 0 0018 9h-1.26A8 8 0 103 16.29" />
<path d="M20 16.2A4.5 4.5 0 0017.5 8h-1.8A7 7 0 104 14.9" />
<path d="M12 12v9" />
<path d="M8 17l4 4 4-4" />
</svg>

Before

Width:  |  Height:  |  Size: 355 B

After

Width:  |  Height:  |  Size: 324 B

14
icons/droplets.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="M7 16.3c2.2 0 4-1.83 4-4.05 0-1.16-.57-2.26-1.71-3.19S7.29 6.75 7 5.3c-.29 1.45-1.14 2.84-2.29 3.76S3 11.1 3 12.25c0 2.22 1.8 4.05 4 4.05z" />
<path d="M12.56 6.6A10.97 10.97 0 0014 3.02c.5 2.5 2 4.9 4 6.5s3 3.5 3 5.5a6.98 6.98 0 01-11.91 4.97" />
</svg>

After

Width:  |  Height:  |  Size: 469 B

15
icons/euro.svg Normal file
View File

@@ -0,0 +1,15 @@
<svg
width="24"
height="24"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path d="M4 10h12" />
<path d="M4 14h9" />
<path d="M19 6a7.7 7.7 0 00-5.2-2A7.9 7.9 0 006 12c0 4.4 3.5 8 7.8 8 2 0 3.8-.8 5.2-2" />
</svg>

After

Width:  |  Height:  |  Size: 347 B

16
icons/file-input.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="M4 22h14a2 2 0 002-2V7.5L14.5 2H6a2 2 0 00-2 2v4" />
<path d="M14 2v6h6" />
<path d="M2 15h10" />
<path d="M9 18l3-3-3-3" />
</svg>

After

Width:  |  Height:  |  Size: 350 B

16
icons/file-output.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="M4 22h14a2 2 0 002-2V7.5L14.5 2H6a2 2 0 00-2 2v4" />
<path d="M14 2v6h6" />
<path d="M2 15h10" />
<path d="M5 12l-3 3 3 3" />
</svg>

After

Width:  |  Height:  |  Size: 351 B

20
icons/haze.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="M5.2 6.2l1.4 1.4" />
<path d="M2 13h2" />
<path d="M20 13h2" />
<path d="M17.4 7.6l1.4-1.4" />
<path d="M22 17H2" />
<path d="M22 21H2" />
<path d="M16 13a4 4 0 00-8 0" />
<path d="M12 5V2.5" />
</svg>

After

Width:  |  Height:  |  Size: 428 B

17
icons/indian-rupee.svg Normal file
View File

@@ -0,0 +1,17 @@
<svg
width="24"
height="24"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path d="M6 3h12" />
<path d="M6 8h12" />
<path d="M6 13l8.5 8" />
<path d="M6 13h3" />
<path d="M9 13c6.667 0 6.667-10 0-10" />
</svg>

After

Width:  |  Height:  |  Size: 347 B

15
icons/jersey-pound.svg Normal file
View File

@@ -0,0 +1,15 @@
<svg
width="24"
height="24"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path d="M12 9.5V21m0-11.5L6 3m6 6.5L18 3" />
<path d="M6 15h12" />
<path d="M6 11h12" />
</svg>

After

Width:  |  Height:  |  Size: 304 B

View File

@@ -9,10 +9,10 @@
stroke-linecap="round"
stroke-linejoin="round"
>
<line x1="5" y1="8" x2="11" y2="14" />
<path d="M5 8l6 6" />
<path d="M4 14l6-6 2-3" />
<line x1="2" y1="5" x2="14" y2="5" />
<line x1="7" y1="2" x2="8" y2="2" />
<path d="M22 21l-5-10-5 10" />
<line x1="14" y1="17" x2="20" y2="17" />
<path d="M2 5h12" />
<path d="M7 2h1" />
<path d="M22 22l-5-10-5 10" />
<path d="M14 18h6" />
</svg>

Before

Width:  |  Height:  |  Size: 433 B

After

Width:  |  Height:  |  Size: 363 B

13
icons/loader-2.svg Normal file
View File

@@ -0,0 +1,13 @@
<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="M21 12a9 9 0 11-6.219-8.56" />
</svg>

After

Width:  |  Height:  |  Size: 250 B

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="M9 9l5 12 1.774-5.226L21 14 9 9z" />
<path d="M16.071 16.071l4.243 4.243" />
<path d="M7.188 2.239l.777 2.897M5.136 7.965l-2.898-.777M13.95 4.05l-2.122 2.122m-5.657 5.656l-2.12 2.122" />
</svg>

After

Width:  |  Height:  |  Size: 410 B

16
icons/pound-sterling.svg Normal file
View File

@@ -0,0 +1,16 @@
<svg
width="24"
height="24"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path d="M18 7c0-5.333-8-5.333-8 0" />
<path d="M10 7v14" />
<path d="M6 21h12" />
<path d="M6 13h10" />
</svg>

After

Width:  |  Height:  |  Size: 321 B

View File

@@ -9,6 +9,6 @@
stroke-linecap="round"
stroke-linejoin="round"
>
<polyline points="22 10 22 16 16 16" />
<path d="M1.994 16c1.813-6.542 9.559-9.482 15.36-4.36l4.64 4.36" />
<path d="M21 7v6h-6" />
<path d="M3 17a9 9 0 019-9 9 9 0 016 2.3l3 2.7" />
</svg>

Before

Width:  |  Height:  |  Size: 320 B

After

Width:  |  Height:  |  Size: 287 B

17
icons/russian-ruble.svg Normal file
View File

@@ -0,0 +1,17 @@
<svg
width="24"
height="24"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path d="M14 11c5.333 0 5.333-8 0-8" />
<path d="M6 11h8" />
<path d="M6 15h8" />
<path d="M9 21V3" />
<path d="M9 3h5" />
</svg>

After

Width:  |  Height:  |  Size: 341 B

View File

@@ -9,13 +9,13 @@
stroke-linecap="round"
stroke-linejoin="round"
>
<circle cx="12" cy="12" r="5" />
<line x1="12" y1="1" x2="12" y2="3" />
<line x1="12" y1="21" x2="12" y2="23" />
<line x1="4.22" y1="4.22" x2="5.64" y2="5.64" />
<line x1="18.36" y1="18.36" x2="19.78" y2="19.78" />
<line x1="1" y1="12" x2="3" y2="12" />
<line x1="21" y1="12" x2="23" y2="12" />
<line x1="4.22" y1="19.78" x2="5.64" y2="18.36" />
<line x1="18.36" y1="5.64" x2="19.78" y2="4.22" />
<circle cx="12" cy="12" r="4" />
<path d="M12 2v2" />
<path d="M12 20v2" />
<path d="M5 5l1.5 1.5" />
<path d="M17.5 17.5L19 19" />
<path d="M2 12h2" />
<path d="M20 12h2" />
<path d="M5 19l1.5-1.5" />
<path d="M17.5 6.5L19 5" />
</svg>

Before

Width:  |  Height:  |  Size: 623 B

After

Width:  |  Height:  |  Size: 456 B

View File

@@ -9,12 +9,12 @@
stroke-linecap="round"
stroke-linejoin="round"
>
<path d="M17 18a5 5 0 00-10 0" />
<line x1="12" y1="2" x2="12" y2="9" />
<line x1="4.22" y1="10.22" x2="5.64" y2="11.64" />
<line x1="1" y1="18" x2="3" y2="18" />
<line x1="21" y1="18" x2="23" y2="18" />
<line x1="18.36" y1="11.64" x2="19.78" y2="10.22" />
<line x1="23" y1="22" x2="1" y2="22" />
<polyline points="8 6 12 2 16 6" />
<path d="M12 2v8" />
<path d="M5.2 11.2l1.4 1.4" />
<path d="M2 18h2" />
<path d="M20 18h2" />
<path d="M17.4 12.6l1.4-1.4" />
<path d="M22 22H2" />
<path d="M8 6l4-4 4 4" />
<path d="M16 18a4 4 0 00-8 0" />
</svg>

Before

Width:  |  Height:  |  Size: 557 B

After

Width:  |  Height:  |  Size: 432 B

View File

@@ -9,12 +9,12 @@
stroke-linecap="round"
stroke-linejoin="round"
>
<path d="M17 18a5 5 0 00-10 0" />
<line x1="12" y1="9" x2="12" y2="2" />
<line x1="4.22" y1="10.22" x2="5.64" y2="11.64" />
<line x1="1" y1="18" x2="3" y2="18" />
<line x1="21" y1="18" x2="23" y2="18" />
<line x1="18.36" y1="11.64" x2="19.78" y2="10.22" />
<line x1="23" y1="22" x2="1" y2="22" />
<polyline points="16 5 12 9 8 5" />
<path d="M12 10V2" />
<path d="M5.2 11.2l1.4 1.4" />
<path d="M2 18h2" />
<path d="M20 18h2" />
<path d="M17.4 12.6l1.4-1.4" />
<path d="M22 22H2" />
<path d="M16 6l-4 4-4-4" />
<path d="M16 18a4 4 0 00-8 0" />
</svg>

Before

Width:  |  Height:  |  Size: 557 B

After

Width:  |  Height:  |  Size: 435 B

15
icons/swiss-franc.svg Normal file
View File

@@ -0,0 +1,15 @@
<svg
width="24"
height="24"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path d="M10 21V3h8" />
<path d="M6 16h9" />
<path d="M10 9.5h7" />
</svg>

After

Width:  |  Height:  |  Size: 282 B

View File

@@ -0,0 +1,18 @@
<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 12h10" />
<path d="M9 4v16" />
<path d="M3 9l3 3-3 3" />
<path d="M12 6L9 9 6 6" />
<path d="M6 18l3-3 1.5 1.5" />
<path d="M18 2a2 2 0 00-2 2v10.5a4 4 0 104 0V4a2 2 0 00-2-2z" />
</svg>

After

Width:  |  Height:  |  Size: 412 B

18
icons/thermometer-sun.svg Normal file
View File

@@ -0,0 +1,18 @@
<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 9a4 4 0 00-2 7.5" />
<path d="M12 3v2" />
<path d="M6.6 18.4l-1.4 1.4" />
<path d="M18 2a2 2 0 012 2v10.5a4 4 0 11-4 0V4c0-1.1.9-2 2-2z" />
<path d="M4 13H2" />
<path d="M6.6 7.6L5.2 6.2" />
</svg>

After

Width:  |  Height:  |  Size: 424 B

View File

@@ -9,5 +9,5 @@
stroke-linecap="round"
stroke-linejoin="round"
>
<path d="M14 14.76V3.5a2.5 2.5 0 00-5 0v11.26a4.5 4.5 0 105 0z" />
<path d="M12 2a2 2 0 00-2 2v10.5a4 4 0 104 0V4a2 2 0 00-2-2z" />
</svg>

Before

Width:  |  Height:  |  Size: 277 B

After

Width:  |  Height:  |  Size: 275 B

View File

@@ -9,6 +9,6 @@
stroke-linecap="round"
stroke-linejoin="round"
>
<polyline points="2 10 2 16 8 16" />
<path d="M22 16c-1.814-6.542-9.56-9.482-15.36-4.36L2 16" />
<path d="M3 7v6h6" />
<path d="M21 17a9 9 0 00-9-9 9 9 0 00-6 2.3L3 13" />
</svg>

Before

Width:  |  Height:  |  Size: 309 B

After

Width:  |  Height:  |  Size: 287 B

View File

@@ -9,8 +9,7 @@
stroke-linecap="round"
stroke-linejoin="round"
>
<polyline points="16 16 12 12 8 16" />
<line x1="12" y1="12" x2="12" y2="21" />
<path d="M20.39 18.39A5 5 0 0018 9h-1.26A8 8 0 103 16.3" />
<polyline points="16 16 12 12 8 16" />
<path d="M20 16.2A4.5 4.5 0 0017.5 8h-1.8A7 7 0 104 14.9" />
<path d="M12 12v9" />
<path d="M16 16l-4-4-4 4" />
</svg>

Before

Width:  |  Height:  |  Size: 395 B

After

Width:  |  Height:  |  Size: 326 B

View File

@@ -1,5 +0,0 @@
[build]
base = "site/"
publish = "build/"
command = "yarn deploy"
ignore = "git diff --quiet origin/master HEAD ../icons ../site"

View File

@@ -1,66 +1,50 @@
{
"name": "lucide",
"description": "Lucide is a community-run fork of Feather Icons, open for anyone to contribute icons.",
"version": "0.13.0",
"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"
},
"amdName": "lucide",
"source": "build/lucide.js",
"main": "dist/cjs/lucide.js",
"main:umd": "dist/umd/lucide.js",
"module": "dist/esm/lucide.js",
"unpkg": "dist/umd/lucide.min.js",
"sideEffects": false,
"private": true,
"workspaces": [
"packages/*",
"site"
],
"scripts": {
"start": "babel-watch --watch src",
"clean": "rimraf dist && rimraf build",
"build": "yarn clean && yarn build:move && yarn build:icons && yarn build:es && yarn build:bundles",
"build:move": "cp -av src build",
"build:icons": "npx babel-node ./scripts/buildIcons.js --presets @babel/env",
"build:es": "babel build -d dist/esm",
"build:bundles": "rollup -c rollup.config.js",
"optimize": "npx babel-node ./scripts/optimizeSvgs.js --presets @babel/env",
"addtags": "npx babel-node ./scripts/addMissingKeysToTags.js --presets @babel/env",
"test": "jest"
"build": "yarn lucide build && yarn lucide-react build && yarn lucide-vue build",
"test": "yarn lucide build:icons && yarn lucide-react build:icons && yarn lucide-vue build:icons && jest",
"lucide": "yarn workspace lucide",
"lucide-react": "yarn workspace lucide-react",
"lucide-vue": "yarn workspace lucide-vue",
"build:icons": "babel-node ./scripts/buildIcons.js --presets @babel/env",
"optimize": "babel-node ./scripts/optimizeSvgs.js --presets @babel/env",
"addtags": "babel-node ./scripts/addMissingKeysToTags.js --presets @babel/env"
},
"devDependencies": {
"@ampproject/rollup-plugin-closure-compiler": "^0.25.2",
"@atomico/rollup-plugin-sizes": "^1.1.4",
"@babel/cli": "^7.10.5",
"@babel/core": "^7.11.1",
"@babel/node": "^7.10.5",
"@babel/node": "^7.13.10",
"@babel/plugin-transform-runtime": "^7.11.5",
"@babel/preset-env": "^7.11.0",
"@rollup/plugin-babel": "^5.0.0",
"babel-jest": "^26.3.0",
"@rollup/plugin-commonjs": "^17.1.0",
"@rollup/plugin-node-resolve": "^11.2.0",
"@rollup/plugin-replace": "^2.4.1",
"babel-jest": "^26.6.3",
"babel-plugin-add-import-extension": "^1.4.3",
"cheerio": "^1.0.0-rc.2",
"core-js": "3",
"eslint": "^4.19.1",
"eslint-config-airbnb-base": "^12.1.0",
"eslint-config-prettier": "^2.9.0",
"eslint-plugin-import": "^2.5.0",
"eslint-plugin-prettier": "^2.5.0",
"html-minifier": "^3.5.8",
"htmlparser2": "^4.1.0",
"husky": "^4.3.6",
"jest": "^26.4.2",
"lint-staged": "^10.5.3",
"minimist": "^1.2.5",
"prettier": "1.17.1",
"rollup": "^2.7.3",
"rollup-plugin-commonjs": "^10.1.0",
"rollup-plugin-license": "^2.0.0",
"rollup-plugin-node-resolve": "^5.2.0",
"rollup-plugin-replace": "^2.2.0",
"rollup-plugin-terser": "^5.2.0",
"rollup-plugin-visualizer": "^4.1.0",
"svgo": "^1.3.2"
"svgo": "^1.3.2",
"svgson": "^4.1.0"
},
"husky": {
"hooks": {

View File

@@ -0,0 +1,25 @@
# Lucide Figma plugin
A Figma plugin for using Lucide Icons
## Local development
1. Install the dependencies
```sh
yarn
```
2. Build the plugin
```sh
yarn watch
```
3. Open the [Figma desktop app](https://www.figma.com/downloads/)
4. Go to `Menu > Plugins > Development > New Plugin...`
5. Choose `lucide/packages/lucide-figma/manifest.json`
6. Run the plugin by going to `Menu > Plugins > Development > Lucide Icons`

Binary file not shown.

After

Width:  |  Height:  |  Size: 127 KiB

675
packages/lucide-figma/figma.d.ts vendored Normal file
View File

@@ -0,0 +1,675 @@
// Global variable with Figma's plugin API.
declare const figma: PluginAPI
declare const __html__: string
interface PluginAPI {
readonly currentPage: PageNode
// Root of the current Figma document.
readonly root: DocumentNode
// API for accessing viewport information.
readonly viewport: ViewportAPI
// call this once your plugin is finished executing.
closePlugin(): void
// Command that the user chose through menu when launching the plugin.
readonly command: string
// Finds a node by its id. If not found, returns null.
getNodeById(id: string): BaseNode | null
// Finds a style by its id. If not found, returns null.
getStyleById(id: string): BaseStyle | null
// Access browser APIs and/or show UI to the user.
showUI(html: string, options?: ShowUIOptions): void
readonly ui: UIAPI
// Lets you store persistent data on the user's local machine
readonly clientStorage: ClientStorageAPI
// This value is returned when a property is in a "mixed" state.
// In order to check if a property is in a mixed state, always
// compare directly to this value. I.e.
// `if (node.cornerRadius === figma.mixed) { ... }`
mixed: symbol
// Creates new nodes. Nodes will start off inserted
// into the current page.
// To move them elsewhere use `appendChild` or `insertChild`
createRectangle(): RectangleNode
createLine(): LineNode
createEllipse(): EllipseNode
createPolygon(): PolygonNode
createStar(): StarNode
createVector(): VectorNode
createText(): TextNode
createBooleanOperation(): BooleanOperationNode
createFrame(): FrameNode
createComponent(): ComponentNode
createPage(): PageNode
createSlice(): SliceNode
// Creates styles. A style's id can be assigned to
// node properties like textStyleId, fillStyleId, etc.
createPaintStyle(): PaintStyle
createTextStyle(): TextStyle
createEffectStyle(): EffectStyle
createGridStyle(): GridStyle
// These let you insert stuff from the team library if you have the key
importComponentByKeyAsync(key: string): Promise<ComponentNode>
importStyleByKeyAsync(key: string): Promise<BaseStyle>
// Return all fonts currently supported for use with the "fontName" property
listAvailableFontsAsync(): Promise<Font[]>
// You must await the promise returned here before being able to use "fontName"
loadFontAsync(fontName: FontName): Promise<void>
// Creates node from an SVG string.
createNodeFromSvg(svg: string): FrameNode
// Creates an Image object using the provided file contents.
createImage(data: Uint8Array): Image
// Groups every node in `nodes` under a new group.
group(nodes: ReadonlyArray<BaseNode>, parent: BaseNode & ChildrenMixin, index?: number): FrameNode
// Flattens every node in `nodes` into a single vector network.
flatten(nodes: ReadonlyArray<BaseNode>, parent?: BaseNode & ChildrenMixin, index?: number): VectorNode
}
interface ClientStorageAPI {
// This stores information in the browser, not on the server. It's similar to localStorage, but is
// asynchronous, and allows storing objects, arrays, strings, numbers, booleans, null, undefined and Uint8Arrays.
getAsync(key: string): Promise<any | undefined>
setAsync(key: string, value: any): Promise<void>
}
type ShowUIOptions = {
visible?: boolean, // defaults to true
width?: number, // defaults to 300
height?: number, // defaults to 200
}
interface UIAPI {
show(): void
hide(): void
resize(width: number, height: number): void
close(): void
// Sends a message to the iframe.
postMessage(pluginMessage: any): void
// Registers a callback for messages sent by the iframe.
onmessage: ((pluginMessage: any) => void) | undefined
}
interface ViewportAPI {
center: { x: number, y: number }
// 1.0 means 100% zoom, 0.5 means 50% zoom.
zoom: number
// Adjust the viewport such that it shows the provided nodes.
scrollAndZoomIntoView(nodes: ReadonlyArray<BaseNode>)
}
// manifest.json format
interface ManifestJson {
// Name of the plugin.
name: string
// Version of the runtime that the plugin uses, e.g. '0.5.0'.
version: string
// The file name that contains the plugin code.
script: string
// The file name that contains the html code made available in script.
html?: string
// Shell command to be executed before the contents of the `html` and `script` files are read.
build?: string
// Menu items to show up in UI.
menu?: ManifestMenuItem[]
}
type ManifestMenuItem =
// Clickable menu item.
{ name: string, command: string } |
// Separator
{ separator: true } |
// Submenu
{ name: string, menu: ManifestMenuItem[] }
////////////////////////////////////////////////////////////////////////////////
// Values
// These are the top two rows of a 3x3 matrix. This is enough to represent
// translation, rotation, and skew.
type Transform = [
[number, number, number],
[number, number, number]
]
interface Vector {
readonly x: number
readonly y: number
}
interface RGB {
readonly r: number
readonly g: number
readonly b: number
}
interface RGBA {
readonly r: number
readonly g: number
readonly b: number
readonly a: number
}
interface FontName {
readonly family: string
readonly style: string
}
interface ArcData {
readonly startingAngle: number
readonly endingAngle: number
readonly innerRadius: number
}
interface ShadowEffect {
readonly type: "DROP_SHADOW" | "INNER_SHADOW"
readonly color: RGBA
readonly offset: Vector
readonly radius: number
readonly visible: boolean
readonly blendMode: BlendMode
}
interface BlurEffect {
readonly type: "LAYER_BLUR" | "BACKGROUND_BLUR"
readonly radius: number
readonly visible: boolean
}
type Effect = ShadowEffect | BlurEffect
type ConstraintType = "MIN" | "CENTER" | "MAX" | "STRETCH" | "SCALE"
interface Constraints {
readonly horizontal: ConstraintType
readonly vertical: ConstraintType
}
interface ColorStop {
readonly position: number
readonly color: RGBA
}
interface SolidPaint {
readonly type: "SOLID"
readonly color: RGB
readonly visible?: boolean
readonly opacity?: number
}
interface GradientPaint {
readonly type: "GRADIENT_LINEAR" | "GRADIENT_RADIAL" | "GRADIENT_ANGULAR" | "GRADIENT_DIAMOND"
readonly gradientTransform: Transform
readonly gradientStops: ReadonlyArray<ColorStop>
readonly visible?: boolean
readonly opacity?: number
}
interface ImagePaint {
readonly type: "IMAGE"
readonly scaleMode: "FILL" | "FIT" | "CROP" | "TILE"
readonly image: Image | null
readonly imageTransform?: Transform // setting for "CROP"
readonly scalingFactor?: number // setting for "TILE"
readonly visible?: boolean
readonly opacity?: number
}
type Paint = SolidPaint | GradientPaint | ImagePaint
interface Guide {
readonly axis: "X" | "Y"
readonly offset: number
}
interface RowsColsLayoutGrid {
readonly pattern: "ROWS" | "COLUMNS"
readonly alignment: "MIN" | "STRETCH" | "CENTER"
readonly gutterSize: number
readonly count: number // Infinity when "Auto" is set in the UI
readonly sectionSize?: number // Not set for alignment: "STRETCH"
readonly offset?: number // Not set for alignment: "CENTER"
readonly visible?: boolean
readonly color?: RGBA
}
interface GridLayoutGrid {
readonly pattern: "GRID"
readonly sectionSize: number
readonly visible?: boolean
readonly color?: RGBA
}
type LayoutGrid = RowsColsLayoutGrid | GridLayoutGrid
interface ExportSettingsImage {
format: "JPG" | "PNG"
contentsOnly?: boolean // defaults to true
suffix?: string
constraint?: { // defaults to unscaled ({ type: "SCALE", value: 1 })
type: "SCALE" | "WIDTH" | "HEIGHT"
value: number
}
}
interface ExportSettingsSVG {
format: "SVG"
contentsOnly?: boolean // defaults to true
suffix?: string
svgOutlineText?: boolean // defaults to true
svgIdAttribute?: boolean // defaults to false
svgSimplifyStroke?: boolean // defaults to true
}
interface ExportSettingsPDF {
format: "PDF"
contentsOnly?: boolean // defaults to true
suffix?: string
}
type ExportSettings = ExportSettingsImage | ExportSettingsSVG | ExportSettingsPDF
type WindingRule = "NONZERO" | "EVENODD"
interface VectorVertex {
readonly x: number
readonly y: number
readonly strokeCap?: StrokeCap
readonly strokeJoin?: StrokeJoin
readonly cornerRadius?: number
readonly handleMirroring?: HandleMirroring
}
interface VectorSegment {
readonly start: number
readonly end: number
readonly tangentStart?: Vector // Defaults to { x: 0, y: 0 }
readonly tangentEnd?: Vector // Defaults to { x: 0, y: 0 }
}
interface VectorRegion {
readonly windingRule: WindingRule
readonly loops: ReadonlyArray<ReadonlyArray<number>>
}
interface VectorNetwork {
readonly vertices: ReadonlyArray<VectorVertex>
readonly segments: ReadonlyArray<VectorSegment>
readonly regions?: ReadonlyArray<VectorRegion> // Defaults to []
}
interface VectorPath {
// Similar to the svg fill-rule
// "NONE" means an open path won't have a fill
readonly windingRule: WindingRule | "NONE"
readonly data: string
}
type VectorPaths = ReadonlyArray<VectorPath>
interface NumberWithUnits {
readonly value: number
readonly units: "PIXELS" | "PERCENT"
}
type BlendMode =
"PASS_THROUGH" |
"NORMAL" |
"DARKEN" |
"MULTIPLY" |
"LINEAR_BURN" |
"COLOR_BURN" |
"LIGHTEN" |
"SCREEN" |
"LINEAR_DODGE" |
"COLOR_DODGE" |
"OVERLAY" |
"SOFT_LIGHT" |
"HARD_LIGHT" |
"DIFFERENCE" |
"EXCLUSION" |
"HUE" |
"SATURATION" |
"COLOR" |
"LUMINOSITY"
interface Font {
fontName: FontName
}
////////////////////////////////////////////////////////////////////////////////
// Mixins
interface BaseNodeMixin {
readonly id: string
readonly parent: (BaseNode & ChildrenMixin) | null
name: string
visible: boolean
locked: boolean
removed: boolean
toString(): string
remove(): void
// Attach custom data to a node. Only your plugin will be able to read this.
getPluginData(key: string): string
setPluginData(key: string, value: string): void
// Attach custom data to a node. All plugins will be able to read this.
// Namespace is a string that must be at least 3 alphanumeric characters, and should
// be a name related to your plugin. This is a mandatory argument to avoid multiple
// multiple plugins adding keys like "data" and colliding with each other. Other
// plugins will still be able to read shared plugin data as long as they know the
// namespace you use.
getSharedPluginData(namespace: string, key: string): string
setSharedPluginData(namespace: string, key: string, value: string): void
}
interface ChildrenMixin {
// Sorted back-to-front. I.e. the top-most child is last in this array.
readonly children: ReadonlyArray<BaseNode>
// Adds to the end of the .children array. I.e. visually on top of all other
// children.
appendChild(child: BaseNode): void
insertChild(index: number, child: BaseNode): void
findAll(callback?: (node: BaseNode) => boolean): ReadonlyArray<BaseNode>
findOne(callback: (node: BaseNode) => boolean): BaseNode | null
}
interface LayoutMixin {
readonly absoluteTransform: Transform
relativeTransform: Transform
x: number // The same as "relativeTransform[0][2]"
y: number // The same as "relativeTransform[1][2]"
rotation: number // The angle of the x axis of "relativeTransform" in degrees. Returns values from -180 to 180.
readonly size: Vector
readonly width: number // The same as "size.x"
readonly height: number // The same as "size.y"
// Resizes the node. If children of the node has constraints, it applies those constraints
// width and height must be >= 0.01
resize(width: number, height: number): void
// Resizes the node. Children of the node are never resized, even if those children have
// constraints. width and height must be >= 0.01
resizeWithoutConstraints(width: number, height: number): void
constraints: Constraints
}
interface BlendMixin {
opacity: number
blendMode: BlendMode
isMask: boolean
effects: ReadonlyArray<Effect>
effectStyleId: string
}
interface FrameMixin {
backgrounds: ReadonlyArray<Paint>
layoutGrids: ReadonlyArray<LayoutGrid>
clipsContent: boolean
guides: ReadonlyArray<Guide>
gridStyleId: string
backgroundStyleId: string
}
type StrokeCap = "NONE" | "ROUND" | "SQUARE" | "ARROW_LINES" | "ARROW_EQUILATERAL"
type StrokeJoin = "MITER" | "BEVEL" | "ROUND"
type HandleMirroring = "NONE" | "ANGLE" | "ANGLE_AND_LENGTH"
interface GeometryMixin {
fills: ReadonlyArray<Paint> | symbol // This can return figma.mixed on TEXT nodes
strokes: ReadonlyArray<Paint>
strokeWeight: number
strokeAlign: "CENTER" | "INSIDE" | "OUTSIDE"
strokeCap: StrokeCap | symbol // This can return figma.mixed on VECTOR nodes if vertices have different strokeCap values
strokeJoin: StrokeJoin | symbol // This can return figma.mixed on VECTOR nodes if vertices have different strokeJoin values
dashPattern: ReadonlyArray<number>
fillStyleId: string | symbol // This can return figma.mixed on TEXT nodes
strokeStyleId: string
}
interface CornerMixin {
// This can return figma.mixed on VECTOR nodes if vertices have different cornerRadius values,
// and on RECTANGLE nodes if node.topLeftRadius etc has different values
cornerRadius: number | symbol
cornerSmoothing: number
}
interface ExportMixin {
exportSettings: ExportSettings[]
exportAsync(settings?: ExportSettings): Promise<Uint8Array> // Defaults to PNG format
}
////////////////////////////////////////////////////////////////////////////////
// Nodes
interface DocumentNode extends BaseNodeMixin, ChildrenMixin {
readonly type: "DOCUMENT"
clone(): DocumentNode // Note: this always throws an error
}
interface PageNode extends BaseNodeMixin, ChildrenMixin, ExportMixin {
readonly type: "PAGE"
clone(): PageNode // cloned node starts off inserted into current page
guides: ReadonlyArray<Guide>
selection: ReadonlyArray<BaseNode>
}
interface FrameNode extends BaseNodeMixin, BlendMixin, ChildrenMixin, FrameMixin, LayoutMixin, ExportMixin {
readonly type: "FRAME" | "GROUP"
clone(): FrameNode // cloned node starts off inserted into current page
}
interface SliceNode extends BaseNodeMixin, LayoutMixin, ExportMixin {
readonly type: "SLICE"
clone(): SliceNode // cloned node starts off inserted into current page
}
interface RectangleNode extends BaseNodeMixin, BlendMixin, CornerMixin, GeometryMixin, LayoutMixin, ExportMixin {
readonly type: "RECTANGLE"
clone(): RectangleNode // cloned node starts off inserted into current page
topLeftRadius: number
topRightRadius: number
bottomLeftRadius: number
bottomRightRadius: number
}
interface LineNode extends BaseNodeMixin, BlendMixin, GeometryMixin, LayoutMixin, ExportMixin {
readonly type: "LINE"
clone(): LineNode // cloned node starts off inserted into current page
}
interface EllipseNode extends BaseNodeMixin, BlendMixin, CornerMixin, GeometryMixin, LayoutMixin, ExportMixin {
readonly type: "ELLIPSE"
clone(): EllipseNode // cloned node starts off inserted into current page
arcData: ArcData
}
interface PolygonNode extends BaseNodeMixin, BlendMixin, CornerMixin, GeometryMixin, LayoutMixin, ExportMixin {
readonly type: "POLYGON"
clone(): PolygonNode // cloned node starts off inserted into current page
pointCount: number
}
interface StarNode extends BaseNodeMixin, BlendMixin, CornerMixin, GeometryMixin, LayoutMixin, ExportMixin {
readonly type: "STAR"
clone(): StarNode // cloned node starts off inserted into current page
pointCount: number
// This is a percentage value from 0 to 1
innerRadius: number
}
interface VectorNode extends BaseNodeMixin, BlendMixin, CornerMixin, GeometryMixin, LayoutMixin, ExportMixin {
readonly type: "VECTOR"
clone(): VectorNode // cloned node starts off inserted into current page
vectorNetwork: VectorNetwork
vectorPaths: VectorPaths
handleMirroring: HandleMirroring | symbol // This can return figma.mixed if vertices have different handleMirroring values
}
interface TextNode extends BaseNodeMixin, BlendMixin, GeometryMixin, LayoutMixin, ExportMixin {
readonly type: "TEXT"
clone(): TextNode // cloned node starts off inserted into current page
characters: string
textAlignHorizontal: "LEFT" | "CENTER" | "RIGHT" | "JUSTIFIED"
textAlignVertical: "TOP" | "CENTER" | "BOTTOM"
textAutoResize: "NONE" | "WIDTH_AND_HEIGHT" | "HEIGHT"
paragraphIndent: number
paragraphSpacing: number
autoRename: boolean
// These properties can all return figma.mixed if the text has multiple values for the property
textStyleId: string | symbol
fontSize: number | symbol
fontName: FontName | symbol
textCase: "ORIGINAL" | "UPPER" | "LOWER" | "TITLE" | symbol
textDecoration: "NONE" | "UNDERLINE" | "STRIKETHROUGH" | symbol
letterSpacing: NumberWithUnits | symbol
lineHeight: NumberWithUnits | symbol
}
interface ComponentNode extends BaseNodeMixin, BlendMixin, ChildrenMixin, FrameMixin, LayoutMixin, ExportMixin {
readonly type: "COMPONENT"
clone(): ComponentNode // cloned node starts off inserted into current page
createInstance(): InstanceNode // instance starts off inserted into current page
description: string
readonly remote: boolean
readonly key: string // The key to use with "importComponentByKeyAsync"
}
interface InstanceNode extends BaseNodeMixin, BlendMixin, ChildrenMixin, FrameMixin, LayoutMixin, ExportMixin {
readonly type: "INSTANCE"
clone(): InstanceNode // cloned node starts off inserted into current page
masterComponent: ComponentNode
}
interface BooleanOperationNode extends BaseNodeMixin, BlendMixin, ChildrenMixin, CornerMixin, GeometryMixin, LayoutMixin, ExportMixin {
readonly type: "BOOLEAN_OPERATION"
clone(): BooleanOperationNode // cloned node starts off inserted into current page
booleanOperation: "UNION" | "INTERSECT" | "SUBTRACT" | "EXCLUDE"
}
type BaseNode =
DocumentNode |
PageNode |
SliceNode |
FrameNode |
ComponentNode |
InstanceNode |
BooleanOperationNode |
VectorNode |
StarNode |
LineNode |
EllipseNode |
PolygonNode |
RectangleNode |
TextNode
type NodeType =
"DOCUMENT" |
"PAGE" |
"SLICE" |
"FRAME" |
"GROUP" |
"COMPONENT" |
"INSTANCE" |
"BOOLEAN_OPERATION" |
"VECTOR" |
"STAR" |
"LINE" |
"ELLIPSE" |
"POLYGON" |
"RECTANGLE" |
"TEXT"
////////////////////////////////////////////////////////////////////////////////
// Styles
type StyleType = "PAINT" | "TEXT" | "EFFECT" | "GRID"
interface BaseStyle {
// The string to uniquely identify a style by
readonly id: string
readonly type: StyleType
name: string // Note: setting this also sets "autoRename" to false on TextNodes
description: string
remote: boolean
readonly key: string // The key to use with "importStyleByKeyAsync"
remove(): void
}
interface PaintStyle extends BaseStyle {
type: "PAINT"
paints: ReadonlyArray<Paint>
}
interface TextStyle extends BaseStyle {
type: "TEXT"
fontSize: number
textDecoration: "NONE" | "UNDERLINE" | "STRIKETHROUGH"
fontName: FontName
letterSpacing: NumberWithUnits
lineHeight: NumberWithUnits
paragraphIndent: number
paragraphSpacing: number
textCase: "ORIGINAL" | "UPPER" | "LOWER" | "TITLE"
}
interface EffectStyle extends BaseStyle {
type: "EFFECT"
effects: ReadonlyArray<Paint>
}
interface GridStyle extends BaseStyle {
type: "GRID"
layoutGrids: ReadonlyArray<LayoutGrid>
}
////////////////////////////////////////////////////////////////////////////////
// Other
interface Image {
// Returns a unique hash for the image
readonly hash: string
// The contents of the image file
getBytesAsync(): Promise<Uint8Array>
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

View File

@@ -0,0 +1,7 @@
{
"name": "Lucide Icons",
"id": "939567362549682242",
"api": "1.0.0",
"ui": "build/ui.html",
"main": "build/main.js"
}

View File

@@ -0,0 +1,27 @@
{
"name": "lucide-figma",
"version": "0.13.0",
"license": "ISC",
"private": true,
"main": "build/ui.js",
"scripts": {
"build": "webpack --mode=production",
"watch": "webpack --mode=development --watch"
},
"dependencies": {
"@emotion/core": "^10.0.14",
"@types/react": "^16.8.23",
"@types/react-dom": "^16.8.4",
"css-loader": "^3.0.0",
"html-webpack-inline-source-plugin": "^0.0.10",
"html-webpack-plugin": "^3.2.0",
"lucide-react": "^0.13.0",
"react": "^16.8.6",
"react-dom": "^16.8.6",
"style-loader": "^0.23.1",
"ts-loader": "^6.0.4",
"typescript": "^3.5.2",
"webpack": "^4.35.2",
"webpack-cli": "^3.3.5"
}
}

View File

@@ -0,0 +1,44 @@
import { jsx } from '@emotion/core'
import theme from '../theme'
import { renderToString } from 'react-dom/server'
import { FC } from 'react';
interface IconButtonProps {
name: string,
component: FC,
}
function IconButton({ name, component: IconComponent }: IconButtonProps) {
const onIconclick = () => {
const svg = renderToString(<IconComponent/>);
parent.postMessage({ pluginMessage: { name, svg }}, '*')
}
return (
<button
key={name}
aria-label={name}
onClick={onIconclick}
css={{
padding: theme.space[2],
color: '#333',
background: 'transparent',
border: 0,
borderRadius: theme.radii[1],
appearance: 'none',
outline: 0,
'&:hover': {
background: 'rgba(0, 0, 0, 0.06)',
},
'&:focus, &:active': {
boxShadow: `inset 0 0 0 2px ${theme.colors.blue}`,
},
}}
>
<IconComponent />
</button>
)
}
export default IconButton

View File

@@ -0,0 +1,24 @@
import { createElement, forwardRef } from 'react'
const SearchIcon = forwardRef((props: any, ref) => createElement(
'svg',
{
xmlns: "http://www.w3.org/2000/svg",
width: 32,
height: 32,
clipRule: 'evenodd',
fillRule: 'evenodd',
ref,
...props,
},
[
createElement(
'path', {
d: 'm20 15c0 2.7614-2.2386 5-5 5s-5-2.2386-5-5 2.2386-5 5-5 5 2.2386 5 5zm-1.1256 4.5815c-1.0453.8849-2.3975 1.4185-3.8744 1.4185-3.3137 0-6-2.6863-6-6s2.6863-6 6-6 6 2.6863 6 6c0 1.4769-.5336 2.8291-1.4185 3.8744l4.2721 4.272-.7072.7072z',
key: 'path'
}
)
]
))
export default SearchIcon

View File

@@ -0,0 +1,43 @@
import { jsx } from '@emotion/core'
import theme from '../theme'
import SearchIcon from './search-icon'
interface SearchInputProps extends React.HTMLProps<HTMLDivElement> {
value: string,
iconCount: number,
onChange: (event: React.ChangeEvent<HTMLInputElement>) => void
}
function SearchInput({ value, onChange, iconCount, ...props }: SearchInputProps) {
return (
<div css={{ position: 'relative' }} {...props}>
<div
css={{
position: 'absolute',
top: 0,
left: 0,
padding: theme.space[1],
}}
>
<SearchIcon fill="#333" />
</div>
<input
autoFocus
type="search"
value={value}
onChange={onChange}
placeholder={`Search ${iconCount} icons`}
css={{
width: '100%',
height: 40,
padding: `0 ${theme.space[4]} 0 36px`,
fontFamily: 'inherit',
fontSize: theme.fontSizes[0],
border: 0,
outline: 0,
}}
/>
</div>
)
}
export default SearchInput

View File

@@ -0,0 +1,21 @@
/**
* Converts string to camelcase
*
* @param {string} string
*/
export const toCamelCase = (string: string) =>
string.replace(/^([A-Z])|[\s-_]+(\w)/g, (match, p1, p2) =>
p2 ? p2.toUpperCase() : p1.toLowerCase(),
);
/**
* Converts string to PascalCase
*
* @param {string} string
*/
export const toPascalCase = (string: string) => {
const camelCase = toCamelCase(string);
return camelCase.charAt(0).toUpperCase() + camelCase.slice(1);
};

View File

@@ -0,0 +1,9 @@
figma.showUI(__html__, { width: 300, height: 400 })
figma.ui.onmessage = ({name, svg}) => {
const icon = figma.createNodeFromSvg(svg)
icon.name = name
icon.x = figma.viewport.center.x
icon.y = figma.viewport.center.y
figma.currentPage.selection = [icon]
}

View File

@@ -0,0 +1,8 @@
export default {
space: [0, 4, 8, 12, 16],
fontSizes: [12, 14, 16],
colors: {
blue: '#18a0fb',
},
radii: [0, 2],
}

View File

@@ -0,0 +1,4 @@
declare module 'lucide-react';
declare module 'lucide';
declare module 'lucide/icons';
declare module 'lucide/build/icons';

View File

@@ -0,0 +1,10 @@
@font-face {
font-family: 'Inter';
font-style: normal;
font-weight: 400;
font-display: swap;
src: url('https://rsms.me/inter/font-files/Inter-Regular.woff2?v=3.9')
format('woff2'),
url('https://rsms.me/inter/font-files/Inter-Regular.woff?v=3.9')
format('woff');
}

View File

@@ -0,0 +1 @@
<div id="root"></div>

View File

@@ -0,0 +1,82 @@
import { Global, jsx } from '@emotion/core'
import { version } from '../package.json'
import React, { useMemo } from 'react'
import ReactDOM from 'react-dom'
import IconButton from './components/icon-button'
import SearchInput from './components/search-input'
import theme from './theme'
import './ui.css'
import tags from '../../../tags.json'
import * as iconComponents from 'lucide-react'
import { toPascalCase } from './helpers/naming';
import useSearch from '../../../site/src/lib/useSearch';
declare var ICONS: [];
function App() {
const [query, setQuery] = React.useState('')
const icons = ICONS.map(name => {
const componentName = toPascalCase(name);
return {
name,
tags: tags[name] || [],
component: iconComponents[componentName] || null
}
}).filter(({component}) => !!component)
const searchResults = useMemo(() => useSearch(icons, query), [icons, query])
return (
<div>
<Global
styles={{ body: { margin: 0, fontFamily: 'Inter, sans-serif' } }}
/>
<SearchInput
value={query}
iconCount={icons.length}
onChange={event => setQuery(event.target.value)}
css={{
position: 'sticky',
top: 0,
borderBottom: '1px solid #e5e5e5',
backfaceVisibility: 'hidden'
}}
/>
<div css={{ padding: theme.space[2] }}>
<div
css={{
display: 'grid',
gridTemplateColumns: 'repeat(6, 1fr)',
gridGap: theme.space[1],
}}
>
{searchResults.map(({name, component: Icon} :any) => (
<IconButton
name={name}
key={name}
component={Icon}
/>
))}
</div>
<div
css={{
marginTop: theme.space[2],
padding: theme.space[2],
fontSize: theme.fontSizes[0],
color: 'rgba(0, 0, 0, 0.5)',
}}
>
<a
href="https://lucide.dev"
target="_blank"
css={{ color: 'inherit' }}
>
Lucide v{version}
</a>
</div>
</div>
</div>
)
}
ReactDOM.render(<App />, document.getElementById('root'))

View File

@@ -0,0 +1,12 @@
{
"compilerOptions": {
"esModuleInterop": true,
"lib": ["dom", "esnext"],
"jsx": "react",
"jsxFactory": "jsx",
"resolveJsonModule": true,
"strict": true,
"allowJs": true,
},
"exclude": ["node_modules"],
}

View File

@@ -0,0 +1,48 @@
const fs = require('fs');
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const HtmlWebpackInlineSourcePlugin = require('html-webpack-inline-source-plugin');
const webpack = require('webpack');
module.exports = (env, argv) => ({
// This is necessary because Figma's 'eval' works differently than normal eval
devtool: argv.mode === 'production' ? false : 'inline-source-map',
entry: {
ui: './src/ui.tsx',
main: './src/main.ts',
},
output: {
filename: '[name].js',
path: path.resolve(__dirname, 'build'),
},
module: {
rules: [
{
test: /\.tsx?$/,
use: 'ts-loader',
exclude: /node_modules/,
},
{
test: /\.css$/,
loader: [{ loader: 'style-loader' }, { loader: 'css-loader' }],
},
],
},
resolve: {
extensions: ['.tsx', '.ts', '.js'],
},
plugins: [
new webpack.DefinePlugin({
ICONS: JSON.stringify(
fs.readdirSync(path.join(process.cwd(), '../../icons')).map(name => name.split('.')[0]),
),
}),
new HtmlWebpackPlugin({
template: './src/ui.html',
filename: 'ui.html',
inlineSource: '.(js)$',
chunks: ['ui'],
}),
new HtmlWebpackInlineSourcePlugin(),
],
});

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,15 @@
ISC License
Copyright (c) 2020, Lucide Contributors
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

View File

@@ -1,6 +1,8 @@
# Lucide React
Use the lucide icon library in you react app.
Implementation of the lucide icon library for react applications.
> What is lucide? Read it [here](https://github.com/lucide-icons/lucide#what-is-lucide).
## Installation

View File

@@ -1,3 +1,6 @@
const mainConfig = require('../../babel.config');
module.exports = {
presets: ['react-app'],
env: mainConfig.env,
};

View File

@@ -3,9 +3,6 @@ module.exports = {
roots: ['<rootDir>/src/', '<rootDir>/tests/'],
moduleFileExtensions: ['js'],
transformIgnorePatterns: [`/node_modules`],
moduleNameMapper: {
'^@/(.*)$': '<rootDir>/src/$1',
},
transform: {
'^.+\\.js$': 'babel-jest',
},

View File

@@ -1,7 +1,7 @@
{
"name": "lucide-react",
"description": "Lucide React package, Lucide is a community-run fork of Feather Icons, open for anyone to contribute icons.",
"version": "0.13.0",
"version": "0.14.1",
"license": "ISC",
"homepage": "https://lucide.dev",
"bugs": "https://github.com/lucide-icons/lucide/issues",
@@ -16,12 +16,13 @@
"main:umd": "dist/umd/lucide-react.js",
"module": "dist/esm/lucide-react.js",
"unpkg": "dist/umd/lucide-react.min.js",
"typings": "dist/lucide-react.d.ts",
"scripts": {
"build": "yarn clean && yarn build:move && yarn build:icons && yarn build:es && yarn build:bundles",
"clean": "rm -rf dist && rm -rf build",
"build:move": "cp -av src build",
"build:icons": "yarn --cwd ../../ build:icons --output=../packages/lucide-react/build --templateSrc=../packages/lucide-react/scripts/exportTemplate --camelizeAttrs --noDefaultAttrs --renderUniqueKey",
"build:es": "yarn --cwd ../../ babel packages/lucide-react/build -d packages/lucide-react/dist/esm",
"build": "yarn clean && yarn build:icons && yarn build:es && yarn build:types && yarn build:bundles",
"clean": "rm -rf dist && rm -rf ./src/icons/*.js",
"build:icons": "yarn --cwd ../../ build:icons --output=../packages/lucide-react/src --templateSrc=../packages/lucide-react/scripts/exportTemplate --renderUniqueKey",
"build:es": "yarn --cwd ../../ babel packages/lucide-react/src -d packages/lucide-react/dist/esm",
"build:types": "yarn --cwd ../../ babel-node packages/lucide-react/scripts/buildTypes.js",
"build:bundles": "yarn --cwd ../../ rollup -c packages/lucide-react/rollup.config.js",
"test": "jest"
},

View File

@@ -1,11 +1,11 @@
const plugins = require('../../rollup.plugins');
const pkg = require('./package.json');
import plugins from '../../rollup.plugins';
import pkg from './package.json';
const packageName = 'LucideReact';
const outputFileName = 'lucide-react';
const rootDir = 'packages/lucide-react'; // It runs from the root
const outputDir = `${rootDir}/dist`;
const inputs = [`${rootDir}/build/lucide-react.js`];
const inputs = [`${rootDir}/src/lucide-react.js`];
const bundles = [
{
format: 'umd',
@@ -30,7 +30,7 @@ const configs = bundles
inputs.map(input => ({
input,
plugins: plugins(pkg, minify),
external: ['react', 'prop-types'],
external: ['react', 'prop-types', 'lucide'],
output: {
name: packageName,
file: `${outputDir}/${format}/${outputFileName}${minify ? '.min' : ''}.js`,
@@ -39,6 +39,7 @@ const configs = bundles
globals: {
react: 'react',
'prop-types': 'PropTypes',
lucide: 'lucide',
},
},
})),

View File

@@ -0,0 +1,44 @@
import path from 'path';
import {
writeFile,
readSvgDirectory,
resetFile,
toPascalCase,
appendFile,
} from '../../../scripts/helpers';
const srcDirectory = path.join(__dirname, '../dist');
// Declare type definitions
const typeDefinitions = `\
/// <reference types="react" />
import { SVGAttributes } from 'react'
// Create interface extending SVGAttributes
export interface LucideProps extends Partial<React.SVGProps<SVGSVGElement>> {
color?: string
size?: string | number
stroke?: string | number
strokeWidth?: string | number
}
// Generated icons
`;
const ICONS_DIR = path.resolve(__dirname, '../../../icons');
const TYPES_FILE = 'lucide-react.d.ts';
resetFile(TYPES_FILE, srcDirectory);
writeFile(typeDefinitions, TYPES_FILE, srcDirectory);
const svgFiles = readSvgDirectory(ICONS_DIR);
svgFiles.forEach(svgFile => {
const iconName = path.basename(svgFile, '.svg');
const componentName = toPascalCase(iconName);
const exportTypeString = `export declare const ${componentName}: (props: LucideProps) => JSX.Element;\n`;
appendFile(exportTypeString, TYPES_FILE, srcDirectory);
});
console.log(`Generated ${TYPES_FILE} file with`, svgFiles.length, 'icons');

View File

@@ -1,8 +1,7 @@
export default ({ componentName, node }) => `
export default ({ componentName, children }) => `
import createReactComponent from '../createReactComponent';
import defaultAttributes from '../defaultAttributes';
const ${componentName} = createReactComponent('${componentName}', ['svg', defaultAttributes, ${node}]);
const ${componentName} = createReactComponent('${componentName}', ${JSON.stringify(children)});
export default ${componentName};
`;

View File

@@ -1,28 +1,29 @@
import { forwardRef, createElement } from 'react';
import PropTypes from 'prop-types';
import defaultAttributes from './defaultAttributes';
export default (iconName, [tag, attrs, children]) => {
export default (iconName, iconNode) => {
const Component = forwardRef(
({ color = 'currentColor', size = 24, strokeWidth = 2, ...rest }, ref) =>
createElement(
tag,
'svg',
{
ref,
...attrs,
...defaultAttributes,
width: size,
height: size,
stroke: color,
strokeWidth,
...rest,
},
children.map(([childTag, childAttrs]) => createElement(childTag, childAttrs)),
iconNode.map(([tag, attrs]) => createElement(tag, attrs)),
),
);
Component.propTypes = {
color: PropTypes.string,
size: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
width: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
strokeWidth: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
};
Component.displayName = `${iconName}`;

View File

@@ -0,0 +1 @@
Folder for generated icons

View File

@@ -1,5 +0,0 @@
/*
Icons exports.
Will be generated
*/

View File

@@ -1,6 +1,6 @@
import React from 'react';
import renderer from 'react-test-renderer';
import { Grid } from '..'
import { Grid } from '../src/icons'
describe('Using lucide icon components', () => {
it('should render an component', () => {

View File

@@ -0,0 +1,15 @@
ISC License
Copyright (c) 2020, Lucide Contributors
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

View File

@@ -1,6 +1,8 @@
# Lucide Vue
Use the lucide icon library in you Vue app.
Implementation of the lucide icon library for Vue applications.
> What is lucide? Read it [here](https://github.com/lucide-icons/lucide#what-is-lucide).
## Installation

View File

@@ -7,7 +7,7 @@ module.exports = {
'^.+\\.vue$': 'vue-jest',
},
transformIgnorePatterns: [`/node_modules`],
snapshotSerializers: ['<rootDir>/node_modules/jest-serializer-vue'],
snapshotSerializers: ['jest-serializer-vue'],
moduleNameMapper: {
'^@/(.*)$': '<rootDir>/src/$1',
},

View File

@@ -1,6 +1,6 @@
{
"name": "lucide-vue",
"version": "0.13.0-beta.1",
"version": "0.14.0",
"author": "Eric Fennis",
"description": "Lucide Vue Package",
"license": "ISC",
@@ -21,19 +21,16 @@
"vue": "^2.6.12"
},
"scripts": {
"build": "yarn clean && yarn build:move && yarn build:icons && yarn build:es && yarn build:bundles",
"clean": "rm -rf dist && rm -rf build",
"build:move": "cp -av src build",
"build:icons": "yarn --cwd ../../ build:icons --output=../packages/lucide-vue/build --templateSrc=../packages/lucide-vue/scripts/exportTemplate --noDefaultAttrs",
"build:es": "yarn --cwd ../../ babel packages/lucide-vue/build -d packages/lucide-vue/dist/esm",
"build": "yarn clean && yarn build:icons && yarn build:es && yarn build:bundles",
"clean": "rm -rf dist && rm -rf ./src/icons/*.js",
"build:icons": "yarn --cwd ../../ build:icons --output=../packages/lucide-vue/src --templateSrc=../packages/lucide-vue/scripts/exportTemplate",
"build:es": "yarn --cwd ../../ babel packages/lucide-vue/src -d packages/lucide-vue/dist/esm",
"build:bundles": "yarn --cwd ../../ rollup -c packages/lucide-vue/rollup.config.js",
"test": "jest",
"test:watch": "jest --watchAll"
},
"devDependencies": {
"@vue/test-utils": "^1.1.2",
"babel-jest": "^26.6.3",
"jest": "^26.6.3",
"jest-serializer-vue": "^2.0.2",
"vue-jest": "^3.0.7",
"vue-template-compiler": "^2.6.12"

View File

@@ -1,11 +1,11 @@
const plugins = require('../../rollup.plugins');
const pkg = require('./package.json');
import plugins from '../../rollup.plugins';
import pkg from './package.json';
const packageName = 'LucideVue';
const outputFileName = 'lucide-vue';
const rootDir = 'packages/lucide-vue'; // It runs from the root
const outputDir = `${rootDir}/dist`;
const inputs = [`${rootDir}/build/lucide-vue.js`];
const inputs = [`${rootDir}/src/lucide-vue.js`];
const bundles = [
{
format: 'umd',

View File

@@ -1,8 +1,7 @@
export default ({ componentName, node }) => `
export default ({ componentName, children }) => `
import createVueComponent from '../createVueComponent';
import defaultAttributes from '../defaultAttributes';
const ${componentName} = createVueComponent('${componentName}Icon', ['svg', defaultAttributes, ${node}]);
const ${componentName} = createVueComponent('${componentName}Icon', ${JSON.stringify(children)});
export default ${componentName};
`;

View File

@@ -1,4 +1,6 @@
export default (iconName, [tag, defaultAttrs, children]) => ({
import defaultAttributes from './defaultAttributes';
export default (iconName, iconNode) => ({
name: iconName,
functional: true,
props: {
@@ -27,13 +29,13 @@ export default (iconName, [tag, defaultAttrs, children]) => ({
},
) {
return createElement(
tag,
'svg',
{
// eslint-disable-next-line prettier/prettier
class: [defaultClass, data.class, data.staticClass, data.attrs && data.attrs.class].filter(Boolean),
style: [data.style, data.staticStyle, data.attrs && data.attrs.style].filter(Boolean),
attrs: {
...defaultAttrs,
...defaultAttributes,
width: size,
height: size,
stroke: color,
@@ -41,7 +43,7 @@ export default (iconName, [tag, defaultAttrs, children]) => ({
...data.attrs,
},
},
children.map(([childTag, childAttrs]) => createElement(childTag, { attrs: childAttrs })),
iconNode.map(([tag, attrs]) => createElement(tag, { attrs })),
);
},
});

View File

@@ -0,0 +1 @@
Folder for generated icons

View File

@@ -1,5 +0,0 @@
/*
Icons exports.
Will be generated
*/

View File

@@ -1,5 +1,5 @@
import { mount } from '@vue/test-utils'
import { Smile } from '..'
import { Smile } from '../src/icons'
describe('Using lucide icon components', () => {
it('should render an component', () => {

1
packages/lucide/.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
src/icons/*.js

View File

@@ -0,0 +1,10 @@
stats
node_modules
tests
scripts
build
src
babel.config.js
jest.config.js
rollup.config.js
yarn.error.log

15
packages/lucide/LICENSE Normal file
View File

@@ -0,0 +1,15 @@
ISC License
Copyright (c) 2020, Lucide Contributors
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

120
packages/lucide/README.md Normal file
View File

@@ -0,0 +1,120 @@
# Lucide
Implementation of the lucide icon library for web applications.
## Installation
### Package Managers
``` bash
npm install lucide
#or
yarn 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>
```
## Usage
### With unpkg
Here is a complete example with unpkg
```html
<!DOCTYPE html>
<body>
<i icon-name="volume-2" class="my-class"></i>
<i icon-name="x"></i>
<i icon-name="menu"></i>
<script src="https://unpkg.com/lucide@latest"></script>
<script>
lucide.createIcons();
</script>
</body>
```
### With ESModules
To reduce bundle size, lucide is built to be fully treeshakable.
The `createIcons` function will search for HTMLElements with the attribute `icon-name` and replace it with the svg from the given icon name.
```html
<!-- Your HTML file -->
<i icon-name="menu"></i>
```
```js
import { createIcons, icons } from 'lucide';
// Caution, this will import all the icons and bundle them.
createIcons({icons});
// Recommended way, to include only the icons you need.
import { createIcons, Menu, ArrowRight, Globe } from 'lucide';
createIcons({
icons: {
Menu,
ArrowRight,
Globe,
},
});
```
#### Additional Options
In the `createIcons` function you can pass some extra parameters to adjust the `nameAttr` or add custom attributes like for example classes.
Here is a full example:
```js
import { createIcons } from 'lucide';
createIcons({
attrs: {
class: ['my-custom-class', 'icon'],
'stroke-width': 1,
stroke: '#333',
},
nameAttr: 'icon-name', // attribute for the icon name.
});
```
#### Treeshake the library, only use the icons you use
```js
import { createIcons, Menu, ArrowRight, Globe } from 'lucide';
createIcons({
icons: {
Menu,
ArrowRight,
Globe,
},
});
```
#### Custom Element binding
```js
import { createElement, Menu } from 'lucide';
const menuIcon = createElement(Menu); // Returns HTMLElement (svg)
// set custom attributes with browser native functions
menuIcon.setAttribute('stroke', '#333');
menuIcon.classList.add('my-icon-class');
// Append HTMLElement in webpage
const myApp = document.getElementById('app');
myApp.appendChild(menuIcon);
```

View File

@@ -0,0 +1,14 @@
const mainConfig = require('../../babel.config');
module.exports = {
presets: [
[
'@babel/env',
{
loose: true,
modules: false,
},
],
],
env: mainConfig.env,
};

View File

@@ -5,9 +5,6 @@ module.exports = {
roots: ['<rootDir>/src/', '<rootDir>/tests/'],
moduleFileExtensions: ['js'],
transformIgnorePatterns: [`/node_modules/(?!${esModules})`],
moduleNameMapper: {
'^@/(.*)$': '<rootDir>/src/$1',
},
transform: {
'^.+\\.js$': 'babel-jest',
},

View File

@@ -0,0 +1,30 @@
{
"name": "lucide",
"description": "Lucide is a community-run fork of Feather Icons, open for anyone to contribute icons.",
"version": "0.14.0",
"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"
},
"amdName": "lucide",
"source": "build/lucide.js",
"main": "dist/cjs/lucide.js",
"main:umd": "dist/umd/lucide.js",
"module": "dist/esm/lucide.js",
"unpkg": "dist/umd/lucide.min.js",
"typings": "dist/lucide.d.ts",
"sideEffects": false,
"scripts": {
"build": "yarn clean && yarn build:icons && yarn build:es && yarn build:types && yarn build:bundles",
"clean": "rm -rf dist && rm -rf ./src/icons/*.js",
"build:icons": "yarn --cwd ../../ build:icons --output=../packages/lucide/src",
"build:es": "babel src -d dist/esm",
"build:types": "yarn --cwd ../../ babel-node packages/lucide/scripts/buildTypes.js",
"build:bundles": "rollup -c rollup.config.js",
"test": "jest"
}
}

View File

@@ -1,9 +1,9 @@
const plugins = require('./rollup.plugins');
const pkg = require('./package.json');
import plugins from '../../rollup.plugins';
import pkg from './package.json';
const outputFileName = pkg.name;
const outputDir = 'dist';
const inputs = ['build/lucide.js'];
const inputs = ['src/lucide.js'];
const bundles = [
{
format: 'umd',
@@ -38,4 +38,4 @@ const configs = bundles
)
.flat();
module.exports = configs;
export default configs;

View File

@@ -0,0 +1,37 @@
import path from 'path';
import { readSvgDirectory, resetFile, appendFile, toPascalCase } from '../../../scripts/helpers';
const TARGET_DIR = path.join(__dirname, '../dist');
const ICONS_DIR = path.resolve(__dirname, '../../../icons');
const TYPES_FILE_NAME = 'lucide.d.ts';
// Generates header of d.ts file include some types and functions
const typeDefinitions = `\
export type IconName = string;
export type IconNode = readonly [tag: string, object:SVGProps<SVGSVGElement>, children:IconNode?];
export type IconsObj = { [IconName]: IconNode }
export interface Attributes extends Partial<Props<Element>> {}
export function createElement(icon: IconNode): SVGSVGElement;
export function createIcons({ icons: IconsObj, nameAttr: string = 'icon-name', attrs: Attributes = {} }): VoidFunction;
export declare const icons: IconsObj;
// Generated icons
`;
resetFile(TYPES_FILE_NAME, TARGET_DIR);
appendFile(typeDefinitions, TYPES_FILE_NAME, TARGET_DIR);
const svgFiles = readSvgDirectory(ICONS_DIR);
svgFiles.forEach(svgFile => {
const nameSvg = path.basename(svgFile, '.svg');
const namePascal = toPascalCase(nameSvg);
appendFile(`export declare const ${namePascal}: IconNode;\n`, TYPES_FILE_NAME, TARGET_DIR);
});
console.log(`Generated ${TYPES_FILE_NAME} file with`, svgFiles.length, 'icons');

View File

@@ -5,7 +5,7 @@ export default {
viewBox: '0 0 24 24',
fill: 'none',
stroke: 'currentColor',
strokeWidth: 2,
strokeLinecap: 'round',
strokeLinejoin: 'round',
'stroke-width': 2,
'stroke-linecap': 'round',
'stroke-linejoin': 'round',
};

View File

@@ -0,0 +1 @@
Folder for generated icons

View File

@@ -1,5 +1,5 @@
import replaceElement from './replaceElement';
import * as allIcons from './icons/index';
import * as allIcons from './icons';
/**
* Replaces all elements with matching nameAttr with the defined icons
@@ -34,4 +34,4 @@ export { default as createElement } from './createElement';
Icons exports.
*/
export { allIcons as icons };
export * from './icons/index';
export * from './icons';

View File

@@ -17,6 +17,7 @@ export const getAttrs = element =>
* @returns {Array}
*/
export const getClassNames = attrs => {
if (typeof attrs === 'string') return attrs;
if (!attrs || !attrs.class) return '';
if (attrs.class && typeof attrs.class === 'string') {
return attrs.class.split(' ');
@@ -38,6 +39,7 @@ export const combineClassNames = arrayOfClassnames => {
return classNameArray
.map(classItem => classItem.trim())
.filter(Boolean)
.filter((value, index, self) => self.indexOf(value) === index)
.join(' ');
};
@@ -63,23 +65,21 @@ export default (element, { nameAttr, icons, attrs }) => {
}
const elementAttrs = getAttrs(element);
const [tag, iconAttributes, children] = iconNode;
const [, iconAttrs] = iconNode;
const allAttrs = {
...iconAttrs,
const iconAttrs = {
...iconAttributes,
'icon-name': iconName,
...attrs,
};
iconNode[1] = { ...allAttrs };
const classNames = combineClassNames([iconAttrs, elementAttrs, attrs]);
const classNames = combineClassNames(['lucide', elementAttrs, attrs]);
if (classNames) {
iconNode[1].class = classNames;
iconAttrs.class = classNames;
}
const svgElement = createElement(iconNode);
const svgElement = createElement([tag, iconAttrs, children]);
return element.parentNode.replaceChild(svgElement, element);
};

View File

@@ -0,0 +1,5 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`createIcons should add custom attributes 1`] = `"<svg xmlns=\\"http://www.w3.org/2000/svg\\" width=\\"24\\" height=\\"24\\" viewBox=\\"0 0 24 24\\" fill=\\"black\\" stroke=\\"currentColor\\" stroke-width=\\"2\\" stroke-linecap=\\"round\\" stroke-linejoin=\\"round\\" icon-name=\\"volume-2\\" class=\\"lucide icon custom-class\\"><polygon points=\\"11 5 6 9 2 9 2 15 6 15 11 19 11 5\\"></polygon><path d=\\"M19.07 4.93a10 10 0 010 14.14M15.54 8.46a5 5 0 010 7.07\\"></path></svg>"`;
exports[`createIcons should read elements from DOM and replace it with icons 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\\" icon-name=\\"volume-2\\" class=\\"lucide\\"><polygon points=\\"11 5 6 9 2 9 2 15 6 15 11 19 11 5\\"></polygon><path d=\\"M19.07 4.93a10 10 0 010 14.14M15.54 8.46a5 5 0 010 7.07\\"></path></svg>"`;

View File

@@ -1,3 +1,3 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`combineClassNames should retuns a string of classNames 1`] = `"item1 item2 item3 item4 item5 item6 item7 item8 item9"`;
exports[`combineClassNames should retuns a string of classNames 1`] = `"item item1 item2 item3 item4 item5 item6 item7 item8 item9"`;

Some files were not shown because too many files have changed in this diff Show More