Compare commits

...

17 Commits

Author SHA1 Message Date
Eric Fennis
a03aa9c58f Rename to japenese yen and add tags (#444)
* bump flutter package version

* Add Folder open icon

Co-authored-by: Jan <72730682+JanTrichter@users.noreply.github.com>

* Rename icon

* update tags

Co-authored-by: Jan <72730682+JanTrichter@users.noreply.github.com>
2021-11-21 21:01:10 +01:00
Eric Fennis
bbd554dd51 Bump up lucide-static version 2021-11-21 21:00:32 +01:00
Eric Fennis
27137d8c7c Fix workflow lucide-static 2021-11-21 20:58:32 +01:00
Eric Fennis
5bba16f432 fix tests 2021-11-21 20:48:06 +01:00
Eric Fennis
bb4f05e6c5 lucide-static (#401)
* Add lucide static

* add render files

* add read scripts

* Add sprite generator

* start with documentation

* Add docs

* adding documentation

* fix build command

* Add some extra static files

* bump version

* Update packages/lucide-static/README.md

Co-authored-by: Kathryn Reeve <67553+BinaryKitten@users.noreply.github.com>

* Fix sprite generation

* update readme

* Add lucide static workflow

* adjust readme

* Add font to release yml

* Temporary turn of new versioning for lucide-static

Co-authored-by: Kathryn Reeve <67553+BinaryKitten@users.noreply.github.com>
2021-11-21 20:27:15 +01:00
Yashu Mittal
6c31ab914a add timer off icon (#309) 2021-11-17 20:18:26 +01:00
SMAH1
f591c86aba Refactoring (#436) 2021-11-17 20:18:12 +01:00
Eric Fennis
8cab99a2ee New Figma Plugin setup (#434)
* Update changes

* Add new ui files

* add new script files

* process

* fix build

* try to fix the worker

* try to implement rollup for figma plugin

* bump flutter package version

* add vite for figma-plugin

* add vite

* add vite

* Fix ext output

* make plugin work!

* Add Folder open icon

Co-authored-by: Jan <72730682+JanTrichter@users.noreply.github.com>

* add new fetcher

* Build new api

* add plugin fetcher

* fix fetch icons

* Fix search

* Fix site build

* update yarn.lock

Co-authored-by: Jan <72730682+JanTrichter@users.noreply.github.com>
2021-11-17 20:12:45 +01:00
Brandon Duffany
ac25cdca38 Add wrap-text icon (#435)
* Add wrap text icon

* Optimize

* Add tags for wrap-text
2021-11-15 07:52:30 +01:00
dependabot[bot]
dca5f0f5a6 Bump dns-packet from 1.3.1 to 1.3.4 (#442)
Bumps [dns-packet](https://github.com/mafintosh/dns-packet) from 1.3.1 to 1.3.4.
- [Release notes](https://github.com/mafintosh/dns-packet/releases)
- [Changelog](https://github.com/mafintosh/dns-packet/blob/master/CHANGELOG.md)
- [Commits](https://github.com/mafintosh/dns-packet/compare/v1.3.1...v1.3.4)

---
updated-dependencies:
- dependency-name: dns-packet
  dependency-type: indirect
...

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-11-14 16:09:34 +01:00
dependabot[bot]
dc988cdf45 Bump tar from 6.1.0 to 6.1.11 (#441)
Bumps [tar](https://github.com/npm/node-tar) from 6.1.0 to 6.1.11.
- [Release notes](https://github.com/npm/node-tar/releases)
- [Changelog](https://github.com/npm/node-tar/blob/main/CHANGELOG.md)
- [Commits](https://github.com/npm/node-tar/compare/v6.1.0...v6.1.11)

---
updated-dependencies:
- dependency-name: tar
  dependency-type: indirect
...

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-11-14 16:07:11 +01:00
dependabot[bot]
326267521d Bump url-parse from 1.5.1 to 1.5.3 (#440)
Bumps [url-parse](https://github.com/unshiftio/url-parse) from 1.5.1 to 1.5.3.
- [Release notes](https://github.com/unshiftio/url-parse/releases)
- [Commits](https://github.com/unshiftio/url-parse/compare/1.5.1...1.5.3)

---
updated-dependencies:
- dependency-name: url-parse
  dependency-type: indirect
...

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-11-14 16:07:02 +01:00
dependabot[bot]
e6253d2455 Bump jszip from 3.6.0 to 3.7.1 (#439)
Bumps [jszip](https://github.com/Stuk/jszip) from 3.6.0 to 3.7.1.
- [Release notes](https://github.com/Stuk/jszip/releases)
- [Changelog](https://github.com/Stuk/jszip/blob/master/CHANGES.md)
- [Commits](https://github.com/Stuk/jszip/compare/v3.6.0...v3.7.1)

---
updated-dependencies:
- dependency-name: jszip
  dependency-type: indirect
...

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-11-14 16:06:52 +01:00
SMAH1
fa55b04fa0 Use 'angular build workflow' in Windows (#433) 2021-11-14 15:50:03 +01:00
SMAH1
eded6e0db2 Support Angular version 11 or higher (#432) 2021-11-14 15:48:50 +01:00
Eric Fennis
1f9a3b6a8d Add folder-open icon (#429)
* bump flutter package version

* Add Folder open icon

Co-authored-by: Jan <72730682+JanTrichter@users.noreply.github.com>

Co-authored-by: Jan <72730682+JanTrichter@users.noreply.github.com>
2021-11-09 20:32:31 +01:00
Yashu Mittal
ee3f9bf92d create wand icon (#351)
* create wand icon

* Update wand.svg

Co-authored-by: Eric Fennis <eric.fennis@gmail.com>
2021-10-23 12:48:09 +02:00
64 changed files with 3866 additions and 6835 deletions

View File

@@ -37,6 +37,7 @@ jobs:
with:
node-version: "14"
cache: yarn
cache-dependency-path: 'yarn.lock'
- name: Install dependencies
run: yarn --prefer-offline
@@ -237,6 +238,42 @@ jobs:
name: lucide-preact-package-json
path: packages/lucide-preact/package.json
lucide-static:
if: github.repository == 'lucide-icons/lucide'
runs-on: ubuntu-latest
needs: [pre-build, lucide-font]
steps:
- uses: actions/checkout@v2
- uses: actions/download-artifact@v2
- uses: actions/setup-node@v2.4.0
with:
node-version: "14"
cache: yarn
- name: Install dependencies
run: yarn --prefer-offline
- name: Set Auth Token
run: npm config set //registry.npmjs.org/:_authToken ${{ secrets.NPM_TOKEN }}
# - name: Set new version
# run: yarn workspace lucide-static version --new-version ${{ needs.pre-build.outputs.VERSION }} --no-git-tag-version
- name: Move Font
run: cp -r lucide-font packages/lucide-static/font
- name: Build
run: yarn workspace lucide-static build
- name: Publish
run: yarn workspace lucide-static publish
- name: Upload package.json
uses: actions/upload-artifact@v2
with:
name: lucide-static-package-json
path: packages/lucide-static/package.json
lucide-font:
if: github.repository == 'lucide-icons/lucide'
runs-on: ubuntu-latest
@@ -277,27 +314,14 @@ jobs:
- name: Build Icon Font
run: |
mkdir build
list=(-200 -300 "" -500 -600)
command=''
for name in "${list[@]}"
do
subcommand="(yarn build:outline-icons --outputDir=converted_icons${name} && fontcustom compile "./converted_icons${name}" -h -n "lucide${name}" -o ./build -F)"
if [ -z "$command" ]
then
command="$subcommand";
else
command="$command & $subcommand";
fi
done
eval $command
mkdir lucide-font
yarn build:outline-icons --outputDir=converted_icons && fontcustom compile "./converted_icons" -h -n "lucide" -o ./lucide-font -F
- name: "Upload to Artifacts"
uses: actions/upload-artifact@v1
with:
name: lucide-font
path: build
path: lucide-font
lucide-flutter:
if: github.repository == 'lucide-icons/lucide'

View File

@@ -9,9 +9,9 @@
stroke-linecap="round"
stroke-linejoin="round"
>
<path d="M19.94 14A8 8 0 0 0 10 5.25m8.13 12.89A8 8 0 1 1 6.87 6.86" />
<path d="m22 6-3-3" />
<path d="m6 19-2 2" />
<path d="m2 2 20 20" />
<path d="M4 4 2 6" />
<path d="M19.94 14A8 8 0 0010 5.25m8.13 12.89A8 8 0 116.87 6.86" />
<path d="M22 6l-3-3" />
<path d="M6 19l-2 2" />
<path d="M2 2l20 20" />
<path d="M4 4L2 6" />
</svg>

Before

Width:  |  Height:  |  Size: 382 B

After

Width:  |  Height:  |  Size: 380 B

View File

@@ -10,5 +10,5 @@
stroke-linejoin="round"
>
<polyline points="17 18 11 12 17 6" />
<path d="M7 6V18" />
<path d="M7 6v12" />
</svg>

Before

Width:  |  Height:  |  Size: 272 B

After

Width:  |  Height:  |  Size: 272 B

View File

@@ -10,5 +10,5 @@
stroke-linejoin="round"
>
<polyline points="7 18 13 12 7 6" />
<path d="M17 6V18" />
<path d="M17 6v12" />
</svg>

Before

Width:  |  Height:  |  Size: 271 B

After

Width:  |  Height:  |  Size: 271 B

13
icons/folder-open.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="M6 17l2-5h14l-3 8a2 2 0 01-2 1H4a2 2 0 01-2-2V5a2 2 0 012-2h5l2 3h7a2 2 0 012 2v4" />
</svg>

After

Width:  |  Height:  |  Size: 305 B

View File

@@ -1,7 +1,7 @@
<svg
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"

Before

Width:  |  Height:  |  Size: 304 B

After

Width:  |  Height:  |  Size: 304 B

View File

@@ -12,6 +12,6 @@
<path d="M11 12H3" />
<path d="M16 6H3" />
<path d="M16 18H3" />
<path d="M18 9V15" />
<path d="M21 12H15" />
<path d="M18 9v6" />
<path d="M21 12h-6" />
</svg>

Before

Width:  |  Height:  |  Size: 328 B

After

Width:  |  Height:  |  Size: 327 B

View File

@@ -9,7 +9,7 @@
stroke-linecap="round"
stroke-linejoin="round"
>
<path d="M19 5c-1.5 0-2.8 1.4-3 2-3.5-1.5-11-.3-11 5 0 1.8 0 3 2 4.5V20h4v-2h3v2h4v-4c1-.5 1.7-1 2-2h2v-4h-2c0-1-.5-1.5-1-2h0V5Z" />
<path d="M2 9v1c0 1.1.9 2 2 2h1"/>
<path d="M19 5c-1.5 0-2.8 1.4-3 2-3.5-1.5-11-.3-11 5 0 1.8 0 3 2 4.5V20h4v-2h3v2h4v-4c1-.5 1.7-1 2-2h2v-4h-2c0-1-.5-1.5-1-2h0V5z" />
<path d="M2 9v1c0 1.1.9 2 2 2h1" />
<path d="M16 11h0" />
</svg>

Before

Width:  |  Height:  |  Size: 404 B

After

Width:  |  Height:  |  Size: 405 B

16
icons/timer-off.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="M10 2h4" />
<path d="M7.43 7.433A8 8 0 0118.566 18.57M4.582 11A8 8 0 0015 21.419" />
<path d="M2 2l20 20" />
<path d="M12 12v-2" />
</svg>

After

Width:  |  Height:  |  Size: 357 B

21
icons/wand.svg Normal file
View File

@@ -0,0 +1,21 @@
<svg
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path d="M15 4V2" />
<path d="M15 16v-2" />
<path d="M8 9h2" />
<path d="M20 9h2" />
<path d="M17.8 11.8L19 13" />
<path d="M15 9h0" />
<path d="M17.8 6.2L19 5" />
<path d="M3 21l9-9" />
<path d="M12.2 6.2L11 5" />
</svg>

After

Width:  |  Height:  |  Size: 441 B

16
icons/wrap-text.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"
>
<line x1="3" y1="6" x2="21" y2="6" />
<path d="M3 12h15a3 3 0 110 6h-4" />
<polyline points="16 16 14 18 16 20" />
<line x1="3" y1="18" x2="10" y2="18" />
</svg>

After

Width:  |  Height:  |  Size: 371 B

View File

@@ -30,6 +30,7 @@
"lucide-preact": "yarn workspace lucide-preact",
"lucide-vue": "yarn workspace lucide-vue",
"lucide-vue-next": "yarn workspace lucide-vue-next",
"lucide-static": "yarn workspace lucide-static",
"build:icons": "babel-node ./scripts/buildIcons.js --presets @babel/env",
"build:outline-icons": "babel-node ./scripts/outlineSvg.js --presets @babel/env",
"optimize": "babel-node ./scripts/optimizeSvgs.js --presets @babel/env",

View File

@@ -46,6 +46,9 @@ testem.log
.DS_Store
Thumbs.db
#npm-yarn
# npm-yarn
package-lock.json
src/createElement.js
# angular cache
.angular/cache

View File

@@ -23,7 +23,7 @@
],
"scripts": {
"build": "yarn clean && yarn build:icons && yarn build:ng",
"clean": "rm -rf dist && rm -rf ./src/icons/*.ts",
"clean": "npx shx rm -rf dist && npx shx rm -rf ./src/icons/*.ts",
"build:icons": "yarn --cwd ../../ build:icons --output=../packages/lucide-angular/src --templateSrc=../packages/lucide-angular/scripts/exportTemplate --iconFileExtention=.ts --exportFileName=index.ts",
"build:ng": "ng build --prod",
"test:headless": "ng test --no-watch --no-progress --browsers=ChromeHeadlessCI",
@@ -33,35 +33,31 @@
"postinstall": "ngcc"
},
"dependencies": {
"tslib": "^2.0.0"
},
"peerDependencies": {
"@angular/common": "^11.2.6",
"@angular/core": "^11.2.6"
"tslib": "^2.3.1"
},
"devDependencies": {
"@angular-devkit/build-angular": "~0.1102.5",
"@angular/cli": "~11.2.5",
"@angular/common": "~11.2.6",
"@angular/compiler": "~11.2.6",
"@angular/compiler-cli": "~11.2.6",
"@angular/core": "~11.2.6",
"@angular/platform-browser": "~11.2.6",
"@angular/platform-browser-dynamic": "~11.2.6",
"@types/jasmine": "~3.6.0",
"@types/node": "^12.11.1",
"codelyzer": "^6.0.0",
"jasmine-core": "~3.6.0",
"jasmine-spec-reporter": "~5.0.0",
"karma": "~6.1.0",
"@angular/cli": "~11.2.15",
"@angular/common": "~11.2.14",
"@angular/compiler": "~11.2.14",
"@angular/compiler-cli": "~11.2.14",
"@angular/core": "~11.2.14",
"@angular/platform-browser": "~11.2.14",
"@angular/platform-browser-dynamic": "~11.2.14",
"ng-packagr": "^11.2.4",
"@types/jasmine": "~3.10.2",
"@types/node": "^16.11.7",
"codelyzer": "^6.0.2",
"jasmine-core": "~3.10.1",
"jasmine-spec-reporter": "~7.0.0",
"karma": "~6.3.8",
"karma-chrome-launcher": "~3.1.0",
"karma-coverage": "~2.0.3",
"karma-jasmine": "~4.0.0",
"karma-jasmine-html-reporter": "^1.5.0",
"ng-packagr": "^11.0.0",
"karma-jasmine": "~4.0.1",
"karma-jasmine-html-reporter": "^1.7.0",
"protractor": "~7.0.0",
"puppeteer": "^8.0.0",
"ts-node": "~8.3.0",
"ts-node": "~10.4.0",
"tslint": "~6.1.0",
"typescript": "~4.1.5"
}

View File

@@ -1,675 +0,0 @@
// 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>
}

View File

@@ -2,7 +2,16 @@
"name": "Lucide Icons",
"id": "939567362549682242",
"api": "1.0.0",
"ui": "build/ui.html",
"main": "build/main.js",
"editorType": ["figma"]
"editorType": ["figma"],
"main": "dist/assets/main.js",
"ui": {
"interface": "dist/src/interface/interface.html",
"worker": "dist/src/worker/worker.html"
},
"parameterOnly": false,
"parameters": [{
"name": "Icon",
"key": "icon-name",
"description": "Enter the name of the icon you want to insert."
}]
}

View File

@@ -1,27 +1,30 @@
{
"name": "lucide-figma",
"version": "0.15.11",
"license": "ISC",
"private": true,
"main": "build/ui.js",
"license": "ISC",
"main": "src/main.js",
"scripts": {
"build": "webpack --mode=production",
"watch": "webpack --mode=development --watch"
"dev": "vite",
"build": "tsc && rm -rf dist && yarn build:main && yarn build:worker && yarn build:interface",
"build:main": "INPUT=main vite build",
"build:worker": "INPUT=worker vite build",
"build:interface": "INPUT=interface vite build",
"serve": "vite preview"
},
"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.16.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"
"minimist": "^1.2.5",
"react": "^17.0.0",
"react-dom": "^17.0.0"
},
"devDependencies": {
"@figma/plugin-typings": "^1.36.0",
"@types/react": "^17.0.0",
"@types/react-dom": "^17.0.0",
"@vitejs/plugin-react": "^1.0.0",
"typescript": "^4.3.2",
"vite": "^2.6.4",
"vite-plugin-singlefile": "^0.5.1"
}
}

View File

@@ -0,0 +1,68 @@
import iconNodeToSvg from "../helpers/iconNodeToSvg"
export type IconNode = any[]
export type IconName = string
export type Tag = string[]
export interface Tags {
[key:string]: Tag
}
export interface LucideIcons {
version: string
iconNodes: { [key: IconName]: IconNode }
tags: Tags,
svgs: { [key: IconName]: string }
}
export const fetchIcons = async (cachedIcons? : LucideIcons): Promise<LucideIcons> => {
const response = await fetch('https://unpkg.com/lucide-static@latest/package.json')
const packageJson = await response.json();
if(cachedIcons && cachedIcons?.version === packageJson.version) {
return cachedIcons
}
const iconNodesResponse = await fetch(`https://unpkg.com/lucide-static@${packageJson.version}/icon-nodes.json`)
const tagsResponse = await fetch('https://unpkg.com/lucide-static@latest/tags.json')
const iconNodes = await iconNodesResponse.json();
const tags = await tagsResponse.json();
const svgs = Object.keys(iconNodes).reduce((acc : { [key:string]: string}, iconName) => {
acc[iconName] = iconNodeToSvg(iconName, iconNodes[iconName])
return acc
}, {})
const lucideIcons: LucideIcons = {
version: packageJson.version,
tags,
iconNodes,
svgs
}
parent.postMessage({
pluginMessage: {
type: "setCachedIcons",
lucideIcons
}
}, "*")
return lucideIcons
}
export const getIcons = () => new Promise<LucideIcons>(async (resolve, reject)=> {
parent.postMessage({
pluginMessage: {
type: "getCachedIcons",
}
}, "*")
window.onmessage = async (event) => {
if (event.type === 'message' && event?.data?.pluginMessage.type === 'cachedIcons') {
const lucideIcons = await fetchIcons(event?.data?.pluginMessage?.cachedIcons)
resolve(lucideIcons)
}
}
});

View File

@@ -0,0 +1,16 @@
.icon-button {
padding: 8px;
color: var(--color-black);
background: transparent;
border: 0;
border-radius: 2px;
appearance: none;
outline: 0;
&:hover {
background: rgba(0, 0, 0, 0.06);
}
&:focus,
&:active {
box-shadow: inset 0 0 0 2px var(--color-blue);
}
}

View File

@@ -0,0 +1,32 @@
import { renderToString } from 'react-dom/server'
import { FC } from 'react';
import './IconButton.scss'
interface IconButtonProps {
name: string,
component: FC,
}
function IconButton({ name, component: IconComponent }: IconButtonProps) {
const onIconClick = () => {
const svg = renderToString(<IconComponent/>);
parent.postMessage({ pluginMessage: {
type: 'drawIcon',
icon: { name, svg }
}}, '*')
}
return (
<button
key={name}
aria-label={name}
onClick={onIconClick}
className='icon-button'
>
<IconComponent />
</button>
)
}
export default IconButton

View File

@@ -0,0 +1 @@
export { default } from './IconButton'

View File

@@ -0,0 +1,17 @@
.search-input {
.icon {
position: absolute;
top: 0;
left: 0;
padding: 4px;
}
input {
width: 100%;
height: 40px;
padding: 0 16px 0 36px;
font-family: inherit;
font-size: 11px;
border: 0;
outline: 0;
}
}

View File

@@ -0,0 +1,30 @@
import "./SearchInput.scss"
import { ChangeEvent } from "react"
import SearchIcon from "../icons/SearchIcon"
interface SearchInputProps extends React.HTMLProps<HTMLDivElement> {
value: string,
iconCount: number,
onChange: (event: ChangeEvent<HTMLInputElement>) => void
}
function SearchInput({ value, onChange, iconCount, className, ...props }: SearchInputProps) {
return (
<div
className="search-input"
{...props}
>
<SearchIcon className='icon'/>
<input
autoFocus
type="search"
value={value}
onChange={onChange}
placeholder={`Search ${iconCount} icons`}
className="input__field"
/>
</div>
)
}
export default SearchInput

View File

@@ -0,0 +1 @@
export { default } from './SearchInput'

View File

@@ -1,44 +0,0 @@
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

@@ -1,43 +0,0 @@
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,13 @@
import { Tags } from "../api/fetchIcons";
import { Icon } from "../hooks/useSearch";
export default (icons: Icon[], tags: Tags ,query:string) =>
icons.filter(([name]: Icon) => {
const iconTags = tags && tags[name] ? tags[name] : []
return [name, ...iconTags].some(
(item:string) => item
.toLowerCase()
.includes(query)
)
})

View File

@@ -0,0 +1,11 @@
import { createReactComponent } from "lucide-react";
import { createElement } from "react";
import { renderToString } from "react-dom/server";
import { IconNode } from "../api/fetchIcons";
const iconNodeToSvg = (iconName: string, iconNode : IconNode) => {
const IconComponent = createReactComponent(iconName, iconNode)
return renderToString(createElement(IconComponent));
}
export default iconNodeToSvg

View File

@@ -0,0 +1,17 @@
import { IconName, IconNode, Tags } from "../api/fetchIcons";
import filterIcons from "../helpers/filterIcons";
export type Icon = [
name: IconName,
iconNode: IconNode
]
function useSearch(icons: Icon[], tags: Tags ,query: string) {
if(!query) return icons;
const searchString = query.toLowerCase()
return filterIcons(icons, tags, searchString);
}
export default useSearch;

View File

@@ -0,0 +1 @@
<svg fill="none" height="32" viewBox="0 0 32 32" width="32" xmlns="http://www.w3.org/2000/svg"><path clip-rule="evenodd" d="m18.8744 19.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.7072zm1.1256-4.5815c0 2.7614-2.2386 5-5 5s-5-2.2386-5-5 2.2386-5 5-5 5 2.2386 5 5z" fill="#000" fill-rule="evenodd"/></svg>

After

Width:  |  Height:  |  Size: 408 B

View File

@@ -0,0 +1 @@
<svg fill="none" height="32" viewBox="0 0 32 32" width="32" xmlns="http://www.w3.org/2000/svg"><path clip-rule="evenodd" d="m18.3972 18.6046c-.7793.625-1.7687.9988-2.8455.9988-2.5138 0-4.5517-2.0378-4.5517-4.5517 0-2.5138 2.0379-4.5517 4.5517-4.5517 2.5139 0 4.5517 2.0379 4.5517 4.5517 0 1.0769-.3739 2.0664-.999 2.8458l3.2491 3.2492-.7071.7071zm.7062-3.5529c0 1.9616-1.5901 3.5517-3.5517 3.5517-1.9615 0-3.5517-1.5901-3.5517-3.5517 0-1.9615 1.5902-3.5517 3.5517-3.5517 1.9616 0 3.5517 1.5902 3.5517 3.5517z" fill="#000" fill-rule="evenodd"/></svg>

After

Width:  |  Height:  |  Size: 549 B

View File

@@ -0,0 +1,3 @@
<script type="module" src="./interface.tsx"></script>
<div id="root"></div>

View File

@@ -0,0 +1,49 @@
@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');
}
:root {
--color-blue: #18a0fb;
--color-black: #333;
}
body {
font-family: Inter, sans-serif;
font-size: 11px;
margin: 0;
}
.search-input {
position: sticky;
top: 0;
border-bottom: 1px solid #e5e5e5;
backface-visibility: hidden;
}
main {
padding-bottom: 8px;
}
.icon-grid {
display: grid;
grid-template-columns: repeat(6, 1fr);
grid-gap: 8px;
}
footer {
margin-top: 8px;
padding: 8px;
font-size: 12px;
color: rgba(0, 0, 0, 0.5);
.footer-link {
color: inherit;
}
}

View File

@@ -0,0 +1,67 @@
import { useEffect, useMemo, useState } from 'react'
import { createReactComponent } from 'lucide-react'
import ReactDOM from 'react-dom'
import IconButton from '../components/IconButton'
import SearchInput from '../components/SearchInput'
import useSearch, { Icon } from '../hooks/useSearch'
import { getIcons } from '../api/fetchIcons'
import './interface.scss'
function App() {
const [query, setQuery] = useState('')
const [icons, setIcons] = useState<Icon[]>([])
const [tags, setTags] = useState({})
const [version, setVersion ] = useState('')
const searchResults = useMemo(() => useSearch(icons, tags, query), [icons, query])
const getLatestIcons = async () => {
const lucideIcons = await getIcons()
setIcons(Object.entries(lucideIcons.iconNodes))
setTags(lucideIcons.tags)
setVersion(lucideIcons.version)
}
useEffect(() => {
getLatestIcons()
}, [])
if(!icons.length) {
return null
}
return (
<div>
<SearchInput
value={query}
iconCount={icons.length}
onChange={(event) => setQuery(event.target.value)}
/>
<main>
<div className='icon-grid'>
{searchResults.map(([name, iconNode] :any) => (
<IconButton
name={name}
key={name}
component={createReactComponent(name, iconNode)}
/>
))}
</div>
<footer>
<a
href="https://lucide.dev"
target="_blank"
className='footer-link'
>
Lucide v{version}
</a>
</footer>
</main>
</div>
)
}
ReactDOM.render(<App />, document.getElementById('root'))

View File

@@ -1,9 +1,97 @@
figma.showUI(__html__, { width: 300, height: 400 })
import type { LucideIcons } from "./api/fetchIcons";
import filterIcons from "./helpers/filterIcons";
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]
figma.showUI(__uiFiles__.worker, { visible: false })
let cachedIcons: LucideIcons
const setResults = ({result, query, lucideIcons} : { result: SuggestionResults, query: string, lucideIcons: LucideIcons }) => {
const icons = Object.entries(lucideIcons.iconNodes);
const suggestions = filterIcons(icons, lucideIcons.tags, query.toLowerCase()).map(([name]) => ({
name,
icon: lucideIcons.svgs[name]
}))
result.setSuggestions(suggestions)
}
figma.parameters.on('input', async ({ parameters, key, query, result }) => {
if (key === 'icon-name') {
console.log('typ tpy', query);
cachedIcons = await figma.clientStorage.getAsync(`lucide-icons`)
console.log('cachedIcons', cachedIcons);
if(cachedIcons && cachedIcons.iconNodes && cachedIcons.tags) {
setResults({result, query, lucideIcons: cachedIcons})
}
}
})
const drawIcon = ({icon: {name, svg}}: any) => {
const min = 0
const max = 100
const randomPosition = () => Math.floor(Math.random() * (max - min + 1) + min)
const icon = figma.createNodeFromSvg(svg)
icon.name = name
icon.x = Math.round(figma.viewport.center.x + randomPosition())
icon.y = Math.round(figma.viewport.center.y + randomPosition())
figma.currentPage.selection = [icon]
// lock children
icon.children.forEach((vectorNode, key) => {
icon.children[key].locked = true
});
}
const setCachedIcons = async (pluginMessage: any) => {
if(pluginMessage.lucideIcons) {
await figma.clientStorage.setAsync(`lucide-icons`, pluginMessage.lucideIcons)
}
}
const getCachedIcons = async () => {
cachedIcons = await figma.clientStorage.getAsync(`lucide-icons`)
const response = { type: 'cachedIcons' }
if(cachedIcons) {
Object.assign(response, { cachedIcons })
}
figma.ui.postMessage(response)
}
getCachedIcons()
figma.ui.onmessage = (event) => {
console.log(event, 'main');
switch (event.type) {
case "drawIcon":
drawIcon(event)
break;
case "getCachedIcons":
getCachedIcons()
break;
case "setCachedIcons":
setCachedIcons(event)
break;
case "close":
figma.closePlugin()
break;
default:
break;
}
}
figma.on('run', event => {
if(event.parameters) {
figma.ui.postMessage({ type: 'getSvg', iconName: event.parameters['icon-name'], cachedIcons })
} else {
figma.showUI(__uiFiles__.interface, { width: 300, height: 400 })
}
})

View File

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

View File

@@ -1,10 +0,0 @@
@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

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

View File

@@ -1,82 +0,0 @@
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 @@
<script type="module" src="./worker.ts"></script>

View File

@@ -0,0 +1,60 @@
import { fetchIcons, LucideIcons } from "../api/fetchIcons"
import { createReactComponent } from 'lucide-react'
import { renderToString } from 'react-dom/server'
import { createElement } from "react"
const getLatestIcons = async ({ cachedIcons }: any) => {
const lucideIcons = await fetchIcons(cachedIcons)
parent.postMessage({
pluginMessage: {
type: "latestIcons",
lucideIcons,
}
}, "*")
}
const getSvg = async ({ cachedIcons, iconName }: { cachedIcons: LucideIcons, iconName: string }) => {
if (!cachedIcons) {
return;
}
const iconNode = cachedIcons.iconNodes[iconName];
if (iconNode) {
const IconComponent = createReactComponent(iconName, iconNode)
const svg = renderToString(createElement(IconComponent));
parent.postMessage({ pluginMessage: {
type: 'drawIcon',
icon: { name, svg }
}}, '*')
parent.postMessage({ pluginMessage: {
type: 'close',
}}, '*')
}
}
window.onmessage = async (event) => {
if (!event?.data?.pluginMessage) {
return
}
const { pluginMessage } = event.data
switch (pluginMessage.type) {
case "getLatestIcons":
getLatestIcons(pluginMessage)
break;
case "getSvg":
getSvg(pluginMessage)
break;
default:
break;
}
}
console.log('Hello world!')

View File

@@ -1,12 +1,24 @@
{
"compilerOptions": {
"esModuleInterop": true,
"lib": ["dom", "esnext"],
"jsx": "react",
"jsxFactory": "jsx",
"resolveJsonModule": true,
"strict": true,
"target": "ESNext",
"useDefineForClassFields": true,
"lib": ["DOM", "DOM.Iterable", "ESNext"],
"allowJs": true,
"skipLibCheck": true,
"esModuleInterop": false,
"allowSyntheticDefaultImports": true,
"strict": true,
"forceConsistentCasingInFileNames": true,
"module": "ESNext",
"moduleResolution": "Node",
"resolveJsonModule": true,
"isolatedModules": false,
"noEmit": true,
"jsx": "react-jsx",
"typeRoots": [
"./node_modules/@types",
"../../node_modules/@figma"
],
},
"exclude": ["node_modules"],
"include": ["src"]
}

View File

@@ -0,0 +1,40 @@
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
import { viteSingleFile } from "vite-plugin-singlefile"
import { resolve } from 'path'
const entries = {
main: resolve(__dirname, 'src/main.ts'),
interface: resolve(__dirname, './src/interface/interface.html'),
worker: resolve(__dirname, './src/worker/worker.html'),
}
const input = {};
if(process.env['INPUT']) {
const entry = process.env['INPUT'];
input[entry] = entries[entry]
}
// https://vitejs.dev/config/
export default defineConfig({
plugins: [react(), viteSingleFile()],
build: {
target: "esnext",
assetsInlineLimit: 100000000,
chunkSizeWarningLimit: 100000000,
cssCodeSplit: false,
brotliSize: false,
emptyOutDir: false,
rollupOptions: {
input,
inlineDynamicImports: true,
output: {
manualChunks: (chunk) => "all.js",
entryFileNames: `assets/[name].js`,
chunkFileNames: `assets/[name].js`,
assetFileNames: `assets/[name].[ext]`
},
},
},
})

View File

@@ -1,48 +0,0 @@
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

@@ -1,10 +1,16 @@
import path from "path";
import {appendFile, readSvgDirectory, resetFile, toPascalCase, writeFile} from "../../../scripts/helpers";
import path from 'path';
import {
appendFile,
readSvgDirectory,
resetFile,
toPascalCase,
writeFile,
} from '../../../scripts/helpers';
const srcDirectory=path.join(__dirname, "../dist");
const srcDirectory = path.join(__dirname, '../dist');
// Declare type definitions
const typeDefinitions=`\
const typeDefinitions = `\
/// <reference types="react" />
import { SVGAttributes } from 'react'
@@ -15,6 +21,8 @@ export interface LucideProps extends Partial<React.SVGProps<SVGSVGElement>> {
size?: string | number
}
export declare const createReactComponent: (iconName: string, iconNode: any[]) => (props: LucideProps) => JSX.Element;
export type Icon = React.FC<LucideProps>;
// Generated icons

View File

@@ -1 +1,2 @@
export * from './icons';
export { default as createReactComponent } from './createReactComponent';

6
packages/lucide-static/.gitignore vendored Normal file
View File

@@ -0,0 +1,6 @@
icons
lib
sprite.svg
tags.json
icon-nodes.json
font

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

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

@@ -0,0 +1,196 @@
# Lucide Static
This package include the following lucide implementations:
- All svg files
- Javascript library containing strings of svgs.
- Icon fonts
- Svg sprite
> What is lucide? Read it [here](https://github.com/lucide-icons/lucide#what-is-lucide).
## Why lucide-static?
This package is suitable for very specific use cases for example if you want to use icon fonts, svg sprites, normal svgs or Common.js Svg strings in your javascript project.
> ⚠️ It is not recommended to use this package for svg sprites or icon fonts for web pages/applications, for prototyping it is ok. We recommend to bundlers for web applications to make sure you only bundle the used icons from this icon library (Threeshaking). Otherwise it will load all the icons, making you webpage loading slower. Threeshaking is only available in the packages: [lucide](https://github.com/lucide-icons/lucide/tree/master/packages/lucide), [lucide-react](https://github.com/lucide-icons/lucide/tree/master/packages/lucide-react), [lucide-vue](https://github.com/lucide-icons/lucide/tree/master/packages/lucide-vue), [lucide-vue-next](https://github.com/lucide-icons/lucide/tree/master/packages/lucide-vue-next), [lucide-angular](https://github.com/lucide-icons/lucide/tree/master/packages/lucide-angular), [lucide-preact](https://github.com/lucide-icons/lucide/tree/master/packages/lucide-preact)
## Installation
## Package Managers
```sh
yarn add lucide-static
# or
npm install lucide-static
```
### CDN
``` html
<!-- Svg File -->
<img src="https://unpkg.com/lucide-static@latest/icons/home.svg">
<!-- Icon Font -->
<style>
@font-face {
font-family: "LucideIcons";
src: url(https://unpkg.com/lucide-static@latest/font/Lucide.ttf) format("truetype");
}
</style>
```
## Usage
Checkout the [codesandbox examples](https://codesandbox.io/s/using-the-svg-sprite-lz1kk).
### SVG Files
#### Svg file as image
To use it in for example html:
``` html
<!-- Svg File -->
<img src="~lucide-static/icons/home.svg">
```
``` css
.home-icon {
background-image: url(~lucide-static/icons/home.svg)
}
```
Make sure you have the correct webpack loaders to make this work. [url-loader](https://v4.webpack.js.org/loaders/url-loader/)
#### Svg file Inline
You can simply import each svg by targeting `lucide-static/icons/{icon-name}.svg`.
To use svgs in your project you can for example use a [svg loader](https://v4.webpack.js.org/loaders/svg-inline-loader/).
```js
import arrowRightIcon from 'lucide-static/icons/arrow-right'
// return string of a svg
```
### SVG Sprite
You may need additional loader for this.
```html
<!-- Icon Sprite, not recommended for production! -->
<img src="lucide-static/sprite.svg#home">
<!-- or -->
<svg
width="24"
height="24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<use href="#alert-triangle" />
</svg>
<svg>
...sprite svg
</svg>
```
If you'd prefer, you can use CSS to hold your base SVG properties
```css
.lucide-icon {
width: 24px;
height: 24px;
stroke: currentColor;
fill: none;
stroke-width: 2;
stroke-linecap: round;
stroke-linejoin: round;
}
```
and update the svg as follows
```svg
<svg
xmlns="http://www.w3.org/2000/svg"
class="lucide-icon"
>
<use
href="#alert-triangle"
/>
</svg>
<svg>
...sprite svg
</svg>
```
### Icon Font
```css
@import("~lucide-static/font/Lucide.css")
```
```html
<div class="icon-home"></div>
```
### Node.js
To use lucide icons in your Nodejs project you can import each icon as:
```js
const { messageSquare } = require('lucide-static/lib')
```
> Note: Each icon name is in camelCase.
#### Example in node.js project
```js
const express = require('express')
const { messageSquare } = require('lucide-static/lib')
const app = express()
const port = 3000
app.get('/', (req, res) => {
res.send(`
<!DOCTYPE html>
<html>
<head>
<title>Page Title</title>
</head>
<body>
<h1>Lucide Icons</h1>
<p>This is a lucide icon ${messageSquare}</p>
</body>
</html>
`)
})
app.listen(port, () => {
console.log(`Example app listening at http://localhost:${port}`)
})
```
## Contributing
For more info on how to contribute please see the [contribution guidelines](https://github.com/lucide-icons/lucide/blob/master/CONTRIBUTING.md).
Caught a mistake or want to contribute to the documentation? [Edit this page on Github](https://github.com/lucide-icons/lucide/blob/master/README.md)
## Community
Join the community on our [Discord](https://discord.gg/EH6nSts) server!
## 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).

View File

@@ -0,0 +1,24 @@
{
"name": "lucide-static",
"description": "Lucide is a community-run fork of Feather Icons, open for anyone to contribute icons.",
"version": "0.16.19-rc.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"
},
"main": "lib/index.js",
"scripts": {
"move:icons": "cp -r ../../icons icons",
"move:tags": "cp ../../tags.json tags.json",
"build": "yarn clean && yarn move:icons && yarn move:tags && yarn build:lib",
"build:lib": "yarn --cwd ../../ babel-node packages/lucide-static/scripts/buildLib.js",
"clean": "rm -rf lib && rm -rf build && rm -rf icons && rm -f sprite.svg && rm -f tags.json"
},
"devDependencies": {
"prettier": "^2.3.2",
"svgson": "^5.2.1"
}
}

View File

@@ -0,0 +1,47 @@
/* eslint-disable import/no-extraneous-dependencies */
import fs from 'fs';
import path from 'path';
import getArgumentOptions from 'minimist';
import { parseSync } from 'svgson';
// import renderIconsObject from '../../../scripts/render/renderIconsObject';
import { appendFile, readSvgDirectory, toCamelCase } from '../../../scripts/helpers';
import readSvgs from './readSvgs';
import generateSprite from './generateSprite';
import generateIconNodes from './generateIconNodes';
const cliArguments = getArgumentOptions(process.argv.slice(2));
const createDirectory = dir => {
if (!fs.existsSync(dir)) {
fs.mkdirSync(dir);
}
};
const PACKAGE_DIR = path.resolve(__dirname, '../');
const ICONS_DIR = path.join(PACKAGE_DIR, 'icons');
const LIB_DIR = path.join(PACKAGE_DIR, cliArguments.output || 'lib');
const ICON_MODULE_DIR = path.join(LIB_DIR, 'icons');
createDirectory(LIB_DIR);
createDirectory(ICON_MODULE_DIR);
const svgFiles = readSvgDirectory(ICONS_DIR);
const svgs = readSvgs(svgFiles, ICONS_DIR);
svgs.forEach(({ name, contents }) => {
const componentName = toCamelCase(name);
const importString = `module.exports.${componentName} = require('./icons/${name}');\n`;
appendFile(importString, `index.js`, LIB_DIR);
const exportString = `module.exports = \`${contents}\`;\n`;
appendFile(exportString, `${name}.js`, ICON_MODULE_DIR);
});
const parsedSvgs = svgs.map(({ name, contents }) => ({
name,
contents,
parsedSvg: parseSync(contents),
}));
generateSprite(parsedSvgs, PACKAGE_DIR);
generateIconNodes(parsedSvgs, PACKAGE_DIR);

View File

@@ -0,0 +1,13 @@
import { writeFile } from '../../../scripts/helpers';
export default function generateIconNodes(parsedSvgs, packageDir) {
const iconNodes = parsedSvgs.reduce((acc, { name, parsedSvg }) => {
acc[name] = parsedSvg.children.map(({ name, attributes }) => [name, attributes]);
return acc;
}, {});
const iconNodesStringified = JSON.stringify(iconNodes, null, 2);
writeFile(iconNodesStringified, 'icon-nodes.json', packageDir);
}

View File

@@ -0,0 +1,39 @@
/* eslint-disable import/no-extraneous-dependencies */
import { stringify } from 'svgson';
import { format } from 'prettier';
import { appendFile } from '../../../scripts/helpers';
export default function generateSprite(svgs, packageDir) {
const symbols = svgs.map(({ name, parsedSvg }) => ({
name: 'symbol',
type: 'element',
attributes: {
id: name,
},
children: parsedSvg.children,
}));
const spriteSvgObject = {
name: 'svg',
type: 'element',
attributes: {
xmlns: 'http://www.w3.org/2000/svg',
version: '1.1',
},
children: [
{
name: 'defs',
type: 'element',
children: symbols,
},
],
};
const spriteSvg = stringify(spriteSvgObject);
const prettifiedSprite = format(spriteSvg, { parser: 'babel' }).replace(/;/g, '');
const xmlMeta = `<?xml version="1.0" encoding="utf-8"?>\n`;
appendFile(xmlMeta, `sprite.svg`, packageDir);
appendFile(prettifiedSprite, `sprite.svg`, packageDir);
}

View File

@@ -0,0 +1,17 @@
/* eslint-disable import/no-extraneous-dependencies */
import { basename } from 'path';
import { readSvg } from '../../../scripts/helpers';
/**
* Build an object in the format: `{ <name>: <contents> }`.
* @param {string[]} svgFiles - A list of filenames.
* @param {Function} getSvg - A function that returns the contents of an SVG file given a filename.
* @returns {Object}
*/
export default (svgFiles, iconsDirectory) =>
svgFiles.map(svgFile => {
const name = basename(svgFile, '.svg');
const contents = readSvg(svgFile, iconsDirectory);
return { name, contents };
});

View File

@@ -1,6 +1,6 @@
{
"name": "lucide-vue-next",
"version": "0.16.12",
"version": "0.16.18",
"author": "Eric Fennis",
"description": "A Lucide icon library package for Vue 3 applications",
"license": "ISC",
@@ -31,10 +31,10 @@
},
"devDependencies": {
"@vue/compiler-sfc": "^3.0.0",
"@vue/test-utils": "^2.0.0-rc.6",
"@vue/test-utils": "^2.0.0-rc.14",
"jest-serializer-vue": "^2.0.2",
"vue": "3.0.6",
"vue-jest": "^5.0.0-alpha.7"
"vue-jest": "^5.0.0-alpha.10"
},
"peerDependencies": {
"vue": "^3.0.0"

View File

@@ -54,13 +54,9 @@ VueWrapper {
"components": Object {
"transition": Object {
"name": "transition",
"props": undefined,
"render": [Function],
},
"transition-group": Object {
"name": "transition-group",
"props": undefined,
"render": [Function],
},
},
"config": Object {
@@ -107,6 +103,7 @@ VueWrapper {
"componentVM": Object {
"hasOwnProperty": [Function],
},
"isDisabled": [Function],
"rootVM": Object {},
"wrapperElement": <svg
class="lucide-icon my-icon"
@@ -199,13 +196,9 @@ VueWrapper {
"components": Object {
"transition": Object {
"name": "transition",
"props": undefined,
"render": [Function],
},
"transition-group": Object {
"name": "transition-group",
"props": undefined,
"render": [Function],
},
},
"config": Object {
@@ -252,6 +245,7 @@ VueWrapper {
"componentVM": Object {
"hasOwnProperty": [Function],
},
"isDisabled": [Function],
"rootVM": Object {},
"wrapperElement": <svg
class="lucide lucide-smile-icon"
@@ -346,13 +340,9 @@ VueWrapper {
"components": Object {
"transition": Object {
"name": "transition",
"props": undefined,
"render": [Function],
},
"transition-group": Object {
"name": "transition-group",
"props": undefined,
"render": [Function],
},
},
"config": Object {
@@ -399,6 +389,7 @@ VueWrapper {
"componentVM": Object {
"hasOwnProperty": [Function],
},
"isDisabled": [Function],
"rootVM": Object {},
"wrapperElement": <svg
class="lucide lucide-smile-icon"
@@ -492,13 +483,9 @@ VueWrapper {
"components": Object {
"transition": Object {
"name": "transition",
"props": undefined,
"render": [Function],
},
"transition-group": Object {
"name": "transition-group",
"props": undefined,
"render": [Function],
},
},
"config": Object {
@@ -545,6 +532,7 @@ VueWrapper {
"componentVM": Object {
"hasOwnProperty": [Function],
},
"isDisabled": [Function],
"rootVM": Object {},
"wrapperElement": <svg
class="lucide lucide-smile-icon"

View File

@@ -10,9 +10,11 @@ const TYPES_FILE_NAME = 'lucide.d.ts';
// Generates header of d.ts file include some types and functions
const typeDefinitions = `\
declare module 'lucide'
export interface SVGProps extends Partial<SVGElement> ${JSON.stringify(defaultAttributes, null, 2)}
export declare type IconNode = readonly [tag: string, attrs:SVGProps, children?:IconNode];
export declare type IconNodeChild = readonly [string, object];
export declare type IconNode = readonly [tag: string, attrs: SVGProps, children?: IconNodeChild[]];
export declare type CustomAttrs = { [attr:string]: any }
export type Icons = { [key: string]: IconNode }

1
sprite-1.svg Normal file
View File

@@ -0,0 +1 @@
<svg/>

After

Width:  |  Height:  |  Size: 6 B

154
tags.json
View File

@@ -16,6 +16,10 @@
"alarm-clock": [
"morning"
],
"alarm-clock-off": [
"morning",
"turn-off"
],
"alarm-minus": [
"remove"
],
@@ -201,6 +205,12 @@
"create",
"new"
],
"bell-ring": [
"alarm",
"notification",
"sound",
"reminder"
],
"bike": [
"bicycle",
"transport",
@@ -331,12 +341,26 @@
"check-circle": [
"done"
],
"check-circle-2": [
"done"
],
"check-square": [
"done"
],
"chevron-down": [
"arrow"
],
"chevron-first": [
"arrow",
"previous",
"music"
],
"chevron-last": [
"arrow",
"skip",
"next",
"music"
],
"chevron-left": [
"arrow"
],
@@ -389,11 +413,21 @@
"copied",
"pasted"
],
"clipboard-copy": [
"copy",
"paste"
],
"clipboard-list": [
"copy",
"paste",
"tasks"
],
"clipboard-x": [
"copy",
"paste",
"discard",
"remove"
],
"clock": [
"time",
"watch",
@@ -750,6 +784,14 @@
"flag": [
"report"
],
"flag-triangle-left": [
"report",
"timeline"
],
"flag-triangle-right": [
"report",
"timeline"
],
"flame": [
"fire",
"lit"
@@ -773,6 +815,9 @@
"folder-minus": [
"directory"
],
"folder-open": [
"directory"
],
"folder-plus": [
"directory"
],
@@ -783,6 +828,11 @@
"field",
"text"
],
"forward": [
"send",
"share",
"email"
],
"framer": [
"logo",
"design",
@@ -795,6 +845,11 @@
"sad",
"emotion"
],
"function-square": [
"programming",
"code",
"automation"
],
"gamepad": [
"console"
],
@@ -808,6 +863,12 @@
"hammer",
"mallet"
],
"gem": [
"diamond",
"price",
"special",
"present"
],
"ghost": [
"pacman",
"spooky"
@@ -891,6 +952,9 @@
"mouse",
"grab"
],
"hand-metal": [
"rock"
],
"hard-drive": [
"computer",
"server",
@@ -964,6 +1028,9 @@
"add",
"create"
],
"import": [
"save"
],
"inbox": [
"email"
],
@@ -998,7 +1065,7 @@
"oblique",
"text"
],
"jersey-pound": [
"japanese-yen": [
"currency",
"money",
"payment"
@@ -1009,9 +1076,6 @@
"authentication",
"secure"
],
"languages": [
"translate"
],
"landmark": [
"bank",
"building",
@@ -1019,6 +1083,9 @@
"finance",
"money"
],
"languages": [
"translate"
],
"laptop": [
"computer"
],
@@ -1098,6 +1165,14 @@
"todo",
"done"
],
"list-minus": [
"playlist",
"remove",
"song",
"subtract",
"remove",
"delete"
],
"list-ordered": [
"number",
"order"
@@ -1109,14 +1184,6 @@
"track",
"new"
],
"list-minus": [
"playlist",
"remove",
"song",
"subtract",
"remove",
"delete"
],
"list-x": [
"playlist",
"subtract",
@@ -1185,6 +1252,12 @@
"arrows",
"expand"
],
"megaphone": [
"advertisement",
"attention",
"alert",
"notification"
],
"meh": [
"emoji",
"face",
@@ -1410,6 +1483,10 @@
"statistics",
"diagram"
],
"piggy-bank": [
"money",
"savings"
],
"pipette": [
"eye dropper",
"color picker"
@@ -1473,12 +1550,12 @@
"office",
"device"
],
"quote": [
"quotation"
],
"qr-code": [
"barcode"
],
"quote": [
"quotation"
],
"radio": [
"signal"
],
@@ -1512,6 +1589,12 @@
"repeat-1": [
"replay"
],
"reply": [
"email"
],
"reply-all": [
"email"
],
"rewind": [
"music"
],
@@ -1606,6 +1689,12 @@
"gear",
"preferences"
],
"settings-2": [
"cog",
"edit",
"gear",
"preferences"
],
"share": [
"network",
"connections"
@@ -1693,9 +1782,14 @@
"calculate"
],
"skip-back": [
"arrow",
"previous",
"music"
],
"skip-forward": [
"arrow",
"skip",
"next",
"music"
],
"skull": [
@@ -1724,6 +1818,12 @@
"cellphone",
"device"
],
"smartphone-charging": [
"phone",
"cellphone",
"device",
"power"
],
"smile": [
"emoji",
"face",
@@ -1878,6 +1978,16 @@
"timer",
"stopwatch"
],
"timer-off": [
"time",
"timer",
"stopwatch"
],
"timer-reset": [
"time",
"timer",
"stopwatch"
],
"toggle-left": [
"on",
"off",
@@ -2012,6 +2122,10 @@
"verified": [
"check"
],
"vibrate": [
"smartphone",
"notification"
],
"video": [
"camera",
"movie",
@@ -2053,6 +2167,10 @@
"finance",
"pocket"
],
"wand": [
"magic",
"selection"
],
"watch": [
"clock",
"time"
@@ -2074,6 +2192,12 @@
"air",
"blow"
],
"wrap-text": [
"words",
"lines",
"break",
"paragraph"
],
"wrench": [
"tool",
"settings",

4832
yarn.lock

File diff suppressed because it is too large Load Diff