Compare commits
60 Commits
angular-pa
...
context-pr
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
91506784a2 | ||
|
|
5528e13644 | ||
|
|
636ae1d9e0 | ||
|
|
83d95dd0e6 | ||
|
|
0031dc42e7 | ||
|
|
881e733159 | ||
|
|
d58a2e43c6 | ||
|
|
5ecf78bb8a | ||
|
|
aa8f74eb9e | ||
|
|
7327637532 | ||
|
|
05a2315a17 | ||
|
|
ec34048560 | ||
|
|
1f081aa276 | ||
|
|
f8c4b8bb48 | ||
|
|
08bd4b33a0 | ||
|
|
6ec17b17a3 | ||
|
|
2eb29ea0e8 | ||
|
|
9fc85ccd32 | ||
|
|
1863791990 | ||
|
|
afd31b0fa2 | ||
|
|
2f9c69a3e1 | ||
|
|
bf0824d216 | ||
|
|
4f74929c33 | ||
|
|
c9769ccddc | ||
|
|
e5fcd3dc34 | ||
|
|
6c3ab468c8 | ||
|
|
26684bf954 | ||
|
|
1859b37c35 | ||
|
|
b08292951a | ||
|
|
811144de12 | ||
|
|
92881531dd | ||
|
|
048a031bf9 | ||
|
|
6c3a072781 | ||
|
|
1c6a4031bb | ||
|
|
66b72c1db1 | ||
|
|
b1675c4c33 | ||
|
|
758fa4b75f | ||
|
|
7bbb1e1fea | ||
|
|
2517a1e944 | ||
|
|
8771dbdae6 | ||
|
|
1b338ef4c6 | ||
|
|
bad581f640 | ||
|
|
66a95c1368 | ||
|
|
1e0149a827 | ||
|
|
1726441298 | ||
|
|
471bd9b817 | ||
|
|
805785c0e7 | ||
|
|
4281588a4c | ||
|
|
99a3844ce2 | ||
|
|
18d0220de9 | ||
|
|
54c75ac20f | ||
|
|
fb99da99a3 | ||
|
|
3cec076d1a | ||
|
|
3dff23edf4 | ||
|
|
546af67faa | ||
|
|
3dd09434c8 | ||
|
|
3fdbda43c1 | ||
|
|
18c155cda0 | ||
|
|
dc418c7011 | ||
|
|
1d48e8b33a |
@@ -9,9 +9,3 @@ strikethrough
|
||||
touchpad
|
||||
ungroup
|
||||
toc
|
||||
|
||||
# Brands
|
||||
codepen
|
||||
codesandbox
|
||||
dribbble
|
||||
x.com
|
||||
|
||||
9
.github/ISSUE_TEMPLATE/02_bug_report.yml
vendored
@@ -13,19 +13,16 @@ body:
|
||||
description: Which Lucide packages are affected? You may select more than one.
|
||||
options:
|
||||
- label: lucide
|
||||
- label: lucide-angular (old version)
|
||||
- label: '@lucide/angular (new version)'
|
||||
- label: '@lucide/astro'
|
||||
- label: lucide-angular
|
||||
- label: lucide-flutter
|
||||
- label: lucide-preact
|
||||
- label: lucide-react
|
||||
- label: lucide-react-native
|
||||
- label: lucide-solid
|
||||
- label: lucide-static
|
||||
- label: lucide-svelte (old version)
|
||||
- label: '@lucide/svelte (new version)'
|
||||
- label: lucide-svelte
|
||||
- label: lucide-vue
|
||||
- label: lucide-vue-next
|
||||
- label: lucide-astro
|
||||
- label: Figma plugin
|
||||
- label: source/main
|
||||
- label: other/not relevant
|
||||
|
||||
10
.github/ISSUE_TEMPLATE/04_feature_request.yml
vendored
@@ -13,23 +13,19 @@ body:
|
||||
description: Which Lucide project do you wish this feature were added to? You may select more than one.
|
||||
options:
|
||||
- label: lucide
|
||||
- label: lucide-angular (old version)
|
||||
- label: '@lucide/angular (new version)'
|
||||
- label: '@lucide/astro'
|
||||
- label: lucide-angular
|
||||
- label: lucide-flutter
|
||||
- label: lucide-preact
|
||||
- label: lucide-react
|
||||
- label: lucide-react-native
|
||||
- label: lucide-solid
|
||||
- label: lucide-static
|
||||
- label: lucide-svelte (old version)
|
||||
- label: '@lucide/svelte (new version)'
|
||||
- label: lucide-svelte
|
||||
- label: lucide-vue
|
||||
- label: lucide-vue-next
|
||||
- label: lucide-astro
|
||||
- label: Figma plugin
|
||||
- label: all JS packages
|
||||
- label: site
|
||||
- label: other/not relevant
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
|
||||
1
.github/labeler.yml
vendored
@@ -59,7 +59,6 @@
|
||||
🅰️ angular package:
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- 'packages/angular/*'
|
||||
- 'packages/lucide-angular/*'
|
||||
|
||||
# For changes in the lucide preact package
|
||||
|
||||
@@ -1,19 +1,21 @@
|
||||
name: Lucide Angular checks
|
||||
name: Lucide Vue checks
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- packages/angular/**
|
||||
- packages/lucide-vue/**
|
||||
- packages/shared/**
|
||||
- tools/build-icons/**
|
||||
- tools/rollup-plugins/**
|
||||
- pnpm-lock.yaml
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/checkout@v4
|
||||
- uses: pnpm/action-setup@v4
|
||||
- uses: actions/setup-node@v6
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
cache: 'pnpm'
|
||||
node-version-file: 'package.json'
|
||||
@@ -22,14 +24,14 @@ jobs:
|
||||
run: pnpm install --frozen-lockfile
|
||||
|
||||
- name: Build
|
||||
run: pnpm --filter @lucide/angular build
|
||||
run: pnpm --filter @lucide/vue build
|
||||
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/checkout@v4
|
||||
- uses: pnpm/action-setup@v4
|
||||
- uses: actions/setup-node@v6
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
cache: 'pnpm'
|
||||
node-version-file: 'package.json'
|
||||
@@ -38,4 +40,4 @@ jobs:
|
||||
run: pnpm install --frozen-lockfile
|
||||
|
||||
- name: Test
|
||||
run: pnpm --filter @lucide/angular test
|
||||
run: pnpm --filter @lucide/vue test
|
||||
2
.github/workflows/release.yml
vendored
@@ -58,9 +58,9 @@ jobs:
|
||||
'lucide-preact',
|
||||
'lucide-solid',
|
||||
'lucide-svelte',
|
||||
'@lucide/angular',
|
||||
'@lucide/astro',
|
||||
'@lucide/svelte',
|
||||
'@lucide/vue',
|
||||
]
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
{
|
||||
"$schema": "../category.schema.json",
|
||||
"title": "Brands",
|
||||
"icon": "facebook"
|
||||
}
|
||||
@@ -15,10 +15,6 @@
|
||||
"name": "arrows",
|
||||
"title": "Arrows"
|
||||
},
|
||||
{
|
||||
"name": "brands",
|
||||
"title": "Brands"
|
||||
},
|
||||
{
|
||||
"name": "buildings",
|
||||
"title": "Buildings"
|
||||
|
||||
@@ -31,20 +31,12 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
"lucide-vue-next": {
|
||||
"@lucide/vue": {
|
||||
"order": 2,
|
||||
"icon": "vue-next",
|
||||
"icon": "vue",
|
||||
"docsAlias": "lucide-vue",
|
||||
"packageDirname": "vue",
|
||||
"shields": [
|
||||
{
|
||||
"alt": "npm",
|
||||
"src": "https://img.shields.io/npm/v/lucide-vue-next",
|
||||
"href": "https://www.npmjs.com/package/lucide-vue-next"
|
||||
},
|
||||
{
|
||||
"alt": "npm",
|
||||
"src": "https://img.shields.io/npm/dw/lucide-vue-next",
|
||||
"href": "https://www.npmjs.com/package/lucide-vue-next"
|
||||
}
|
||||
]
|
||||
},
|
||||
"lucide-svelte": {
|
||||
@@ -95,24 +87,8 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
"@lucide/angular": {
|
||||
"order": 6,
|
||||
"icon": "angular",
|
||||
"shields": [
|
||||
{
|
||||
"alt": "npm",
|
||||
"src": "https://img.shields.io/npm/v/@lucide/angular",
|
||||
"href": "https://www.npmjs.com/package/@lucide/angular"
|
||||
},
|
||||
{
|
||||
"alt": "npm",
|
||||
"src": "https://img.shields.io/npm/dw/@lucide/angular",
|
||||
"href": "https://www.npmjs.com/package/@lucide/angular"
|
||||
}
|
||||
]
|
||||
},
|
||||
"lucide-angular": {
|
||||
"order": 7,
|
||||
"order": 6,
|
||||
"icon": "angular",
|
||||
"shields": [
|
||||
{
|
||||
@@ -128,7 +104,7 @@
|
||||
]
|
||||
},
|
||||
"lucide-preact": {
|
||||
"order": 8,
|
||||
"order": 7,
|
||||
"icon": "preact",
|
||||
"shields": [
|
||||
{
|
||||
@@ -146,7 +122,7 @@
|
||||
"@lucide/astro": {
|
||||
"docsAlias": "lucide-astro",
|
||||
"packageDirname": "astro",
|
||||
"order": 9,
|
||||
"order": 8,
|
||||
"icon": "astro",
|
||||
"iconDark": "astro-dark",
|
||||
"shields": [
|
||||
@@ -163,7 +139,7 @@
|
||||
]
|
||||
},
|
||||
"lucide-static": {
|
||||
"order": 10,
|
||||
"order": 9,
|
||||
"icon": "svg",
|
||||
"shields": [
|
||||
{
|
||||
|
||||
@@ -43,7 +43,7 @@ export default App;
|
||||
language: 'vue',
|
||||
title: 'Vue',
|
||||
code: `<script setup>
|
||||
import { $PascalCase } from 'lucide-vue-next';
|
||||
import { $PascalCase } from '@lucide/vue';
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
||||
@@ -69,39 +69,39 @@ const sidebar: UserConfig<DefaultTheme.Config>['themeConfig']['sidebar'] = {
|
||||
link: '/guide/packages/lucide',
|
||||
},
|
||||
{
|
||||
text: 'React',
|
||||
text: 'Lucide React',
|
||||
link: '/guide/packages/lucide-react',
|
||||
},
|
||||
{
|
||||
text: 'Vue',
|
||||
link: '/guide/packages/lucide-vue-next',
|
||||
text: 'Lucide Vue',
|
||||
link: '/guide/packages/lucide-vue',
|
||||
},
|
||||
{
|
||||
text: 'Svelte',
|
||||
text: 'Lucide Svelte',
|
||||
link: '/guide/packages/lucide-svelte',
|
||||
},
|
||||
{
|
||||
text: 'Solid',
|
||||
text: 'Lucide Solid',
|
||||
link: '/guide/packages/lucide-solid',
|
||||
},
|
||||
{
|
||||
text: 'React Native',
|
||||
text: 'Lucide React Native',
|
||||
link: '/guide/packages/lucide-react-native',
|
||||
},
|
||||
{
|
||||
text: 'Angular',
|
||||
link: '/guide/packages/angular',
|
||||
text: 'Lucide Angular',
|
||||
link: '/guide/packages/lucide-angular',
|
||||
},
|
||||
{
|
||||
text: 'Preact',
|
||||
text: 'Lucide Preact',
|
||||
link: '/guide/packages/lucide-preact',
|
||||
},
|
||||
{
|
||||
text: 'Astro',
|
||||
text: 'Lucide Astro',
|
||||
link: '/guide/packages/lucide-astro',
|
||||
},
|
||||
{
|
||||
text: 'Static',
|
||||
text: 'Lucide Static',
|
||||
link: '/guide/packages/lucide-static',
|
||||
},
|
||||
],
|
||||
|
||||
@@ -70,7 +70,7 @@ const value = computed({
|
||||
color: var(--vp-c-text-2);
|
||||
padding: 3px 8px 3px 3px;
|
||||
height: auto;
|
||||
font-size: 13px;
|
||||
font-size: 14px;
|
||||
text-align: left;
|
||||
border: 1px solid transparent;
|
||||
cursor: text;
|
||||
@@ -90,7 +90,7 @@ const value = computed({
|
||||
border: none;
|
||||
background: transparent;
|
||||
color: var(--vp-c-text-1);
|
||||
font-size: 13px;
|
||||
font-size: 14px;
|
||||
text-align: left;
|
||||
border-radius: 8px;
|
||||
cursor: text;
|
||||
|
||||
@@ -13,9 +13,9 @@ export default {
|
||||
label: 'Lucide documentation for React',
|
||||
},
|
||||
{
|
||||
name: 'lucide-vue-next',
|
||||
name: 'lucide-vue',
|
||||
logo: '/framework-logos/vue.svg',
|
||||
label: 'Lucide documentation for Vue 3',
|
||||
label: 'Lucide documentation for Vue',
|
||||
},
|
||||
{
|
||||
name: 'lucide-svelte',
|
||||
@@ -33,7 +33,7 @@ export default {
|
||||
label: 'Lucide documentation for Preact',
|
||||
},
|
||||
{
|
||||
name: 'angular',
|
||||
name: 'lucide-angular',
|
||||
logo: '/framework-logos/angular.svg',
|
||||
label: 'Lucide documentation for Angular',
|
||||
},
|
||||
|
||||
@@ -29,7 +29,12 @@ const props = defineProps<{
|
||||
|
||||
const iconComponent = computed(() => {
|
||||
if (!props.name || !props.iconNode) return null;
|
||||
try {
|
||||
return createLucideIcon(props.name, props.iconNode);
|
||||
} catch (error) {
|
||||
console.warn(`Icon ${props.name} not found, using fallback`);
|
||||
return null;
|
||||
}
|
||||
});
|
||||
|
||||
const CalendarIcon = createLucideIcon('calendar', Calendar.iconNode);
|
||||
@@ -61,7 +66,7 @@ const prettyName = props.name
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<section class="showcase">
|
||||
<section class="showcase" v-if="iconComponent">
|
||||
<h2 class="title">See this icon in action</h2>
|
||||
<div class="showcase-grid">
|
||||
<div class="showcase-item column">
|
||||
|
||||
@@ -29,7 +29,7 @@ However, not everyone can understand them easily. Read more about [how to use Lu
|
||||
|
||||
## Official Packages
|
||||
|
||||
Lucide's official packages are designed to work on different platforms, making it easier for users to integrate icons into their projects. The packages are available for various technologies, including [Web (Vanilla)](https://lucide.dev/guide/packages/lucide), [React](https://lucide.dev/guide/packages/lucide-react), [React Native](https://lucide.dev/guide/packages/lucide-react-native), [Vue](https://lucide.dev/guide/packages/lucide-vue), [Vue 3](https://lucide.dev/guide/packages/lucide-vue-next), [Svelte](https://lucide.dev/guide/packages/lucide-svelte), [Preact](https://lucide.dev/guide/packages/lucide-preact), [Solid](https://lucide.dev/guide/packages/lucide-solid), [Angular](https://lucide.dev/guide/packages/angular), [Astro](https://lucide.dev/guide/packages/lucide-astro), and [NodeJS](https://lucide.dev/guide/packages/lucide-static#nodejs).
|
||||
Lucide's official packages are designed to work on different platforms, making it easier for users to integrate icons into their projects. The packages are available for various technologies, including [Web (Vanilla)](https://lucide.dev/guide/packages/lucide), [React](https://lucide.dev/guide/packages/lucide-react), [React Native](https://lucide.dev/guide/packages/lucide-react-native), [Vue](https://lucide.dev/guide/packages/lucide-vue), [Vue 3](https://lucide.dev/guide/packages/lucide-vue-next), [Svelte](https://lucide.dev/guide/packages/lucide-svelte), [Preact](https://lucide.dev/guide/packages/lucide-preact), [Solid](https://lucide.dev/guide/packages/lucide-solid), [Angular](https://lucide.dev/guide/packages/lucide-angular), [Astro](https://lucide.dev/guide/packages/lucide-astro), and [NodeJS](https://lucide.dev/guide/packages/lucide-static#nodejs).
|
||||
|
||||
## Community
|
||||
|
||||
|
||||
@@ -64,25 +64,24 @@ Implementation of the lucide icon library for Vue applications.
|
||||
::: code-group
|
||||
|
||||
```sh [pnpm]
|
||||
pnpm add lucide-vue-next
|
||||
pnpm add @lucide/vue
|
||||
```
|
||||
|
||||
```sh [yarn]
|
||||
yarn add lucide-vue-next
|
||||
yarn add @lucide/vue
|
||||
```
|
||||
|
||||
```sh [npm]
|
||||
npm install lucide-vue-next
|
||||
npm install @lucide/vue
|
||||
```
|
||||
|
||||
```sh [bun]
|
||||
bun add lucide-vue-next
|
||||
bun add @lucide/vue
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
For more details, see the [documentation](packages/lucide-vue-next.md).
|
||||
For Vue 2 use the `lucide-vue` package.
|
||||
For more details, see the [documentation](packages/lucide-vue.md).
|
||||
|
||||
## Svelte
|
||||
|
||||
@@ -91,22 +90,22 @@ Implementation of the lucide icon library for Svelte applications.
|
||||
::: code-group
|
||||
|
||||
```sh [pnpm]
|
||||
pnpm add lucide-svelte
|
||||
pnpm add @lucide/svelte
|
||||
```
|
||||
|
||||
```sh [yarn]
|
||||
yarn add lucide-svelte
|
||||
yarn add @lucide/svelte
|
||||
```
|
||||
|
||||
```sh [npm]
|
||||
npm install lucide-svelte
|
||||
npm install @lucide/svelte
|
||||
```
|
||||
|
||||
```sh [bun]
|
||||
bun add lucide-svelte
|
||||
bun add @lucide/svelte
|
||||
```
|
||||
|
||||
:::
|
||||
> `@lucide/svelte` is only for Svelte 5, for Svelte 4 use the `lucide-svelte` package.
|
||||
|
||||
For more details, see the [documentation](packages/lucide-svelte.md).
|
||||
|
||||
|
||||
@@ -1,277 +0,0 @@
|
||||
# `@lucide/angular`
|
||||
|
||||
::: warning
|
||||
This documentation is for `@lucide/angular`.
|
||||
|
||||
To learn about our legacy package for Angular, please refer to [`lucide-angular`](./lucide-angular).
|
||||
:::
|
||||
|
||||
A standalone, signal-based, zoneless implementation of Lucide icons for Angular.
|
||||
|
||||
**What you can accomplish:**
|
||||
- Use icons as standalone Angular components with full dependency injection support
|
||||
- Configure icons globally through modern Angular providers
|
||||
- Integrate with Angular's reactive forms and data binding
|
||||
- Build scalable applications with tree-shaken icons and lazy loading support
|
||||
|
||||
## Prerequisites
|
||||
|
||||
This package requires Angular 17+ and uses standalone components, signals, and zoneless change detection.
|
||||
|
||||
## Installation
|
||||
|
||||
::: code-group
|
||||
|
||||
```sh [pnpm]
|
||||
pnpm add @lucide/angular
|
||||
```
|
||||
|
||||
```sh [yarn]
|
||||
yarn add @lucide/angular
|
||||
```
|
||||
|
||||
```sh [npm]
|
||||
npm install @lucide/angular
|
||||
```
|
||||
|
||||
```sh [bun]
|
||||
bun add @lucide/angular
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
## How to use
|
||||
|
||||
### Standalone icons
|
||||
|
||||
Every icon can be imported as a ready-to-use standalone component:
|
||||
|
||||
```html
|
||||
<svg lucideFileText></svg>
|
||||
```
|
||||
|
||||
```ts{2,7}
|
||||
import { Component } from '@angular/core';
|
||||
import { LucideFileText } from '@lucide/angular';
|
||||
|
||||
@Component({
|
||||
selector: 'app-foobar',
|
||||
templateUrl: './foobar.html',
|
||||
imports: [LucideFileText],
|
||||
})
|
||||
export class Foobar { }
|
||||
```
|
||||
|
||||
::: tip
|
||||
Standalone icon components use the selector `svg[lucide{PascalCaseIconName}]`.
|
||||
|
||||
This ensures minimal bloating of the DOM and the ability to directly manipulate all attributes of the resulting SVG element.
|
||||
:::
|
||||
|
||||
### Dynamic icon component
|
||||
|
||||
You may also use the dynamic `LucideIcon` component to dynamically render icons.
|
||||
|
||||
#### With tree-shaken imports
|
||||
|
||||
You may pass imported icons directly to the component:
|
||||
|
||||
```html{3}
|
||||
@for (item of items) {
|
||||
<a navbarItem [routerLink]="item.routerLink">
|
||||
<svg [lucideIcon]="item.icon"></svg>
|
||||
{{ item.title }}
|
||||
</a>
|
||||
}
|
||||
```
|
||||
|
||||
```ts{2,8,14,19}
|
||||
import { Component } from '@angular/core';
|
||||
import { LucideIcon, LucideHouse, LucideUsersRound } from '@lucide/angular';
|
||||
import { NavbarItem, NavbarItemModel } from './navbar-item';
|
||||
|
||||
@Component({
|
||||
selector: 'app-navbar',
|
||||
templateUrl: './navbar.html',
|
||||
imports: [LucideIcon, NavbarItem],
|
||||
})
|
||||
export class Navbar {
|
||||
readonly items: NavbarItemModel[] = [
|
||||
{
|
||||
title: 'Home',
|
||||
icon: LucideHouse,
|
||||
routerLink: [''],
|
||||
},
|
||||
{
|
||||
title: 'Users',
|
||||
icon: LucideUsersRound,
|
||||
routerLink: ['admin/users'],
|
||||
},
|
||||
];
|
||||
}
|
||||
```
|
||||
|
||||
#### With icons provided via dependency injection
|
||||
|
||||
Alternatively, the component also accepts string inputs.
|
||||
|
||||
To use icons this way, first, you have to provide icons via `provideLucideIcons`:
|
||||
|
||||
:::code-group
|
||||
```ts{7-10} [app.config.ts]
|
||||
import { ApplicationConfig } from '@angular/core';
|
||||
import { provideLucideIcons, LucideCircleCheck, LucideCircleX } from '@lucide/angular';
|
||||
|
||||
export const appConfig: ApplicationConfig = {
|
||||
providers: [
|
||||
// ...
|
||||
provideLucideIcons([
|
||||
LucideCircleCheck,
|
||||
LucideCircleX,
|
||||
]),
|
||||
]
|
||||
};
|
||||
```
|
||||
|
||||
```html [foobar.html]
|
||||
<svg lucideIcon="circle-check"></svg>
|
||||
```
|
||||
|
||||
```ts{7} [foobar.ts]
|
||||
import { Component } from '@angular/core';
|
||||
import { LucideIcon } from '@lucide/angular';
|
||||
|
||||
@Component({
|
||||
selector: 'app-foobar',
|
||||
templateUrl: './template-url',
|
||||
imports: [LucideIcon],
|
||||
})
|
||||
export class Foobar { }
|
||||
```
|
||||
:::
|
||||
|
||||
::: tip
|
||||
For optimal bundle size, provide icons at the highest appropriate level in your application.
|
||||
|
||||
Providing all icons at the root level may increase your initial bundle size, while providing them at feature module level enables better code splitting.
|
||||
:::
|
||||
|
||||
::: warning
|
||||
While you may provide your icons at any level of the dependency injection tree, be aware that [Angular's DI system is hierarchical](https://angular.dev/guide/di/defining-dependency-providers#injector-hierarchy-in-angular): `LucideIcon` will only have access to the icons provided closest to it in the tree.
|
||||
:::
|
||||
|
||||
## Accessible labels
|
||||
|
||||
You can use the `title` input property to set the [accessible name element](https://developer.mozilla.org/en-US/docs/Web/SVG/Reference/Element/title) on the SVG:
|
||||
|
||||
```html
|
||||
<svg lucideIcon="house" title="Go to dashboard"></svg>
|
||||
```
|
||||
|
||||
This will result in the following output:
|
||||
|
||||
```html{2}
|
||||
<svg class="lucide lucide-house" ...>
|
||||
<title>Go to dashboard</title>
|
||||
<!-- SVG paths -->
|
||||
</svg>
|
||||
```
|
||||
|
||||
## Props
|
||||
|
||||
You can pass additional props to adjust the icon appearance.
|
||||
|
||||
| name | type | default |
|
||||
|-----------------------|-----------|--------------|
|
||||
| `size` | *number* | 24 |
|
||||
| `color` | *string* | currentColor |
|
||||
| `strokeWidth` | *number* | 2 |
|
||||
| `absoluteStrokeWidth` | *boolean* | false |
|
||||
|
||||
```html
|
||||
<svg lucideHouse size="48" color="red" strokeWidth="1"></svg>
|
||||
```
|
||||
|
||||
## Global configuration
|
||||
|
||||
You can use `provideLucideConfig` to configure the default property values as defined above:
|
||||
|
||||
```ts{2,7-9}
|
||||
import { ApplicationConfig } from '@angular/core';
|
||||
import { provideLucideConfig } from '@lucide/angular';
|
||||
|
||||
export const appConfig: ApplicationConfig = {
|
||||
providers: [
|
||||
// ...
|
||||
provideLucideConfig({
|
||||
strokeWidth: 1.5
|
||||
}),
|
||||
]
|
||||
};
|
||||
```
|
||||
|
||||
## Styling via CSS
|
||||
|
||||
Icons can also be styled by using custom CSS classes:
|
||||
|
||||
```html
|
||||
<svg lucideHousePlus class="my-icon"></svg>
|
||||
```
|
||||
|
||||
```css
|
||||
svg.my-icon {
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
stroke-width: 3;
|
||||
}
|
||||
```
|
||||
|
||||
## With Lucide lab or custom icons
|
||||
|
||||
[Lucide lab](https://github.com/lucide-icons/lucide-lab) is a collection of icons that are not part of the Lucide main library.
|
||||
|
||||
While they aren't provided as standalone components, they can be still be passed to the `LucideIcon` component the same way as official icons:
|
||||
|
||||
```html
|
||||
<!-- Directly as LucideIconData: -->
|
||||
<svg [lucideIcon]="CoconutIcon"></svg>
|
||||
|
||||
<!-- As a provided icon by name: -->
|
||||
<svg lucideIcon="coconut"></svg>
|
||||
```
|
||||
|
||||
```ts{2,6-7,11-12}
|
||||
import { provideLucideIcons } from '@lucide/angular';
|
||||
import { coconut } from '@lucide/lab';
|
||||
|
||||
@Component({
|
||||
templateUrl: './foobar.html',
|
||||
// For using by name via provider:
|
||||
providers: [provideLucideIcons({ coconut })],
|
||||
imports: [LucideIcon]
|
||||
})
|
||||
export class Foobar {
|
||||
// For passing directly as LucideIconData:
|
||||
readonly CoconutIcon = coconut;
|
||||
}
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### The icon is not being displayed
|
||||
If using per-icon-components:
|
||||
1. Ensure that the icon component is being imported, if using per-icon-components
|
||||
2. Check that the icon name matches exactly (case-sensitive)
|
||||
|
||||
If using the dynamic component:
|
||||
1. Ensure the icon is provided via `provideLucideIcons()` if using string names
|
||||
2. Verify the icon is imported from `@lucide/angular` and not the legacy package
|
||||
|
||||
### TypeScript errors?
|
||||
Make sure you're importing from `@lucide/angular` and not `lucide-angular`.
|
||||
|
||||
### Icons render with wrong defaults
|
||||
Ensure `provideLucideConfig()` is used at the right level.
|
||||
|
||||
## Migration guide
|
||||
Migrating from `lucide-angular`? Read our [comprehensive migration guide](https://github.com/lucide-icons/lucide/blob/main/packages/angular/MIGRATION.md).
|
||||
@@ -1,11 +1,5 @@
|
||||
# Lucide Angular
|
||||
|
||||
::: warning
|
||||
This documentation if for our legacy package for Angular.
|
||||
|
||||
For our modern, standalone-first implementation, please refer to [`@lucide/angular`](./angular).
|
||||
:::
|
||||
|
||||
Angular components and services for Lucide icons that integrate with Angular's dependency injection and component system. Provides both traditional module-based and modern standalone component approaches for maximum flexibility in Angular applications.
|
||||
|
||||
**What you can accomplish:**
|
||||
|
||||
@@ -102,16 +102,10 @@ The example below imports all ES Modules, so exercise caution when using it. Imp
|
||||
|
||||
### Icon Component Example
|
||||
|
||||
```tsx
|
||||
import * as icons from 'lucide-react-native/icons';
|
||||
```jsx
|
||||
import { icons } from 'lucide-react-native';
|
||||
|
||||
interface IconProps {
|
||||
name: keyof typeof icons;
|
||||
color?: string;
|
||||
size?: number;
|
||||
}
|
||||
|
||||
const Icon = ({ name, color, size }: IconProps) => {
|
||||
const Icon = ({ name, color, size }) => {
|
||||
const LucideIcon = icons[name];
|
||||
|
||||
return <LucideIcon color={color} size={size} />;
|
||||
@@ -122,11 +116,11 @@ export default Icon;
|
||||
|
||||
#### Using the Icon Component
|
||||
|
||||
```tsx
|
||||
```jsx
|
||||
import Icon from './Icon';
|
||||
|
||||
const App = () => {
|
||||
return <Icon name="House" />;
|
||||
return <Icon name="house" />;
|
||||
};
|
||||
|
||||
export default App;
|
||||
|
||||
@@ -30,14 +30,7 @@ This package includes the following implementations of Lucide icons:
|
||||
|
||||
SVG sprites and icon fonts include **all icons**, which can significantly increase your app's bundle size and load time.
|
||||
|
||||
For production environments, we recommend using a bundler with tree-shaking support to include only the icons you actually use. Consider using:
|
||||
|
||||
- [lucide](lucide)
|
||||
- [lucide-react](lucide-react)
|
||||
- [lucide-vue](lucide-vue)
|
||||
- [lucide-vue-next](lucide-vue-next)
|
||||
- [lucide-angular](lucide-angular)
|
||||
- [lucide-preact](lucide-preact)
|
||||
For production environments, we recommend using a bundler with tree-shaking support to include only the icons you actually use. Consider using one of the framework-specific [packages](../../packages).
|
||||
:::
|
||||
|
||||
## Installation
|
||||
|
||||
@@ -1,148 +0,0 @@
|
||||
# Lucide Vue Next
|
||||
|
||||
Vue 3 components for Lucide icons that leverage the Composition API and modern Vue features. Each icon is a reactive Vue component that renders as an inline SVG, providing excellent performance and developer experience in Vue 3 applications.
|
||||
|
||||
**What you can accomplish:**
|
||||
- Use icons as Vue 3 components with full reactivity and TypeScript support
|
||||
- Bind icon properties to reactive data and computed values
|
||||
- Customize icons with props, slots, and Vue's powerful templating system
|
||||
- Integrate seamlessly with Vue 3's Composition API and script setup syntax
|
||||
- Build dynamic interfaces where icons respond to application state changes
|
||||
|
||||
## Installation
|
||||
|
||||
::: code-group
|
||||
|
||||
```sh [pnpm]
|
||||
pnpm add lucide-vue-next
|
||||
```
|
||||
|
||||
```sh [yarn]
|
||||
yarn add lucide-vue-next
|
||||
```
|
||||
|
||||
```sh [npm]
|
||||
npm install lucide-vue-next
|
||||
```
|
||||
|
||||
```sh [bun]
|
||||
bun add lucide-vue-next
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
## How to use
|
||||
|
||||
Lucide is built with ES Modules, so it's completely tree-shakable.
|
||||
|
||||
Each icon can be imported as a Vue component, which renders an inline SVG Element. This way only the icons that are imported into your project are included in the final bundle. The rest of the icons are tree-shaken away.
|
||||
|
||||
### Example
|
||||
|
||||
You can pass additional props to adjust the icon.
|
||||
|
||||
```vue
|
||||
<script setup>
|
||||
import { Camera } from 'lucide-vue-next';
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Camera
|
||||
color="red"
|
||||
:size="32"
|
||||
/>
|
||||
</template>
|
||||
```
|
||||
|
||||
## Props
|
||||
|
||||
| name | type | default |
|
||||
| ----------------------- | --------- | ------------ |
|
||||
| `size` | *number* | 24 |
|
||||
| `color` | *string* | currentColor |
|
||||
| `stroke-width` | *number* | 2 |
|
||||
| `absoluteStrokeWidth` | *boolean* | false |
|
||||
| `default-class` | *string* | lucide-icon |
|
||||
|
||||
### Applying props
|
||||
|
||||
To customize the appearance of an icon, you can pass custom properties as props directly to the component. The component accepts all SVG attributes as props, which allows flexible styling of the SVG elements. See the list of SVG Presentation Attributes on [MDN](https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/Presentation).
|
||||
|
||||
```vue
|
||||
<template>
|
||||
<Camera fill="red" />
|
||||
</template>
|
||||
```
|
||||
|
||||
## With Lucide lab or custom icons
|
||||
|
||||
[Lucide lab](https://github.com/lucide-icons/lucide-lab) is a collection of icons that are not part of the Lucide main library.
|
||||
|
||||
They can be used by using the `Icon` component.
|
||||
All props like regular lucide icons can be passed to adjust the icon appearance.
|
||||
|
||||
### Using the `Icon` component
|
||||
|
||||
This creates a single icon based on the iconNode passed and renders a Lucide icon component.
|
||||
|
||||
```vue
|
||||
<script setup>
|
||||
import { Icon } from 'lucide-vue-next';
|
||||
import { baseball } from '@lucide/lab';
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Icon :iconNode="baseball" />
|
||||
</template>
|
||||
```
|
||||
|
||||
## One generic icon component
|
||||
|
||||
It is possible to create one generic icon component to load icons, but it is not recommended.
|
||||
|
||||
::: danger
|
||||
The example below imports all ES Modules, so exercise caution when using it. Importing all icons will significantly increase the build size of the application, negatively affecting its performance. This is especially important when using bundlers like `Webpack`, `Rollup`, or `Vite`.
|
||||
:::
|
||||
|
||||
### Icon Component Example
|
||||
|
||||
```vue
|
||||
<script setup>
|
||||
import { computed } from 'vue';
|
||||
import * as icons from "lucide-vue-next";
|
||||
|
||||
const props = defineProps({
|
||||
name: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
size: Number,
|
||||
color: String,
|
||||
strokeWidth: Number,
|
||||
defaultClass: String
|
||||
})
|
||||
|
||||
const icon = computed(() => icons[props.name]);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<component
|
||||
:is="icon"
|
||||
:size="size"
|
||||
:color="color"
|
||||
:stroke-width="strokeWidth" :default-class="defaultClass"
|
||||
/>
|
||||
</template>
|
||||
```
|
||||
|
||||
### Using the Icon Component
|
||||
|
||||
All other props listed above also work on the `Icon` Component.
|
||||
|
||||
```vue
|
||||
<template>
|
||||
<div id="app">
|
||||
<Icon name="Airplay" />
|
||||
</div>
|
||||
</template>
|
||||
```
|
||||
@@ -9,28 +9,24 @@ Vue 2 components for Lucide icons that integrate with Vue's Options API and temp
|
||||
- Build applications using Vue 2's familiar syntax and patterns
|
||||
- Bridge the gap while planning migration to Vue 3
|
||||
|
||||
::: danger
|
||||
This package is deprecated. Vue 2 is EOF See [Announcement](https://v2.vuejs.org/eol/). Migrate to Vue 3.
|
||||
:::
|
||||
|
||||
## Installation
|
||||
|
||||
::: code-group
|
||||
|
||||
```sh [pnpm]
|
||||
pnpm add lucide-vue
|
||||
pnpm add @lucide/vue
|
||||
```
|
||||
|
||||
```sh [yarn]
|
||||
yarn add lucide-vue
|
||||
yarn add @lucide/vue
|
||||
```
|
||||
|
||||
```sh [npm]
|
||||
npm install lucide-vue
|
||||
npm install @lucide/vue
|
||||
```
|
||||
|
||||
```sh [bun]
|
||||
bun add lucide-vue
|
||||
bun add @lucide/vue
|
||||
```
|
||||
|
||||
:::
|
||||
@@ -43,21 +39,19 @@ Each icon can be imported as a Vue component, which renders an inline SVG Elemen
|
||||
|
||||
### Example
|
||||
|
||||
Additional props can be passed to adjust the icon:
|
||||
You can pass additional props to adjust the icon.
|
||||
|
||||
```vue
|
||||
<template>
|
||||
<Camera color="red" :size="32" />
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { Camera } from 'lucide-vue';
|
||||
|
||||
export default {
|
||||
name: 'My Component',
|
||||
components: { Camera }
|
||||
};
|
||||
<script setup>
|
||||
import { Camera } from '@lucide/vue';
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Camera
|
||||
color="red"
|
||||
:size="32"
|
||||
/>
|
||||
</template>
|
||||
```
|
||||
|
||||
## Props
|
||||
@@ -80,6 +74,28 @@ To customize the appearance of an icon, you can pass custom properties as props
|
||||
</template>
|
||||
```
|
||||
|
||||
## With Lucide lab or custom icons
|
||||
|
||||
[Lucide lab](https://github.com/lucide-icons/lucide-lab) is a collection of icons that are not part of the Lucide main library.
|
||||
|
||||
They can be used by using the `Icon` component.
|
||||
All props like regular lucide icons can be passed to adjust the icon appearance.
|
||||
|
||||
### Using the `Icon` component
|
||||
|
||||
This creates a single icon based on the iconNode passed and renders a Lucide icon component.
|
||||
|
||||
```vue
|
||||
<script setup>
|
||||
import { Icon } from '@lucide/vue';
|
||||
import { baseball } from '@lucide/lab';
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Icon :iconNode="baseball" />
|
||||
</template>
|
||||
```
|
||||
|
||||
## One generic icon component
|
||||
|
||||
It is possible to create one generic icon component to load icons, but it is not recommended.
|
||||
@@ -91,30 +107,37 @@ The example below imports all ES Modules, so exercise caution when using it. Imp
|
||||
### Icon Component Example
|
||||
|
||||
```vue
|
||||
<template>
|
||||
<component :is="icon" />
|
||||
</template>
|
||||
<script setup>
|
||||
import { computed } from 'vue';
|
||||
import * as icons from "@lucide/vue";
|
||||
|
||||
<script>
|
||||
import * as icons from 'lucide-vue';
|
||||
|
||||
export default {
|
||||
props: {
|
||||
const props = defineProps({
|
||||
name: {
|
||||
type: String,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
icon() {
|
||||
return icons[this.name];
|
||||
}
|
||||
}
|
||||
};
|
||||
size: Number,
|
||||
color: String,
|
||||
strokeWidth: Number,
|
||||
defaultClass: String
|
||||
})
|
||||
|
||||
const icon = computed(() => icons[props.name]);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<component
|
||||
:is="icon"
|
||||
:size="size"
|
||||
:color="color"
|
||||
:stroke-width="strokeWidth" :default-class="defaultClass"
|
||||
/>
|
||||
</template>
|
||||
```
|
||||
|
||||
#### Using the Icon Component
|
||||
### Using the Icon Component
|
||||
|
||||
All other props listed above also work on the `Icon` Component.
|
||||
|
||||
```vue
|
||||
<template>
|
||||
|
||||
@@ -34,6 +34,11 @@
|
||||
],
|
||||
"destination": "/icons",
|
||||
"permanent": false
|
||||
},
|
||||
{
|
||||
"source": "/guide/packages/lucide-vue-next",
|
||||
"destination": "/guide/packages/lucide-vue",
|
||||
"permanent": false
|
||||
}
|
||||
],
|
||||
"headers": [
|
||||
|
||||
@@ -56,7 +56,6 @@
|
||||
"account",
|
||||
"animals",
|
||||
"arrows",
|
||||
"brands",
|
||||
"buildings",
|
||||
"charts",
|
||||
"communication",
|
||||
@@ -134,7 +133,7 @@
|
||||
"$defs": {
|
||||
"iconDeprecationReasons": {
|
||||
"type": "string",
|
||||
"enum": ["icon.brand"]
|
||||
"enum": ["icon.renamed"]
|
||||
},
|
||||
"aliasDeprecationReasons": {
|
||||
"type": "string",
|
||||
|
||||
@@ -16,8 +16,6 @@
|
||||
],
|
||||
"categories": [
|
||||
"multimedia",
|
||||
"connectivity",
|
||||
"devices",
|
||||
"brands"
|
||||
"connectivity"
|
||||
]
|
||||
}
|
||||
|
||||
@@ -10,7 +10,6 @@
|
||||
"payment"
|
||||
],
|
||||
"categories": [
|
||||
"brands",
|
||||
"development",
|
||||
"finance"
|
||||
]
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
{
|
||||
"$schema": "../icon.schema.json",
|
||||
"deprecated": true,
|
||||
"deprecationReason": "icon.brand",
|
||||
"toBeRemovedInVersion": "v1.0",
|
||||
"contributors": [
|
||||
"colebemis",
|
||||
"ericfennis"
|
||||
],
|
||||
"tags": [
|
||||
"browser",
|
||||
"logo"
|
||||
],
|
||||
"categories": [
|
||||
"brands"
|
||||
],
|
||||
"aliases": [
|
||||
{
|
||||
"name": "chrome",
|
||||
"deprecated": true,
|
||||
"deprecationReason": "alias.name",
|
||||
"toBeRemovedInVersion": "v1.0"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
<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.88 21.94 15.46 14" />
|
||||
<path d="M21.17 8H12" />
|
||||
<path d="M3.95 6.06 8.54 14" />
|
||||
<circle cx="12" cy="12" r="10" />
|
||||
<circle cx="12" cy="12" r="4" />
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 377 B |
@@ -1,17 +0,0 @@
|
||||
{
|
||||
"$schema": "../icon.schema.json",
|
||||
"deprecated": true,
|
||||
"deprecationReason": "icon.brand",
|
||||
"toBeRemovedInVersion": "v1.0",
|
||||
"contributors": [
|
||||
"colebemis",
|
||||
"ericfennis"
|
||||
],
|
||||
"tags": [
|
||||
"logo"
|
||||
],
|
||||
"categories": [
|
||||
"brands",
|
||||
"development"
|
||||
]
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
<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"
|
||||
>
|
||||
<polygon points="12 2 22 8.5 22 15.5 12 22 2 15.5 2 8.5 12 2" />
|
||||
<line x1="12" x2="12" y1="22" y2="15.5" />
|
||||
<polyline points="22 8.5 12 15.5 2 8.5" />
|
||||
<polyline points="2 15.5 12 8.5 22 15.5" />
|
||||
<line x1="12" x2="12" y1="2" y2="8.5" />
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 454 B |
@@ -1,18 +0,0 @@
|
||||
{
|
||||
"$schema": "../icon.schema.json",
|
||||
"deprecated": true,
|
||||
"deprecationReason": "icon.brand",
|
||||
"toBeRemovedInVersion": "v1.0",
|
||||
"contributors": [
|
||||
"colebemis",
|
||||
"csandman",
|
||||
"ericfennis"
|
||||
],
|
||||
"tags": [
|
||||
"logo"
|
||||
],
|
||||
"categories": [
|
||||
"brands",
|
||||
"development"
|
||||
]
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
<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 16V8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16z" />
|
||||
<polyline points="7.5 4.21 12 6.81 16.5 4.21" />
|
||||
<polyline points="7.5 19.79 7.5 14.6 3 12" />
|
||||
<polyline points="21 12 16.5 14.6 16.5 19.79" />
|
||||
<polyline points="3.27 6.96 12 12.01 20.73 6.96" />
|
||||
<line x1="12" x2="12" y1="22.08" y2="12" />
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 595 B |
@@ -1,18 +0,0 @@
|
||||
{
|
||||
"$schema": "../icon.schema.json",
|
||||
"deprecated": true,
|
||||
"deprecationReason": "icon.brand",
|
||||
"toBeRemovedInVersion": "v1.0",
|
||||
"contributors": [
|
||||
"ahtohbi4"
|
||||
],
|
||||
"tags": [
|
||||
"design",
|
||||
"social"
|
||||
],
|
||||
"categories": [
|
||||
"brands",
|
||||
"social",
|
||||
"design"
|
||||
]
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="24"
|
||||
height="24"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
>
|
||||
<circle cx="12" cy="12" r="10" />
|
||||
<path d="M19.13 5.09C15.22 9.14 10 10.44 2.25 10.94" />
|
||||
<path d="M21.75 12.84c-6.62-1.41-12.14 1-16.38 6.32" />
|
||||
<path d="M8.56 2.75c4.37 6 6 9.42 8 17.72" />
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 408 B |
@@ -1,19 +0,0 @@
|
||||
{
|
||||
"$schema": "../icon.schema.json",
|
||||
"deprecated": true,
|
||||
"deprecationReason": "icon.brand",
|
||||
"toBeRemovedInVersion": "v1.0",
|
||||
"contributors": [
|
||||
"colebemis",
|
||||
"csandman",
|
||||
"ericfennis"
|
||||
],
|
||||
"tags": [
|
||||
"logo",
|
||||
"social"
|
||||
],
|
||||
"categories": [
|
||||
"social",
|
||||
"brands"
|
||||
]
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
<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="M18 2h-3a5 5 0 0 0-5 5v3H7v4h3v8h4v-8h3l1-4h-4V7a1 1 0 0 1 1-1h3z" />
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 289 B |
@@ -1,21 +0,0 @@
|
||||
{
|
||||
"$schema": "../icon.schema.json",
|
||||
"deprecated": true,
|
||||
"deprecationReason": "icon.brand",
|
||||
"toBeRemovedInVersion": "v1.0",
|
||||
"contributors": [
|
||||
"colebemis",
|
||||
"csandman",
|
||||
"mittalyashu",
|
||||
"ericfennis"
|
||||
],
|
||||
"tags": [
|
||||
"logo",
|
||||
"design",
|
||||
"tool"
|
||||
],
|
||||
"categories": [
|
||||
"brands",
|
||||
"design"
|
||||
]
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
<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 5.5A3.5 3.5 0 0 1 8.5 2H12v7H8.5A3.5 3.5 0 0 1 5 5.5z" />
|
||||
<path d="M12 2h3.5a3.5 3.5 0 1 1 0 7H12V2z" />
|
||||
<path d="M12 12.5a3.5 3.5 0 1 1 7 0 3.5 3.5 0 1 1-7 0z" />
|
||||
<path d="M5 19.5A3.5 3.5 0 0 1 8.5 16H12v3.5a3.5 3.5 0 1 1-7 0z" />
|
||||
<path d="M5 12.5A3.5 3.5 0 0 1 8.5 9H12v7H8.5A3.5 3.5 0 0 1 5 12.5z" />
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 534 B |
@@ -1,21 +0,0 @@
|
||||
{
|
||||
"$schema": "../icon.schema.json",
|
||||
"deprecated": true,
|
||||
"deprecationReason": "icon.brand",
|
||||
"toBeRemovedInVersion": "v1.0",
|
||||
"contributors": [
|
||||
"colebemis",
|
||||
"csandman",
|
||||
"mittalyashu",
|
||||
"ericfennis"
|
||||
],
|
||||
"tags": [
|
||||
"logo",
|
||||
"design",
|
||||
"tool"
|
||||
],
|
||||
"categories": [
|
||||
"brands",
|
||||
"design"
|
||||
]
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
<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 16V9h14V2H5l14 14h-7m-7 0 7 7v-7m-7 0h7" />
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 266 B |
@@ -1,20 +0,0 @@
|
||||
{
|
||||
"$schema": "../icon.schema.json",
|
||||
"deprecated": true,
|
||||
"deprecationReason": "icon.brand",
|
||||
"toBeRemovedInVersion": "v1.0",
|
||||
"contributors": [
|
||||
"colebemis",
|
||||
"csandman",
|
||||
"ericfennis",
|
||||
"karsa-mistmere"
|
||||
],
|
||||
"tags": [
|
||||
"logo",
|
||||
"version control"
|
||||
],
|
||||
"categories": [
|
||||
"brands",
|
||||
"development"
|
||||
]
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
<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 22v-4a4.8 4.8 0 0 0-1-3.5c3 0 6-2 6-5.5.08-1.25-.27-2.48-1-3.5.28-1.15.28-2.35 0-3.5 0 0-1 0-3 1.5-2.64-.5-5.36-.5-8 0C6 2 5 2 5 2c-.3 1.15-.3 2.35 0 3.5A5.403 5.403 0 0 0 4 9c0 3.5 3 5.5 6 5.5-.39.49-.68 1.05-.85 1.65-.17.6-.22 1.23-.15 1.85v4" />
|
||||
<path d="M9 18c-4.51 2-5-2-7-2" />
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 509 B |
@@ -1,20 +0,0 @@
|
||||
{
|
||||
"$schema": "../icon.schema.json",
|
||||
"deprecated": true,
|
||||
"deprecationReason": "icon.brand",
|
||||
"toBeRemovedInVersion": "v1.0",
|
||||
"contributors": [
|
||||
"colebemis",
|
||||
"csandman",
|
||||
"ericfennis",
|
||||
"karsa-mistmere"
|
||||
],
|
||||
"tags": [
|
||||
"logo",
|
||||
"version control"
|
||||
],
|
||||
"categories": [
|
||||
"brands",
|
||||
"development"
|
||||
]
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="24"
|
||||
height="24"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
>
|
||||
<path d="m22 13.29-3.33-10a.42.42 0 0 0-.14-.18.38.38 0 0 0-.22-.11.39.39 0 0 0-.23.07.42.42 0 0 0-.14.18l-2.26 6.67H8.32L6.1 3.26a.42.42 0 0 0-.1-.18.38.38 0 0 0-.26-.08.39.39 0 0 0-.23.07.42.42 0 0 0-.14.18L2 13.29a.74.74 0 0 0 .27.83L12 21l9.69-6.88a.71.71 0 0 0 .31-.83Z" />
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 489 B |
@@ -12,7 +12,6 @@
|
||||
],
|
||||
"categories": [
|
||||
"shapes",
|
||||
"brands",
|
||||
"development"
|
||||
]
|
||||
}
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
{
|
||||
"$schema": "../icon.schema.json",
|
||||
"deprecated": true,
|
||||
"deprecationReason": "icon.brand",
|
||||
"toBeRemovedInVersion": "v1.0",
|
||||
"contributors": [
|
||||
"colebemis",
|
||||
"csandman",
|
||||
"ericfennis"
|
||||
],
|
||||
"tags": [
|
||||
"logo",
|
||||
"camera",
|
||||
"social"
|
||||
],
|
||||
"categories": [
|
||||
"brands",
|
||||
"social",
|
||||
"photography"
|
||||
]
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="24"
|
||||
height="24"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
>
|
||||
<rect width="20" height="20" x="2" y="2" rx="5" ry="5" />
|
||||
<path d="M16 11.37A4 4 0 1 1 12.63 8 4 4 0 0 1 16 11.37z" />
|
||||
<line x1="17.5" x2="17.51" y1="6.5" y2="6.5" />
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 381 B |
@@ -1,20 +0,0 @@
|
||||
{
|
||||
"$schema": "../icon.schema.json",
|
||||
"deprecated": true,
|
||||
"deprecationReason": "icon.brand",
|
||||
"toBeRemovedInVersion": "v1.0",
|
||||
"contributors": [
|
||||
"okcoker",
|
||||
"csandman",
|
||||
"ericfennis"
|
||||
],
|
||||
"tags": [
|
||||
"logo",
|
||||
"social media",
|
||||
"social"
|
||||
],
|
||||
"categories": [
|
||||
"social",
|
||||
"brands"
|
||||
]
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
<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="M16 8a6 6 0 0 1 6 6v7h-4v-7a2 2 0 0 0-2-2 2 2 0 0 0-2 2v7h-4v-7a6 6 0 0 1 6-6z" />
|
||||
<rect width="4" height="12" x="2" y="9" />
|
||||
<circle cx="4" cy="4" r="2" />
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 380 B |
@@ -9,8 +9,8 @@
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
>
|
||||
<path d="M11 7 6 2" />
|
||||
<path d="M18.992 12H2.041" />
|
||||
<path d="M19 12H2" />
|
||||
<path d="M21.145 18.38A3.34 3.34 0 0 1 20 16.5a3.3 3.3 0 0 1-1.145 1.88c-.575.46-.855 1.02-.855 1.595A2 2 0 0 0 20 22a2 2 0 0 0 2-2.025c0-.58-.285-1.13-.855-1.595" />
|
||||
<path d="m6 2 5 5" />
|
||||
<path d="m8.5 4.5 2.148-2.148a1.205 1.205 0 0 1 1.704 0l7.296 7.296a1.205 1.205 0 0 1 0 1.704l-7.592 7.592a3.615 3.615 0 0 1-5.112 0l-3.888-3.888a3.615 3.615 0 0 1 0-5.112L5.67 7.33" />
|
||||
</svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 622 B After Width: | Height: | Size: 613 B |
@@ -1,18 +0,0 @@
|
||||
{
|
||||
"$schema": "../icon.schema.json",
|
||||
"deprecated": true,
|
||||
"deprecationReason": "icon.brand",
|
||||
"toBeRemovedInVersion": "v1.0",
|
||||
"contributors": [
|
||||
"colebemis",
|
||||
"csandman",
|
||||
"ericfennis"
|
||||
],
|
||||
"tags": [
|
||||
"logo",
|
||||
"save"
|
||||
],
|
||||
"categories": [
|
||||
"brands"
|
||||
]
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
<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 3a2 2 0 0 1 2 2v6a1 1 0 0 1-20 0V5a2 2 0 0 1 2-2z" />
|
||||
<path d="m8 10 4 4 4-4" />
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 306 B |
@@ -1,19 +0,0 @@
|
||||
{
|
||||
"$schema": "../icon.schema.json",
|
||||
"contributors": [
|
||||
"danielbayley"
|
||||
],
|
||||
"deprecated": true,
|
||||
"deprecationReason": "icon.brand",
|
||||
"toBeRemovedInVersion": "v1.0",
|
||||
"tags": [
|
||||
"railway",
|
||||
"train",
|
||||
"track",
|
||||
"line"
|
||||
],
|
||||
"categories": [
|
||||
"transportation",
|
||||
"navigation"
|
||||
]
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
<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 15h14" />
|
||||
<path d="M5 9h14" />
|
||||
<path d="m14 20-5-5 6-6-5-5" />
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 289 B |
@@ -1,22 +0,0 @@
|
||||
{
|
||||
"$schema": "../icon.schema.json",
|
||||
"deprecated": true,
|
||||
"deprecationReason": "icon.brand",
|
||||
"toBeRemovedInVersion": "v1.0",
|
||||
"contributors": [
|
||||
"colebemis",
|
||||
"ashygee",
|
||||
"wojtekmaj",
|
||||
"mittalyashu",
|
||||
"ericfennis"
|
||||
],
|
||||
"tags": [
|
||||
"logo"
|
||||
],
|
||||
"categories": [
|
||||
"account",
|
||||
"social",
|
||||
"brands",
|
||||
"development"
|
||||
]
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="24"
|
||||
height="24"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
>
|
||||
<rect width="3" height="8" x="13" y="2" rx="1.5" />
|
||||
<path d="M19 8.5V10h1.5A1.5 1.5 0 1 0 19 8.5" />
|
||||
<rect width="3" height="8" x="8" y="14" rx="1.5" />
|
||||
<path d="M5 15.5V14H3.5A1.5 1.5 0 1 0 5 15.5" />
|
||||
<rect width="8" height="3" x="14" y="13" rx="1.5" />
|
||||
<path d="M15.5 19H14v1.5a1.5 1.5 0 1 0 1.5-1.5" />
|
||||
<rect width="8" height="3" x="2" y="8" rx="1.5" />
|
||||
<path d="M8.5 5H10V3.5A1.5 1.5 0 1 0 8.5 5" />
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 628 B |
@@ -13,7 +13,6 @@
|
||||
"productivity"
|
||||
],
|
||||
"categories": [
|
||||
"brands",
|
||||
"gaming"
|
||||
]
|
||||
}
|
||||
|
||||
@@ -1,37 +0,0 @@
|
||||
{
|
||||
"$schema": "../icon.schema.json",
|
||||
"contributors": [
|
||||
"karsa-mistmere"
|
||||
],
|
||||
"tags": [
|
||||
"toolkit",
|
||||
"tools",
|
||||
"trunk",
|
||||
"chest",
|
||||
"box",
|
||||
"storage",
|
||||
"utility",
|
||||
"utilities",
|
||||
"container",
|
||||
"kit",
|
||||
"set",
|
||||
"repair",
|
||||
"fix",
|
||||
"service",
|
||||
"maintenance",
|
||||
"mechanic",
|
||||
"workshop",
|
||||
"construction",
|
||||
"hardware",
|
||||
"equipment",
|
||||
"gear",
|
||||
"handyman",
|
||||
"engineering",
|
||||
"craft",
|
||||
"diy"
|
||||
],
|
||||
"categories": [
|
||||
"tools",
|
||||
"home"
|
||||
]
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
<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="M16 12v4" />
|
||||
<path d="M16 6a2 2 0 0 1 1.414.586l4 4A2 2 0 0 1 22 12v7a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2v-7a2 2 0 0 1 .586-1.414l4-4A2 2 0 0 1 8 6z" />
|
||||
<path d="M16 6V4a2 2 0 0 0-2-2h-4a2 2 0 0 0-2 2v2" />
|
||||
<path d="M2 14h20" />
|
||||
<path d="M8 12v4" />
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 471 B |
@@ -1,21 +0,0 @@
|
||||
{
|
||||
"$schema": "../icon.schema.json",
|
||||
"deprecated": true,
|
||||
"deprecationReason": "icon.brand",
|
||||
"toBeRemovedInVersion": "v1.0",
|
||||
"contributors": [
|
||||
"bdbch",
|
||||
"csandman",
|
||||
"mittalyashu",
|
||||
"ericfennis"
|
||||
],
|
||||
"tags": [
|
||||
"logo",
|
||||
"brand"
|
||||
],
|
||||
"categories": [
|
||||
"account",
|
||||
"brands",
|
||||
"development"
|
||||
]
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="24"
|
||||
height="24"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
>
|
||||
<rect width="18" height="18" x="3" y="3" rx="2" ry="2" />
|
||||
<rect width="3" height="9" x="7" y="7" />
|
||||
<rect width="3" height="5" x="14" y="7" />
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 357 B |
@@ -1,20 +0,0 @@
|
||||
{
|
||||
"$schema": "../icon.schema.json",
|
||||
"deprecated": true,
|
||||
"deprecationReason": "icon.brand",
|
||||
"toBeRemovedInVersion": "v1.0",
|
||||
"contributors": [
|
||||
"ahtohbi4",
|
||||
"johnletey"
|
||||
],
|
||||
"tags": [
|
||||
"logo",
|
||||
"social"
|
||||
],
|
||||
"categories": [
|
||||
"brands",
|
||||
"social",
|
||||
"account",
|
||||
"gaming"
|
||||
]
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
<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 2H3v16h5v4l4-4h5l4-4V2zm-10 9V7m5 4V7" />
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 265 B |
@@ -1,21 +0,0 @@
|
||||
{
|
||||
"$schema": "../icon.schema.json",
|
||||
"deprecated": true,
|
||||
"deprecationReason": "icon.brand",
|
||||
"toBeRemovedInVersion": "v1.0",
|
||||
"contributors": [
|
||||
"colebemis",
|
||||
"csandman",
|
||||
"ericfennis",
|
||||
"karsa-mistmere"
|
||||
],
|
||||
"tags": [
|
||||
"logo",
|
||||
"social"
|
||||
],
|
||||
"categories": [
|
||||
"brands",
|
||||
"social",
|
||||
"account"
|
||||
]
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="24"
|
||||
height="24"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
>
|
||||
<path d="M22 4s-.7 2.1-2 3.4c1.6 10-9.4 17.3-18 11.6 2.2.1 4.4-.6 6-2C3 15.5.5 9.6 3 5c2.2 2.6 5.6 4.1 9 4-.9-4.2 4-6.6 7-3.8 1.1 0 3-1.2 3-1.2z" />
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 359 B |
@@ -1,24 +0,0 @@
|
||||
{
|
||||
"$schema": "../icon.schema.json",
|
||||
"deprecated": true,
|
||||
"deprecationReason": "icon.brand",
|
||||
"toBeRemovedInVersion": "v1.0",
|
||||
"contributors": [
|
||||
"colebemis",
|
||||
"csandman",
|
||||
"ericfennis",
|
||||
"karsa-mistmere",
|
||||
"jguddas"
|
||||
],
|
||||
"tags": [
|
||||
"logo",
|
||||
"social",
|
||||
"video",
|
||||
"play"
|
||||
],
|
||||
"categories": [
|
||||
"multimedia",
|
||||
"social",
|
||||
"brands"
|
||||
]
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
<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.5 17a24.12 24.12 0 0 1 0-10 2 2 0 0 1 1.4-1.4 49.56 49.56 0 0 1 16.2 0A2 2 0 0 1 21.5 7a24.12 24.12 0 0 1 0 10 2 2 0 0 1-1.4 1.4 49.55 49.55 0 0 1-16.2 0A2 2 0 0 1 2.5 17" />
|
||||
<path d="m10 15 5-3-5-3z" />
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 428 B |
@@ -1,38 +0,0 @@
|
||||
module.exports = {
|
||||
root: true,
|
||||
overrides: [
|
||||
{
|
||||
files: ['*.ts'],
|
||||
extends: [
|
||||
'eslint:recommended',
|
||||
'plugin:@typescript-eslint/recommended',
|
||||
'plugin:@angular-eslint/recommended',
|
||||
'plugin:@angular-eslint/template/process-inline-templates',
|
||||
'prettier',
|
||||
],
|
||||
rules: {
|
||||
'@angular-eslint/directive-selector': [
|
||||
'error',
|
||||
{
|
||||
type: 'attribute',
|
||||
prefix: 'lucide',
|
||||
style: 'camelCase',
|
||||
},
|
||||
],
|
||||
'@angular-eslint/component-selector': [
|
||||
'error',
|
||||
{
|
||||
type: 'attribute',
|
||||
prefix: ['lucide'],
|
||||
style: 'camelCase',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
files: ['*.html'],
|
||||
extends: ['plugin:@angular-eslint/template/recommended'],
|
||||
rules: {},
|
||||
},
|
||||
],
|
||||
};
|
||||
4
packages/angular/.vscode/extensions.json
vendored
@@ -1,4 +0,0 @@
|
||||
{
|
||||
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=827846
|
||||
"recommendations": ["angular.ng-template"]
|
||||
}
|
||||
20
packages/angular/.vscode/launch.json
vendored
@@ -1,20 +0,0 @@
|
||||
{
|
||||
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"name": "ng serve",
|
||||
"type": "chrome",
|
||||
"request": "launch",
|
||||
"preLaunchTask": "npm: start",
|
||||
"url": "http://localhost:4200/"
|
||||
},
|
||||
{
|
||||
"name": "ng test",
|
||||
"type": "chrome",
|
||||
"request": "launch",
|
||||
"preLaunchTask": "npm: test",
|
||||
"url": "http://localhost:9876/debug.html"
|
||||
}
|
||||
]
|
||||
}
|
||||
42
packages/angular/.vscode/tasks.json
vendored
@@ -1,42 +0,0 @@
|
||||
{
|
||||
// For more information, visit: https://go.microsoft.com/fwlink/?LinkId=733558
|
||||
"version": "2.0.0",
|
||||
"tasks": [
|
||||
{
|
||||
"type": "npm",
|
||||
"script": "start",
|
||||
"isBackground": true,
|
||||
"problemMatcher": {
|
||||
"owner": "typescript",
|
||||
"pattern": "$tsc",
|
||||
"background": {
|
||||
"activeOnStart": true,
|
||||
"beginsPattern": {
|
||||
"regexp": "(.*?)"
|
||||
},
|
||||
"endsPattern": {
|
||||
"regexp": "bundle generation complete"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "npm",
|
||||
"script": "test",
|
||||
"isBackground": true,
|
||||
"problemMatcher": {
|
||||
"owner": "typescript",
|
||||
"pattern": "$tsc",
|
||||
"background": {
|
||||
"activeOnStart": true,
|
||||
"beginsPattern": {
|
||||
"regexp": "(.*?)"
|
||||
},
|
||||
"endsPattern": {
|
||||
"regexp": "bundle generation complete"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,184 +0,0 @@
|
||||
# Migrating from `lucide-angular` ⇒ `@lucide/angular`
|
||||
|
||||
## What changed
|
||||
|
||||
`@lucide/angular` moves from a module + single component based API to a more modern Angular approach:
|
||||
|
||||
- The library defines modern signal-based, standalone components, without zone.js based change detection.
|
||||
- Icons are consumed as standalone imports (one component per icon).
|
||||
- Dynamic icon registration is done via `provideLucideIcon()`, not using `NgModule`.
|
||||
- Static icons use per-icon components for better tree-shaking.
|
||||
- Dynamic icons still use a single dynamic component (`svg[lucideIcon]`).
|
||||
- Global defaults are configured via `provideLucideConfig()`.
|
||||
|
||||
---
|
||||
|
||||
## Step 1 – Update dependencies
|
||||
|
||||
Remove `lucide-angular`, add `@lucide/angular`, see http://lucide.dev/guide/packages/angular#installation
|
||||
|
||||
---
|
||||
|
||||
## Step 2 – Replace `LucideAngularModule.pick(...)` with `provideLucideIcons(...)`
|
||||
|
||||
> Notes:
|
||||
> - Old imports like `AirVentIcon` / `AlarmClock` from `lucide-angular` should be replaced with the new per-icon exports `LucideAirVent` and `LucideAlarmClock`.
|
||||
> - If you mostly used static icons, you may not need to provide them **at all**, please refer to Step 3.
|
||||
|
||||
### Before
|
||||
|
||||
#### NgModule based
|
||||
```ts
|
||||
import { LucideAngularModule, AirVent, AlarmClock } from 'lucide-angular';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
BrowserModule,
|
||||
LucideAngularModule.pick({ AirVent, AlarmClock }),
|
||||
],
|
||||
})
|
||||
export class AppModule {}
|
||||
```
|
||||
|
||||
#### Standalone
|
||||
|
||||
```ts
|
||||
import { ApplicationConfig } from '@angular/core';
|
||||
|
||||
export const appConfig: ApplicationConfig = {
|
||||
providers: [
|
||||
importProvidersFrom(LucideAngularModule.pick({ AirVent, AlarmClock })),
|
||||
]
|
||||
};
|
||||
```
|
||||
|
||||
### After
|
||||
```ts
|
||||
import { ApplicationConfig } from '@angular/core';
|
||||
import { provideLucideIcons, LucideAirVent, LucideAlarmClock } from '@lucide/angular';
|
||||
|
||||
export const appConfig: ApplicationConfig = {
|
||||
providers: [
|
||||
// ...
|
||||
provideLucideIcons([
|
||||
LucideAirVent,
|
||||
LucideAlarmClock,
|
||||
]),
|
||||
]
|
||||
};
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Step 3 – Replace `<lucide-angular>` / `<lucide-icon>` / `<i-lucide>` / `<span-lucide>`
|
||||
|
||||
The legacy package rendered everything through a single component. All of these selectors must be migrated to `<svg>` usage.
|
||||
|
||||
### A. Static icons by name
|
||||
|
||||
If the icon is known at build time, just use a static import:
|
||||
|
||||
#### Before
|
||||
```html
|
||||
<lucide-angular name="circle-check"></lucide-angular>
|
||||
```
|
||||
|
||||
#### After
|
||||
```html
|
||||
<svg lucideCircleCheck></svg>
|
||||
```
|
||||
|
||||
### B. Static icons with icon data binding
|
||||
|
||||
#### Before
|
||||
```ts
|
||||
import { CircleCheck } from 'lucide-angular';
|
||||
```
|
||||
|
||||
```html
|
||||
<lucide-icon [img]="CircleCheck"></lucide-icon>
|
||||
```
|
||||
|
||||
#### After
|
||||
|
||||
```ts
|
||||
import { LucideCircleCheck } from '@lucide/angular';
|
||||
```
|
||||
|
||||
```html
|
||||
<svg lucideCircleCheck></svg>
|
||||
```
|
||||
|
||||
...and import `LucideCircleCheck` from `@lucide/angular`.
|
||||
|
||||
---
|
||||
|
||||
### C. Dynamic icons
|
||||
|
||||
If the icon varies at runtime, use the dynamic component:
|
||||
|
||||
#### Before
|
||||
```html
|
||||
<lucide-icon [name]="item.icon"></lucide-icon>
|
||||
```
|
||||
|
||||
#### After
|
||||
```html
|
||||
<svg [lucideIcon]="item.icon"></svg>
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Step 4 – Replace `LucideIconConfig` with `provideLucideConfig()`
|
||||
|
||||
### Before
|
||||
```ts
|
||||
import { inject } from '@angular/core';
|
||||
import { LucideIconConfig } from 'lucide-angular';
|
||||
|
||||
inject(LucideIconConfig).size = 12;
|
||||
```
|
||||
|
||||
### After
|
||||
```ts
|
||||
import { provideLucideConfig } from '@lucide/angular';
|
||||
|
||||
providers: [
|
||||
provideLucideConfig({ size: 12 }),
|
||||
]
|
||||
```
|
||||
|
||||
### Where to place it
|
||||
|
||||
- App-wide: `AppModule.providers` or `bootstrapApplication(...providers)`
|
||||
- Feature-level: feature module providers
|
||||
- Component-level (standalone): component `providers`
|
||||
|
||||
---
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### The icon is not being displayed
|
||||
If using per-icon-components:
|
||||
1. Ensure that the icon component is being imported, if using per-icon-components
|
||||
2. Check that the icon name matches exactly (case-sensitive)
|
||||
|
||||
If using the dynamic component:
|
||||
1. Ensure the icon is provided via `provideLucideIcons()` if using string names
|
||||
2. Verify the icon is imported from `@lucide/angular` and not the legacy package
|
||||
|
||||
### TypeScript errors?
|
||||
Make sure you're importing from `@lucide/angular` and not `lucide-angular`.
|
||||
|
||||
### Icons render with wrong defaults
|
||||
Ensure `provideLucideConfig()` is used at the right level.
|
||||
|
||||
---
|
||||
|
||||
## TL;DR
|
||||
- `LucideAngularModule` ⇒ static: removed; dynamic: `LucideIcon`
|
||||
- `LucideAngularModule.pick(...)` ⇒ `provideLucideIcons(...)`
|
||||
- `<lucide-angular name="foo-bar">` ⇒ `<svg lucideFooBar>`
|
||||
- `<lucide-icon [name]="expr">` ⇒ `<svg [lucideIcon]="expr">`
|
||||
- `<lucide-icon [img]="expr">` ⇒ `<svg [lucideIcon]="expr">`
|
||||
- `LucideIconConfig` ⇒ `provideLucideConfig(...)`
|
||||
@@ -1,77 +0,0 @@
|
||||
<p align="center">
|
||||
<a href="https://github.com/lucide-icons/lucide">
|
||||
<img src="https://lucide.dev/package-logos/lucide-angular.svg" alt="Lucide icon library for Angular applications." width="540">
|
||||
</a>
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
Lucide icon library for Angular applications.
|
||||
</p>
|
||||
|
||||
<div align="center">
|
||||
|
||||
[](https://www.npmjs.com/package/lucide-angular)
|
||||

|
||||
[](https://lucide.dev/license)
|
||||
</div>
|
||||
|
||||
<p align="center">
|
||||
<a href="https://lucide.dev/guide/">About</a>
|
||||
·
|
||||
<a href="https://lucide.dev/icons/">Icons</a>
|
||||
·
|
||||
<a href="https://lucide.dev/guide/packages/lucide-angular">Documentation</a>
|
||||
·
|
||||
<a href="https://lucide.dev/license">License</a>
|
||||
</p>
|
||||
|
||||
# Lucide Angular
|
||||
|
||||
A standalone, signal based, zoneless implementation of the Lucide icon library for Angular applications.
|
||||
|
||||
## Installation
|
||||
|
||||
```sh
|
||||
pnpm add @lucide/angular
|
||||
```
|
||||
|
||||
```sh
|
||||
npm install @lucide/angular
|
||||
```
|
||||
|
||||
```sh
|
||||
yarn add @lucide/angular
|
||||
```
|
||||
|
||||
```sh
|
||||
bun add @lucide/angular
|
||||
```
|
||||
|
||||
## Documentation
|
||||
|
||||
For full documentation, visit [lucide.dev](https://lucide.dev/guide/packages/angular)
|
||||
|
||||
## Migration guide
|
||||
|
||||
Migrating from `lucide-angular`? Read our [comprehensive migration guide](./MIGRATION.md).
|
||||
|
||||
## Community
|
||||
|
||||
Join the [Discord server](https://discord.gg/EH6nSts) to chat with the maintainers and other users.
|
||||
|
||||
## License
|
||||
|
||||
Lucide is licensed under the ISC license. See [LICENSE](https://lucide.dev/license).
|
||||
|
||||
## Sponsors
|
||||
|
||||
<a href="https://vercel.com?utm_source=lucide&utm_campaign=oss">
|
||||
<img src="https://lucide.dev/vercel.svg" alt="Powered by Vercel" width="200" />
|
||||
</a>
|
||||
|
||||
<a href="https://www.digitalocean.com/?refcode=b0877a2caebd&utm_campaign=Referral_Invite&utm_medium=Referral_Program&utm_source=badge"><img src="https://lucide.dev/digitalocean.svg" width="200" alt="DigitalOcean Referral Badge" /></a>
|
||||
|
||||
### Awesome backers 🍺
|
||||
|
||||
<a href="https://www.scipress.io?utm_source=lucide"><img src="https://lucide.dev/sponsors/scipress.svg" width="180" alt="Scipress sponsor badge" /></a>
|
||||
<a href="https://github.com/pdfme/pdfme"><img src="https://lucide.dev/sponsors/pdfme.svg" width="180" alt="pdfme sponsor badge" /></a>
|
||||
@@ -1,51 +0,0 @@
|
||||
{
|
||||
"$schema": "./node_modules/@angular/cli/lib/config/schema.json",
|
||||
"version": 1,
|
||||
"cli": {
|
||||
"packageManager": "pnpm"
|
||||
},
|
||||
"newProjectRoot": ".",
|
||||
"projects": {
|
||||
"@lucide/angular": {
|
||||
"projectType": "library",
|
||||
"root": ".",
|
||||
"sourceRoot": "./src",
|
||||
"prefix": "lib",
|
||||
"architect": {
|
||||
"build": {
|
||||
"builder": "@angular/build:ng-packagr",
|
||||
"configurations": {
|
||||
"production": {
|
||||
"tsConfig": "./tsconfig.lib.prod.json"
|
||||
},
|
||||
"development": {
|
||||
"tsConfig": "./tsconfig.lib.json"
|
||||
}
|
||||
},
|
||||
"defaultConfiguration": "production"
|
||||
},
|
||||
"test": {
|
||||
"builder": "@angular/build:unit-test",
|
||||
"options": {
|
||||
"tsConfig": "./tsconfig.spec.json",
|
||||
"coverage": true,
|
||||
"coverageReporters": ["html", "lcov"],
|
||||
"coverageExclude": ["src/icons/*"],
|
||||
"coverageThresholds": {
|
||||
"statements": 80,
|
||||
"branches": 80,
|
||||
"functions": 80,
|
||||
"lines": 80
|
||||
}
|
||||
}
|
||||
},
|
||||
"lint": {
|
||||
"builder": "@angular-eslint/builder:lint",
|
||||
"options": {
|
||||
"lintFilePatterns": ["src/**/*.ts", "src/**/*.html"]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
{
|
||||
"$schema": "./node_modules/ng-packagr/ng-package.schema.json",
|
||||
"dest": "./dist",
|
||||
"lib": {
|
||||
"entryFile": "./src/public-api.ts"
|
||||
}
|
||||
}
|
||||
@@ -1,76 +0,0 @@
|
||||
{
|
||||
"name": "@lucide/angular",
|
||||
"description": "A Lucide icon library package for Angular applications.",
|
||||
"version": "0.0.1",
|
||||
"author": "SMAH1",
|
||||
"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-angular"
|
||||
},
|
||||
"publishConfig": {
|
||||
"directory": "dist"
|
||||
},
|
||||
"scripts": {
|
||||
"ng": "ng",
|
||||
"watch": "ng build --watch --configuration development",
|
||||
"prebuild": "pnpm clean && pnpm copy:license && pnpm build:icons",
|
||||
"build": "pnpm prebuild && pnpm build:ng",
|
||||
"copy:license": "cp ../../LICENSE ./LICENSE",
|
||||
"clean": "rm -rf dist && rm -rf ./src/icons/*.ts",
|
||||
"build:icons": "build-icons --output=./src --templateSrc=./scripts/exportTemplate.mts --renderUniqueKey --iconFileExtension=.ts --exportFileName=lucide-angular.ts --useDefaultExports=0",
|
||||
"build:ng": "ng build --configuration production",
|
||||
"test": "pnpm prebuild && ng test --no-watch",
|
||||
"test:watch": "ng test",
|
||||
"lint": "npx eslint 'src/**/*.{js,jsx,ts,tsx,html,css,scss}' --quiet --fix",
|
||||
"e2e": "ng e2e",
|
||||
"version": "pnpm version --git-tag-version=false"
|
||||
},
|
||||
"prettier": {
|
||||
"printWidth": 100,
|
||||
"singleQuote": true,
|
||||
"overrides": [
|
||||
{
|
||||
"files": "*.html",
|
||||
"options": {
|
||||
"parser": "angular"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"private": true,
|
||||
"devDependencies": {
|
||||
"@angular-eslint/builder": "~21.1.0",
|
||||
"@angular-eslint/eslint-plugin": "~21.1.0",
|
||||
"@angular-eslint/eslint-plugin-template": "~21.1.0",
|
||||
"@angular-eslint/schematics": "~21.1.0",
|
||||
"@angular-eslint/template-parser": "~21.1.0",
|
||||
"@angular/build": "^21.0.3",
|
||||
"@angular/cli": "^21.0.3",
|
||||
"@angular/common": "^21.0.0",
|
||||
"@angular/compiler": "^21.0.0",
|
||||
"@angular/compiler-cli": "^21.0.0",
|
||||
"@angular/core": "^21.0.0",
|
||||
"@angular/forms": "^21.0.0",
|
||||
"@angular/platform-browser": "^21.0.0",
|
||||
"@angular/router": "^21.0.0",
|
||||
"@lucide/build-icons": "workspace:*",
|
||||
"@lucide/helpers": "workspace:*",
|
||||
"@vitest/browser-playwright": "^4.0.16",
|
||||
"@vitest/coverage-v8": "^4.0.16",
|
||||
"angular-eslint": "21.1.0",
|
||||
"jsdom": "^27.1.0",
|
||||
"ng-packagr": "^21.0.0",
|
||||
"rxjs": "~7.8.0",
|
||||
"tslib": "^2.3.0",
|
||||
"typescript": "~5.9.2",
|
||||
"vitest": "^4.0.16"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@angular/common": "17.x - 21.x",
|
||||
"@angular/core": "17.x - 21.x"
|
||||
}
|
||||
}
|
||||
@@ -1,68 +0,0 @@
|
||||
import base64SVG from '@lucide/build-icons/utils/base64SVG';
|
||||
import defineExportTemplate from '@lucide/build-icons/utils/defineExportTemplate';
|
||||
import { toPascalCase } from '@lucide/helpers';
|
||||
|
||||
export default defineExportTemplate(async ({
|
||||
componentName,
|
||||
iconName,
|
||||
children,
|
||||
getSvg,
|
||||
deprecated,
|
||||
deprecationReason,
|
||||
aliases = [],
|
||||
}) => {
|
||||
const svgContents = await getSvg();
|
||||
const svgBase64 = base64SVG(svgContents);
|
||||
const angularComponentName = `Lucide${componentName}`;
|
||||
const selectors = [`svg[lucide${toPascalCase(iconName)}]`];
|
||||
const aliasComponentNames: string[] = [];
|
||||
for (const alias of aliases) {
|
||||
const aliasName = typeof alias === 'string' ? alias : alias.name;
|
||||
const aliasComponentName = `Lucide${toPascalCase(aliasName)}`;
|
||||
const aliasSelector = `svg[lucide${toPascalCase(aliasName)}]`;
|
||||
if (!selectors.includes(aliasSelector)) {
|
||||
selectors.push(aliasSelector);
|
||||
}
|
||||
if (aliasComponentName !== angularComponentName && !aliasComponentNames.includes(aliasComponentName)) {
|
||||
aliasComponentNames.push(aliasComponentName);
|
||||
}
|
||||
}
|
||||
|
||||
return `\
|
||||
import { LucideIconData } from '../types';
|
||||
import { LucideIconBase } from '../lucide-icon-base';
|
||||
import { Component, signal } from '@angular/core';
|
||||
|
||||
/**
|
||||
* @component @name ${componentName}
|
||||
* @description Lucide SVG icon component, renders SVG Element with children.
|
||||
*
|
||||
* @preview  - https://lucide.dev/icons/${iconName}
|
||||
* @see https://lucide.dev/guide/packages/lucide-angular - Documentation
|
||||
*
|
||||
* @param {Object} props - Lucide icons props and any valid SVG attribute
|
||||
* ${deprecated ? `@deprecated ${deprecationReason}` : ''}
|
||||
*/
|
||||
@Component({
|
||||
selector: '${selectors.join(', ')}',
|
||||
templateUrl: '../lucide-icon.html',
|
||||
standalone: true,
|
||||
})
|
||||
export class ${angularComponentName} extends LucideIconBase {
|
||||
static readonly iconName = '${iconName}';
|
||||
static readonly iconData: LucideIconData = ${JSON.stringify(children)};
|
||||
protected override readonly iconName = signal(${angularComponentName}.iconName);
|
||||
protected override readonly iconData = signal(${angularComponentName}.iconData);
|
||||
}
|
||||
|
||||
${aliasComponentNames.map((aliasComponentName) => {
|
||||
return `
|
||||
/**
|
||||
* @deprecated
|
||||
* @see ${angularComponentName}
|
||||
*/
|
||||
export const ${aliasComponentName} = ${angularComponentName};
|
||||
`;
|
||||
}).join(`\n\n`)}
|
||||
`;
|
||||
});
|
||||
@@ -1,11 +0,0 @@
|
||||
export default {
|
||||
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',
|
||||
};
|
||||
@@ -1,25 +0,0 @@
|
||||
import { TestBed } from '@angular/core/testing';
|
||||
import { LUCIDE_CONFIG, lucideDefaultConfig, provideLucideConfig } from './lucide-config';
|
||||
|
||||
describe('Lucide config', () => {
|
||||
describe('LUCIDE_CONFIG', () => {
|
||||
it('should use default', () => {
|
||||
expect(TestBed.inject(LUCIDE_CONFIG)).toBe(lucideDefaultConfig);
|
||||
});
|
||||
});
|
||||
describe('provideLucideConfig', () => {
|
||||
it('should use defaults', () => {
|
||||
TestBed.configureTestingModule({
|
||||
providers: [
|
||||
provideLucideConfig({
|
||||
size: 18,
|
||||
}),
|
||||
],
|
||||
});
|
||||
expect(TestBed.inject(LUCIDE_CONFIG)).toEqual({
|
||||
...lucideDefaultConfig,
|
||||
size: 18,
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -1,67 +0,0 @@
|
||||
import { InjectionToken, Provider } from '@angular/core';
|
||||
|
||||
/**
|
||||
* Lucide icon configuration options.
|
||||
*/
|
||||
export interface LucideConfig {
|
||||
/**
|
||||
* Stroke color.
|
||||
* @default currentColor
|
||||
*/
|
||||
color: string;
|
||||
/**
|
||||
* Width and height.
|
||||
* @default 24
|
||||
*/
|
||||
size: number;
|
||||
/**
|
||||
* Stroke width
|
||||
* @default 2
|
||||
*/
|
||||
strokeWidth: number;
|
||||
/**
|
||||
* Whether stroke width should be scaled to appear uniform regardless of icon size.
|
||||
* @default false
|
||||
*
|
||||
* @remarks
|
||||
* Use CSS to set on SVG paths instead:
|
||||
* ```css
|
||||
* .lucide * {
|
||||
* vector-effect: non-scaling-stroke;
|
||||
* }`
|
||||
* ```
|
||||
*/
|
||||
absoluteStrokeWidth: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* Default icon configuration options.
|
||||
*/
|
||||
export const lucideDefaultConfig: LucideConfig = {
|
||||
color: 'currentColor',
|
||||
size: 24,
|
||||
strokeWidth: 2,
|
||||
absoluteStrokeWidth: false,
|
||||
};
|
||||
|
||||
/**
|
||||
* Injection token for providing default configuration options.
|
||||
*
|
||||
* @internal Use {@link provideLucideConfig}
|
||||
*/
|
||||
export const LUCIDE_CONFIG = new InjectionToken<LucideConfig>('Lucide icon config', {
|
||||
factory: () => lucideDefaultConfig,
|
||||
});
|
||||
|
||||
/**
|
||||
* Provider for default icon configuration options.
|
||||
*/
|
||||
export function provideLucideConfig(config: Partial<LucideConfig>): Provider {
|
||||
return {
|
||||
provide: LUCIDE_CONFIG,
|
||||
useValue: {
|
||||
...lucideDefaultConfig,
|
||||
...config,
|
||||
},
|
||||
};
|
||||
}
|
||||
@@ -1,149 +0,0 @@
|
||||
import {
|
||||
Component,
|
||||
computed,
|
||||
effect,
|
||||
ElementRef,
|
||||
inject,
|
||||
input,
|
||||
Renderer2,
|
||||
Signal,
|
||||
} from '@angular/core';
|
||||
import { LUCIDE_CONFIG } from './lucide-config';
|
||||
import { LucideIconData, Nullable } from './types';
|
||||
import defaultAttributes from './default-attributes';
|
||||
import { formatFixed } from './utils/format-fixed';
|
||||
import { toKebabCase } from './utils/to-kebab-case';
|
||||
|
||||
function transformNumericStringInput(
|
||||
value: Nullable<string | number>,
|
||||
defaultValue: number,
|
||||
): number {
|
||||
if (typeof value === 'string') {
|
||||
const parsedValue = parseInt(value, 10);
|
||||
if (isNaN(parsedValue)) {
|
||||
return defaultValue;
|
||||
}
|
||||
return parsedValue;
|
||||
}
|
||||
return value ?? defaultValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
@Component({
|
||||
// eslint-disable-next-line @angular-eslint/component-selector
|
||||
selector: 'svg[lucideIcon]',
|
||||
templateUrl: './lucide-icon.html',
|
||||
host: {
|
||||
...defaultAttributes,
|
||||
class: 'lucide',
|
||||
'[attr.width]': 'size().toString(10)',
|
||||
'[attr.height]': 'size().toString(10)',
|
||||
'[attr.stroke]': 'color()',
|
||||
'[attr.stroke-width]': 'computedStrokeWidth()',
|
||||
'[attr.aria-hidden]': 'ariaHidden()',
|
||||
},
|
||||
})
|
||||
export abstract class LucideIconBase {
|
||||
protected abstract readonly iconName: Signal<Nullable<string>>;
|
||||
protected abstract readonly iconData: Signal<Nullable<LucideIconData>>;
|
||||
protected readonly iconConfig = inject(LUCIDE_CONFIG);
|
||||
protected readonly elRef = inject(ElementRef);
|
||||
protected readonly renderer = inject(Renderer2);
|
||||
protected readonly ariaHidden = computed(() => {
|
||||
return !this.title();
|
||||
});
|
||||
/**
|
||||
* An optional accessible label for the icon.
|
||||
* - If provided, it will add the title as an [`<svg:title>` element](https://developer.mozilla.org/en-US/docs/Web/SVG/Reference/Element/title).
|
||||
* - If not provided, the component will add an `aria-hidden="true"` attribute automatically.
|
||||
*
|
||||
* @remarks
|
||||
* Please refer to our [Accessibility guide](https://lucide.dev/guide/advanced/accessibility) regarding this matter.
|
||||
* Adding accessible labels to icons is normally not necessary:
|
||||
* - If your icon is decorative (as most icons are) just leave it as hidden from screen readers.
|
||||
* - If your icon is interactive, it should be contained within an interactive element (e.g. button), and you should probably set your accessible label on that element.
|
||||
* - If your icon is functional (e.g. used in place of a label), feel free to use this property.
|
||||
*/
|
||||
readonly title = input<Nullable<string>>();
|
||||
/**
|
||||
* Width and height.
|
||||
* @default 24
|
||||
*/
|
||||
readonly size = input(this.iconConfig.size, {
|
||||
transform: (value: Nullable<string | number>) =>
|
||||
transformNumericStringInput(value, this.iconConfig.size),
|
||||
});
|
||||
/**
|
||||
* Stroke color.
|
||||
* @default currentColor
|
||||
*/
|
||||
readonly color = input(this.iconConfig.color, {
|
||||
transform: (value: Nullable<string>) => value ?? this.iconConfig.color,
|
||||
});
|
||||
/**
|
||||
* Stroke width
|
||||
* @default 2
|
||||
*/
|
||||
readonly strokeWidth = input(this.iconConfig.strokeWidth, {
|
||||
transform: (value: Nullable<string | number>) =>
|
||||
transformNumericStringInput(value, this.iconConfig.strokeWidth),
|
||||
});
|
||||
/**
|
||||
* Whether stroke width should be scaled to appear uniform regardless of icon size.
|
||||
*
|
||||
* @remarks
|
||||
* Use CSS to set on SVG paths instead:
|
||||
* ```css
|
||||
* .lucide * {
|
||||
* vector-effect: non-scaling-stroke;
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
readonly absoluteStrokeWidth = input(this.iconConfig.absoluteStrokeWidth, {
|
||||
transform: (value: Nullable<boolean>) => value ?? this.iconConfig.absoluteStrokeWidth,
|
||||
});
|
||||
protected readonly computedStrokeWidth = computed(() => {
|
||||
const strokeWidth = this.strokeWidth();
|
||||
const size = this.size();
|
||||
return this.absoluteStrokeWidth()
|
||||
? formatFixed(strokeWidth / (size / 24))
|
||||
: strokeWidth.toString(10);
|
||||
});
|
||||
|
||||
constructor() {
|
||||
effect((onCleanup) => {
|
||||
const icon = this.iconData();
|
||||
if (icon) {
|
||||
const elements = icon.map(([name, attrs]) => {
|
||||
const element = this.renderer.createElement(name, 'http://www.w3.org/2000/svg');
|
||||
Object.entries(attrs).forEach(([name, value]) =>
|
||||
this.renderer.setAttribute(
|
||||
element,
|
||||
name,
|
||||
typeof value === 'number' ? value.toString(10) : value,
|
||||
),
|
||||
);
|
||||
this.renderer.appendChild(this.elRef.nativeElement, element);
|
||||
return element;
|
||||
});
|
||||
onCleanup(() => {
|
||||
elements.forEach((element) =>
|
||||
this.renderer.removeChild(this.elRef.nativeElement, element),
|
||||
);
|
||||
});
|
||||
}
|
||||
});
|
||||
effect((onCleanup) => {
|
||||
const name = this.iconName();
|
||||
if (name) {
|
||||
const cssClass = `lucide-${toKebabCase(name)}`;
|
||||
this.renderer.addClass(this.elRef.nativeElement, cssClass);
|
||||
onCleanup(() => {
|
||||
this.renderer.removeClass(this.elRef.nativeElement, cssClass);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -1,4 +0,0 @@
|
||||
@if (title(); as titleValue) {
|
||||
<title>{{ titleValue }}</title>
|
||||
}
|
||||
<ng-content />
|
||||
@@ -1,243 +0,0 @@
|
||||
import { Component, input, inputBinding, signal, WritableSignal } from '@angular/core';
|
||||
import { LucideIcon } from './lucide-icon';
|
||||
import { LucideIconData, LucideIconInput } from './types';
|
||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
import { provideLucideIcons } from './lucide-icons';
|
||||
import { LucideActivity } from './icons/activity';
|
||||
import { By } from '@angular/platform-browser';
|
||||
|
||||
@Component({
|
||||
template: `@if (icon(); as iconData) {
|
||||
<svg [lucideIcon]="iconData">
|
||||
<rect x="1" y="1" width="22" height="22" />
|
||||
</svg>
|
||||
}`,
|
||||
imports: [LucideIcon],
|
||||
})
|
||||
class TestHostComponent {
|
||||
readonly icon = input<LucideIconData>();
|
||||
}
|
||||
|
||||
describe('LucideIcon', () => {
|
||||
let component: LucideIcon;
|
||||
let fixture: ComponentFixture<LucideIcon>;
|
||||
let icon: WritableSignal<LucideIconInput | null | undefined>;
|
||||
let name: WritableSignal<string | undefined>;
|
||||
let title: WritableSignal<string | undefined>;
|
||||
let color: WritableSignal<string | undefined>;
|
||||
let size: WritableSignal<string | number | undefined>;
|
||||
let strokeWidth: WritableSignal<string | number | undefined>;
|
||||
let absoluteStrokeWidth: WritableSignal<boolean | undefined>;
|
||||
const getSvgAttribute = (attr: string) => fixture.nativeElement.getAttribute(attr);
|
||||
const testIcon: LucideIconData = [['polyline', { points: '1 1 22 22' }]];
|
||||
const testIcon2: LucideIconData = [
|
||||
['circle', { cx: 12, cy: 12, r: 8 }],
|
||||
['polyline', { points: '1 1 22 22' }],
|
||||
];
|
||||
beforeEach(async () => {
|
||||
TestBed.configureTestingModule({
|
||||
providers: [provideLucideIcons({ demo: testIcon })],
|
||||
});
|
||||
icon = signal('demo');
|
||||
name = signal(undefined);
|
||||
title = signal(undefined);
|
||||
color = signal(undefined);
|
||||
size = signal(undefined);
|
||||
strokeWidth = signal(undefined);
|
||||
absoluteStrokeWidth = signal(undefined);
|
||||
fixture = TestBed.createComponent(LucideIcon, {
|
||||
inferTagName: true,
|
||||
bindings: [
|
||||
inputBinding('lucideIcon', icon),
|
||||
inputBinding('name', name),
|
||||
inputBinding('title', title),
|
||||
inputBinding('color', color),
|
||||
inputBinding('size', size),
|
||||
inputBinding('strokeWidth', strokeWidth),
|
||||
inputBinding('absoluteStrokeWidth', absoluteStrokeWidth),
|
||||
],
|
||||
});
|
||||
component = fixture.componentInstance;
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
fixture.detectChanges();
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should render children', () => {
|
||||
icon.set(testIcon2);
|
||||
fixture.detectChanges();
|
||||
expect(fixture.nativeElement.innerHTML).toBe(
|
||||
'<!--container--><circle cx="12" cy="12" r="8"></circle><polyline points="1 1 22 22"></polyline>',
|
||||
);
|
||||
});
|
||||
|
||||
it('should remove children on change', () => {
|
||||
icon.set(null);
|
||||
fixture.detectChanges();
|
||||
expect(fixture.nativeElement.innerHTML).toBe('<!--container-->');
|
||||
});
|
||||
|
||||
describe('iconInput', () => {
|
||||
it('should support LucideIconData input', () => {
|
||||
icon.set(testIcon);
|
||||
name.set('custom-name');
|
||||
fixture.detectChanges();
|
||||
|
||||
expect(component['iconData']()).toBe(testIcon);
|
||||
expect(component['iconName']()).toBe('custom-name');
|
||||
expect(fixture.nativeElement.innerHTML).toBe(
|
||||
'<!--container--><polyline points="1 1 22 22"></polyline>',
|
||||
);
|
||||
});
|
||||
it('should support LucideIconComponentType input', () => {
|
||||
icon.set(LucideActivity);
|
||||
fixture.detectChanges();
|
||||
|
||||
expect(component['iconData']()).toBe(LucideActivity.iconData);
|
||||
expect(component['iconName']()).toBe(LucideActivity.iconName);
|
||||
});
|
||||
it('should support string icon name', () => {
|
||||
icon.set('demo');
|
||||
fixture.detectChanges();
|
||||
|
||||
expect(component['iconData']()).toBe(testIcon);
|
||||
expect(component['iconName']()).toBe('demo');
|
||||
});
|
||||
it('should throw error if no icon founds', () => {
|
||||
icon.set('invalid');
|
||||
expect(() => fixture.detectChanges()).toThrowError(`Unable to resolve icon 'invalid'`);
|
||||
});
|
||||
});
|
||||
|
||||
describe('class', () => {
|
||||
it('should add all classes', () => {
|
||||
fixture.detectChanges();
|
||||
expect(getSvgAttribute('class')).toBe('lucide lucide-demo');
|
||||
});
|
||||
it('should add class from name, even if icon has name', () => {
|
||||
icon.set(LucideActivity);
|
||||
name.set('custom-name');
|
||||
fixture.detectChanges();
|
||||
|
||||
expect(getSvgAttribute('class')).toBe('lucide lucide-custom-name');
|
||||
});
|
||||
it('should add class icon if available', () => {
|
||||
icon.set(LucideActivity);
|
||||
fixture.detectChanges();
|
||||
|
||||
expect(getSvgAttribute('class')).toBe('lucide lucide-activity');
|
||||
});
|
||||
it('should remove class on change', () => {
|
||||
icon.set(null);
|
||||
fixture.detectChanges();
|
||||
expect(getSvgAttribute('class')).toBe('lucide');
|
||||
});
|
||||
});
|
||||
|
||||
describe('color', () => {
|
||||
it('should default to currentColor', () => {
|
||||
fixture.detectChanges();
|
||||
expect(getSvgAttribute('stroke')).toBe('currentColor');
|
||||
});
|
||||
it('should set color', () => {
|
||||
color.set('red');
|
||||
fixture.detectChanges();
|
||||
expect(getSvgAttribute('stroke')).toBe('red');
|
||||
});
|
||||
});
|
||||
|
||||
describe('size', () => {
|
||||
it('should default to 24', () => {
|
||||
fixture.detectChanges();
|
||||
expect(getSvgAttribute('width')).toBe('24');
|
||||
expect(getSvgAttribute('height')).toBe('24');
|
||||
});
|
||||
it('should set size', () => {
|
||||
size.set(12);
|
||||
fixture.detectChanges();
|
||||
expect(getSvgAttribute('width')).toBe('12');
|
||||
expect(getSvgAttribute('height')).toBe('12');
|
||||
});
|
||||
it('should allow string size', () => {
|
||||
size.set('18');
|
||||
fixture.detectChanges();
|
||||
expect(getSvgAttribute('width')).toBe('18');
|
||||
expect(getSvgAttribute('height')).toBe('18');
|
||||
});
|
||||
it('should use default on invalid string', () => {
|
||||
size.set('large');
|
||||
fixture.detectChanges();
|
||||
expect(getSvgAttribute('width')).toBe('24');
|
||||
expect(getSvgAttribute('height')).toBe('24');
|
||||
});
|
||||
});
|
||||
|
||||
describe('strokeWidth', () => {
|
||||
it('should default to 2', () => {
|
||||
fixture.detectChanges();
|
||||
expect(getSvgAttribute('stroke-width')).toBe('2');
|
||||
});
|
||||
it('should set stroke width', () => {
|
||||
strokeWidth.set(1.41);
|
||||
fixture.detectChanges();
|
||||
expect(getSvgAttribute('stroke-width')).toBe('1.41');
|
||||
});
|
||||
it('should allow string stroke width', () => {
|
||||
strokeWidth.set('1px');
|
||||
fixture.detectChanges();
|
||||
expect(getSvgAttribute('stroke-width')).toBe('1');
|
||||
});
|
||||
});
|
||||
|
||||
describe('absoluteStrokeWidth', () => {
|
||||
it('should not adjust stroke width', () => {
|
||||
strokeWidth.set(2);
|
||||
size.set(12);
|
||||
absoluteStrokeWidth.set(false);
|
||||
fixture.detectChanges();
|
||||
expect(getSvgAttribute('stroke-width')).toBe('2');
|
||||
});
|
||||
it('should adjust stroke width', () => {
|
||||
strokeWidth.set(2);
|
||||
size.set(12);
|
||||
absoluteStrokeWidth.set(true);
|
||||
fixture.detectChanges();
|
||||
expect(getSvgAttribute('stroke-width')).toBe('4');
|
||||
});
|
||||
});
|
||||
|
||||
describe('title', () => {
|
||||
it('should set title if provided', () => {
|
||||
title.set('Foobar');
|
||||
fixture.detectChanges();
|
||||
const titleEl = fixture.debugElement.query(By.css('title')).nativeElement;
|
||||
expect(titleEl).toBeDefined();
|
||||
expect(titleEl.textContent).toBe('Foobar');
|
||||
});
|
||||
it('should not set aria-hidden when title is set', () => {
|
||||
title.set('Foobar');
|
||||
fixture.detectChanges();
|
||||
expect(getSvgAttribute('aria-hidden')).toBeUndefined;
|
||||
});
|
||||
it('should set aria-hidden if no title is provided', () => {
|
||||
title.set(undefined);
|
||||
fixture.detectChanges();
|
||||
expect(getSvgAttribute('aria-hidden')).toBeUndefined;
|
||||
});
|
||||
});
|
||||
|
||||
describe('content projection', () => {
|
||||
it('should project content', () => {
|
||||
const hostFixture = TestBed.createComponent(TestHostComponent);
|
||||
hostFixture.componentRef.setInput('icon', testIcon);
|
||||
hostFixture.detectChanges();
|
||||
hostFixture.componentRef.setInput('icon', testIcon2);
|
||||
hostFixture.detectChanges();
|
||||
const rect = hostFixture.debugElement.query(By.css('rect')).nativeElement;
|
||||
expect(rect).toBeInstanceOf(SVGElement);
|
||||
expect(rect.outerHTML).toBe('<rect x="1" y="1" width="22" height="22"></rect>');
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -1,65 +0,0 @@
|
||||
import { Component, computed, inject, input } from '@angular/core';
|
||||
import { isLucideIconComponent, isLucideIconData, LucideIconInput } from './types';
|
||||
import { LucideIconBase } from './lucide-icon-base';
|
||||
import { LUCIDE_ICONS } from './lucide-icons';
|
||||
import { LucideIconData } from './types';
|
||||
import { toKebabCase } from './utils/to-kebab-case';
|
||||
|
||||
interface LucideResolvedIcon {
|
||||
name?: string | null;
|
||||
data: LucideIconData;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generic icon component for rendering LucideIconData.
|
||||
*/
|
||||
@Component({
|
||||
selector: 'svg[lucideIcon]',
|
||||
templateUrl: './lucide-icon.html',
|
||||
standalone: true,
|
||||
})
|
||||
export class LucideIcon extends LucideIconBase {
|
||||
protected readonly icons = inject(LUCIDE_ICONS);
|
||||
readonly name = input<string | null>();
|
||||
readonly iconInput = input.required<LucideIconInput | null>({
|
||||
alias: 'lucideIcon',
|
||||
});
|
||||
readonly resolvedIcon = computed<LucideResolvedIcon | null>(() => {
|
||||
return this.resolveIcon(this.name(), this.iconInput());
|
||||
});
|
||||
protected override readonly iconName = computed(() => {
|
||||
return this.resolvedIcon()?.name;
|
||||
});
|
||||
protected override readonly iconData = computed(() => {
|
||||
return this.resolvedIcon()?.data;
|
||||
});
|
||||
|
||||
protected resolveIcon(
|
||||
name: string | null | undefined,
|
||||
icon: LucideIconInput | null | undefined,
|
||||
): LucideResolvedIcon | null {
|
||||
if (isLucideIconData(icon)) {
|
||||
return {
|
||||
name,
|
||||
data: icon,
|
||||
};
|
||||
} else if (isLucideIconComponent(icon)) {
|
||||
return {
|
||||
name: name ?? icon.iconName,
|
||||
data: icon.iconData,
|
||||
};
|
||||
} else if (typeof icon === 'string') {
|
||||
const name = toKebabCase(icon);
|
||||
if (name in this.icons) {
|
||||
return {
|
||||
name,
|
||||
data: this.icons[name],
|
||||
};
|
||||
} else {
|
||||
throw new Error(`Unable to resolve icon '${icon}'`);
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -1,44 +0,0 @@
|
||||
import { TestBed } from '@angular/core/testing';
|
||||
import { LUCIDE_ICONS, provideLucideIcons } from './lucide-icons';
|
||||
import { LucideIconData } from './types';
|
||||
import { LucideActivity } from './icons/activity';
|
||||
import { LucideCircle } from './icons/circle';
|
||||
import { LucideSquareX } from './icons/square-x';
|
||||
|
||||
describe('Lucide icons', () => {
|
||||
describe('LUCIDE_ICONS', () => {
|
||||
it('should default to empty map', () => {
|
||||
expect(TestBed.inject(LUCIDE_ICONS)).toEqual({});
|
||||
});
|
||||
});
|
||||
describe('provideLucideIcons', () => {
|
||||
const mockIcon: LucideIconData = [['polyline', { points: '1 1 22 22' }]];
|
||||
const mockIcon2: LucideIconData = [['circle', { cx: 12, cy: 12, r: 8 }]];
|
||||
it('should accept dictionary of icons', () => {
|
||||
TestBed.configureTestingModule({
|
||||
providers: [
|
||||
provideLucideIcons({
|
||||
DemoIcon: mockIcon,
|
||||
MockIcon: mockIcon2,
|
||||
TestIcon: LucideActivity,
|
||||
}),
|
||||
],
|
||||
});
|
||||
expect(TestBed.inject(LUCIDE_ICONS)).toEqual({
|
||||
'demo-icon': mockIcon,
|
||||
'mock-icon': mockIcon2,
|
||||
[LucideActivity.iconName]: LucideActivity.iconData,
|
||||
});
|
||||
});
|
||||
it('should accept list of icon components', () => {
|
||||
TestBed.configureTestingModule({
|
||||
providers: [provideLucideIcons([LucideActivity, LucideSquareX, LucideCircle])],
|
||||
});
|
||||
expect(TestBed.inject(LUCIDE_ICONS)).toEqual({
|
||||
[LucideActivity.iconName]: LucideActivity.iconData,
|
||||
[LucideSquareX.iconName]: LucideSquareX.iconData,
|
||||
[LucideCircle.iconName]: LucideCircle.iconData,
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -1,64 +0,0 @@
|
||||
import { InjectionToken, Provider } from '@angular/core';
|
||||
import { LucideIconData, LucideIcons } from './types';
|
||||
import { isLucideIconComponent, LucideIconComponentType } from './types';
|
||||
import { toKebabCase } from './utils/to-kebab-case';
|
||||
|
||||
/**
|
||||
* Injection token for providing Lucide icons by name.
|
||||
*
|
||||
* @internal Use {@link provideLucideConfig}
|
||||
*/
|
||||
export const LUCIDE_ICONS = new InjectionToken<LucideIcons>('Lucide icons', {
|
||||
factory: () => ({}),
|
||||
});
|
||||
|
||||
/**
|
||||
* Provide Lucide icons by name.
|
||||
*
|
||||
* @remarks
|
||||
* Warning! This provider will convert dictionary keys to lower-kebab-case.
|
||||
*
|
||||
* @param icons Either a dictionary of icons or a list of Angular icon components.
|
||||
*
|
||||
* @usage
|
||||
* ```ts
|
||||
* import { provideLucideIcons, SquareCheck } from '@lucide/angular';
|
||||
* import { MyCustomIcon } from './custom-icons/circle-check';
|
||||
*
|
||||
* providers: [
|
||||
* provideLucideIcons({
|
||||
* SquareCheck,
|
||||
* MyCustomIcon, // LucideIconData
|
||||
* }),
|
||||
* ]
|
||||
* ```
|
||||
*
|
||||
* ```html
|
||||
* <svg lucideIcon="my-custom-icon" />
|
||||
* ```
|
||||
*/
|
||||
export function provideLucideIcons(
|
||||
icons: Record<string, LucideIconData | LucideIconComponentType> | Array<LucideIconComponentType>,
|
||||
): Provider {
|
||||
if (Array.isArray(icons)) {
|
||||
return {
|
||||
provide: LUCIDE_ICONS,
|
||||
useValue: icons.reduce((acc, icon) => {
|
||||
acc[toKebabCase(icon.iconName)] = icon.iconData;
|
||||
return acc;
|
||||
}, {} as LucideIcons),
|
||||
};
|
||||
} else {
|
||||
return {
|
||||
provide: LUCIDE_ICONS,
|
||||
useValue: Object.entries(icons).reduce((acc, [name, icon]) => {
|
||||
if (isLucideIconComponent(icon)) {
|
||||
acc[icon.iconName] = icon.iconData;
|
||||
} else {
|
||||
acc[toKebabCase(name)] = icon;
|
||||
}
|
||||
return acc;
|
||||
}, {} as LucideIcons),
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
import * as icons from './icons/lucide-angular';
|
||||
|
||||
export * from './lucide-config';
|
||||
export * from './lucide-icon';
|
||||
export * from './lucide-icons';
|
||||
export * from './types';
|
||||
export * from './icons/lucide-angular';
|
||||
export { icons };
|
||||
@@ -1,47 +0,0 @@
|
||||
import { Signal, Type } from '@angular/core';
|
||||
|
||||
type HtmlAttributes = { [key: string]: string | number };
|
||||
export type LucideIconNode = readonly [string, HtmlAttributes];
|
||||
export type LucideIconData = readonly LucideIconNode[];
|
||||
export type LucideIcons = { [key: string]: LucideIconData };
|
||||
|
||||
/**
|
||||
* Represents a Lucide icon component that has `iconName` and `iconData` signals inherited from `LucideIconBase` and respective static members accessible without instantiating the component.
|
||||
*/
|
||||
export type LucideIconComponentType = Type<{
|
||||
title: Signal<Nullable<string>>;
|
||||
size: Signal<Nullable<number>>;
|
||||
color: Signal<Nullable<string>>;
|
||||
strokeWidth: Signal<Nullable<number>>;
|
||||
absoluteStrokeWidth: Signal<Nullable<boolean>>;
|
||||
}> & {
|
||||
iconName: string;
|
||||
iconData: LucideIconData;
|
||||
};
|
||||
|
||||
/**
|
||||
* Type guard for {@link LucideIconData}
|
||||
*/
|
||||
export function isLucideIconData(icon: unknown): icon is LucideIconData {
|
||||
return Array.isArray(icon);
|
||||
}
|
||||
|
||||
/**
|
||||
* Type guard for {@link LucideIconComponentType}
|
||||
*/
|
||||
export function isLucideIconComponent(icon: unknown): icon is LucideIconComponentType {
|
||||
return (
|
||||
icon instanceof Type &&
|
||||
'iconData' in icon &&
|
||||
Array.isArray(icon.iconData) &&
|
||||
'iconName' in icon &&
|
||||
typeof icon.iconName === 'string'
|
||||
);
|
||||
}
|
||||
|
||||
export type LucideIconInput = LucideIconComponentType | LucideIconData | string;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
export type Nullable<T> = T | null | undefined;
|
||||
@@ -1,3 +0,0 @@
|
||||
export function formatFixed(number: number, decimals = 3): string {
|
||||
return parseFloat(number.toFixed(decimals)).toString(10);
|
||||
}
|
||||
@@ -1,2 +0,0 @@
|
||||
export const toKebabCase = (name: string) =>
|
||||
name.replace(/([a-z0-9])([A-Z])/g, '$1-$2').toLowerCase();
|
||||
@@ -1,38 +0,0 @@
|
||||
/* To learn more about Typescript configuration file: https://www.typescriptlang.org/docs/handbook/tsconfig-json.html. */
|
||||
/* To learn more about Angular compiler options: https://angular.dev/reference/configs/angular-compiler-options. */
|
||||
{
|
||||
"compileOnSave": false,
|
||||
"compilerOptions": {
|
||||
"paths": {
|
||||
"@lucide/angular": ["./dist"],
|
||||
},
|
||||
"strict": true,
|
||||
"noImplicitOverride": true,
|
||||
"noPropertyAccessFromIndexSignature": true,
|
||||
"noImplicitReturns": true,
|
||||
"noFallthroughCasesInSwitch": true,
|
||||
"skipLibCheck": true,
|
||||
"isolatedModules": true,
|
||||
"declaration": false,
|
||||
"downlevelIteration": true,
|
||||
"experimentalDecorators": true,
|
||||
"importHelpers": true,
|
||||
"target": "ES2022",
|
||||
"module": "preserve",
|
||||
},
|
||||
"angularCompilerOptions": {
|
||||
"enableI18nLegacyMessageIdFormat": false,
|
||||
"strictInjectionParameters": true,
|
||||
"strictInputAccessModifiers": true,
|
||||
"strictTemplates": true,
|
||||
},
|
||||
"files": [],
|
||||
"references": [
|
||||
{
|
||||
"path": "./tsconfig.lib.json",
|
||||
},
|
||||
{
|
||||
"path": "./tsconfig.spec.json",
|
||||
},
|
||||
],
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
/* To learn more about Typescript configuration file: https://www.typescriptlang.org/docs/handbook/tsconfig-json.html. */
|
||||
/* To learn more about Angular compiler options: https://angular.dev/reference/configs/angular-compiler-options. */
|
||||
{
|
||||
"extends": "./tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "./out-tsc/lib",
|
||||
"declaration": true,
|
||||
"declarationMap": true,
|
||||
"inlineSources": true,
|
||||
"types": []
|
||||
},
|
||||
"include": ["src/**/*.ts"],
|
||||
"exclude": ["**/*.spec.ts"]
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
/* To learn more about Typescript configuration file: https://www.typescriptlang.org/docs/handbook/tsconfig-json.html. */
|
||||
/* To learn more about Angular compiler options: https://angular.dev/reference/configs/angular-compiler-options. */
|
||||
{
|
||||
"extends": "./tsconfig.lib.json",
|
||||
"compilerOptions": {
|
||||
"declarationMap": false
|
||||
},
|
||||
"angularCompilerOptions": {
|
||||
"compilationMode": "partial"
|
||||
}
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
/* To learn more about Typescript configuration file: https://www.typescriptlang.org/docs/handbook/tsconfig-json.html. */
|
||||
/* To learn more about Angular compiler options: https://angular.dev/reference/configs/angular-compiler-options. */
|
||||
{
|
||||
"extends": "./tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "./out-tsc/spec",
|
||||
"types": ["vitest/globals"]
|
||||
},
|
||||
"include": ["src/**/*.d.ts", "src/**/*.spec.ts"]
|
||||
}
|
||||
@@ -24,9 +24,7 @@
|
||||
"author": "Eric Fennis",
|
||||
"amdName": "lucide-preact",
|
||||
"main": "dist/cjs/lucide-preact.js",
|
||||
"main:umd": "dist/umd/lucide-preact.js",
|
||||
"module": "dist/esm/lucide-preact.js",
|
||||
"unpkg": "dist/umd/lucide-preact.min.js",
|
||||
"typings": "dist/lucide-preact.d.ts",
|
||||
"files": [
|
||||
"dist"
|
||||
@@ -39,6 +37,7 @@
|
||||
"build:icons": "build-icons --output=./src --templateSrc=./scripts/exportTemplate.mts --renderUniqueKey --withAliases --aliasesFileExtension=.ts --iconFileExtension=.ts --exportFileName=index.ts",
|
||||
"build:bundles": "rollup -c ./rollup.config.mjs",
|
||||
"test": "pnpm build:icons && vitest run",
|
||||
"test:watch": "vitest watch",
|
||||
"version": "pnpm version --git-tag-version=false"
|
||||
},
|
||||
"devDependencies": {
|
||||
@@ -46,10 +45,10 @@
|
||||
"@lucide/rollup-plugins": "workspace:*",
|
||||
"@lucide/shared": "workspace:*",
|
||||
"@preact/preset-vite": "^2.10.2",
|
||||
"@testing-library/jest-dom": "^6.1.4",
|
||||
"@testing-library/jest-dom": "^6.6.3",
|
||||
"@testing-library/preact": "^3.2.3",
|
||||
"jest-serializer-html": "^7.1.0",
|
||||
"preact": "^10.19.2",
|
||||
"preact": "^10.26.9",
|
||||
"rollup": "^4.53.3",
|
||||
"rollup-plugin-dts": "^6.2.3",
|
||||
"typescript": "^5.8.3",
|
||||
|
||||
@@ -7,17 +7,6 @@ const outputFileName = 'lucide-preact';
|
||||
const outputDir = 'dist';
|
||||
const inputs = [`src/lucide-preact.ts`];
|
||||
const bundles = [
|
||||
{
|
||||
format: 'umd',
|
||||
inputs,
|
||||
outputDir,
|
||||
minify: true,
|
||||
},
|
||||
{
|
||||
format: 'umd',
|
||||
inputs,
|
||||
outputDir,
|
||||
},
|
||||
{
|
||||
format: 'cjs',
|
||||
inputs,
|
||||
@@ -32,7 +21,7 @@ const bundles = [
|
||||
];
|
||||
|
||||
const configs = bundles
|
||||
.map(({ inputs, outputDir, format, minify, preserveModules }) =>
|
||||
.map(({ inputs, outputDir, format, preserveModules }) =>
|
||||
inputs.map((input) => ({
|
||||
input,
|
||||
plugins: plugins({ pkg, minify }),
|
||||
@@ -44,7 +33,7 @@ const configs = bundles
|
||||
dir: `${outputDir}/${format}`,
|
||||
}
|
||||
: {
|
||||
file: `${outputDir}/${format}/${outputFileName}${minify ? '.min' : ''}.js`,
|
||||
file: `${outputDir}/${format}/${outputFileName}.js`,
|
||||
}),
|
||||
preserveModules,
|
||||
format,
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import { h, toChildArray } from 'preact';
|
||||
import defaultAttributes from './defaultAttributes';
|
||||
import type { IconNode, LucideProps } from './types';
|
||||
import { useLucideContext } from './context';
|
||||
import { mergeClasses } from '@lucide/shared';
|
||||
|
||||
interface IconComponentProps extends LucideProps {
|
||||
iconNode: IconNode;
|
||||
@@ -22,29 +24,41 @@ interface IconComponentProps extends LucideProps {
|
||||
* @returns {ForwardRefExoticComponent} LucideIcon
|
||||
*/
|
||||
const Icon = ({
|
||||
color = 'currentColor',
|
||||
size = 24,
|
||||
strokeWidth = 2,
|
||||
color,
|
||||
size,
|
||||
strokeWidth,
|
||||
absoluteStrokeWidth,
|
||||
children,
|
||||
iconNode,
|
||||
class: classes = '',
|
||||
...rest
|
||||
}: IconComponentProps) =>
|
||||
h(
|
||||
}: IconComponentProps) => {
|
||||
const {
|
||||
size: contextSize = 24,
|
||||
strokeWidth: contextStrokeWidth = 2,
|
||||
absoluteStrokeWidth: contextAbsoluteStrokeWidth = false,
|
||||
color: contextColor = 'currentColor',
|
||||
class: contextClass = '',
|
||||
} = useLucideContext() ?? {};
|
||||
|
||||
const calculatedStrokeWidth =
|
||||
absoluteStrokeWidth ?? contextAbsoluteStrokeWidth
|
||||
? (Number(strokeWidth ?? contextStrokeWidth) * 24) / Number(size ?? contextSize)
|
||||
: strokeWidth ?? contextStrokeWidth;
|
||||
|
||||
return h(
|
||||
'svg',
|
||||
{
|
||||
...defaultAttributes,
|
||||
width: String(size),
|
||||
height: size,
|
||||
stroke: color,
|
||||
['stroke-width' as 'strokeWidth']: absoluteStrokeWidth
|
||||
? (Number(strokeWidth) * 24) / Number(size)
|
||||
: strokeWidth,
|
||||
class: ['lucide', classes].join(' '),
|
||||
width: size ?? contextSize ?? 24,
|
||||
height: size ?? contextSize ?? 24,
|
||||
stroke: color ?? contextColor,
|
||||
['stroke-width' as 'strokeWidth']: calculatedStrokeWidth,
|
||||
class: mergeClasses('lucide', contextClass, classes),
|
||||
...rest,
|
||||
},
|
||||
[...iconNode.map(([tag, attrs]) => h(tag, attrs)), ...toChildArray(children)],
|
||||
);
|
||||
};
|
||||
|
||||
export default Icon;
|
||||
|
||||
49
packages/lucide-preact/src/context.tsx
Normal file
@@ -0,0 +1,49 @@
|
||||
import { createContext, type ComponentChildren } from 'preact';
|
||||
import { useContext, useMemo } from 'preact/hooks';
|
||||
|
||||
const LucideContext = createContext<{
|
||||
size?: number;
|
||||
color?: string;
|
||||
strokeWidth?: number;
|
||||
absoluteStrokeWidth?: boolean;
|
||||
class?: string;
|
||||
}>({
|
||||
size: 24,
|
||||
color: 'currentColor',
|
||||
strokeWidth: 2,
|
||||
absoluteStrokeWidth: false,
|
||||
class: '',
|
||||
});
|
||||
|
||||
interface LucideProviderProps {
|
||||
children: ComponentChildren;
|
||||
size?: number;
|
||||
color?: string;
|
||||
strokeWidth?: number;
|
||||
absoluteStrokeWidth?: boolean;
|
||||
class?: string;
|
||||
}
|
||||
|
||||
export function LucideProvider({
|
||||
children,
|
||||
size,
|
||||
color,
|
||||
strokeWidth,
|
||||
absoluteStrokeWidth,
|
||||
class: className,
|
||||
}: LucideProviderProps) {
|
||||
const value = useMemo(
|
||||
() => ({
|
||||
size,
|
||||
color,
|
||||
strokeWidth,
|
||||
absoluteStrokeWidth,
|
||||
class: className,
|
||||
}),
|
||||
[size, color, strokeWidth, absoluteStrokeWidth, className],
|
||||
);
|
||||
|
||||
return <LucideContext.Provider value={value}>{children}</LucideContext.Provider>;
|
||||
}
|
||||
|
||||
export const useLucideContext = () => useContext(LucideContext);
|
||||
@@ -2,6 +2,7 @@ export * from './icons';
|
||||
export * as icons from './icons';
|
||||
export * from './aliases';
|
||||
export * from './types';
|
||||
export * from './context';
|
||||
|
||||
export { default as createLucideIcon } from './createLucideIcon';
|
||||
export { default as Icon } from './Icon';
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
|
||||
|
||||
exports[`Using LucideProvider > should render the icon with LucideProvider 1`] = `
|
||||
<svg
|
||||
class="lucide lucide-house"
|
||||
fill="none"
|
||||
height="48"
|
||||
stroke="red"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
viewBox="0 0 24 24"
|
||||
width="48"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M15 21v-8a1 1 0 0 0-1-1h-4a1 1 0 0 0-1 1v8"
|
||||
/>
|
||||
<path
|
||||
d="M3 10a2 2 0 0 1 .709-1.528l7-6a2 2 0 0 1 2.582 0l7 6A2 2 0 0 1 21 10v9a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"
|
||||
/>
|
||||
</svg>
|
||||
`;
|
||||