mirror of
https://github.com/lucide-icons/lucide.git
synced 2026-11-10 13:18:25 +00:00
feat(packages): extract icon build logic into @lucide/shared (#4409)
* feat(packages): extract build logic to @lucide/shared, still wip * feat(): unify icon build logic some more, add nonScalingStroke option, marking absoluteStrokeWidth as deprecated * feat(): unify icon build logic some more, add nonScalingStroke option, marking absoluteStrokeWidth as deprecated * feat(packages): extract build logic to @lucide/shared, still wip * feat(): unify icon build logic some more, add nonScalingStroke option, marking absoluteStrokeWidth as deprecated * feat(): unify icon build logic some more, add nonScalingStroke option, marking absoluteStrokeWidth as deprecated * chore(icons): revert git hook changes made to icons * fix(packages/astro,react-native,vue): fix iconNode type fix(packages/vue): fix hasA11yProp * fix(packages/solid): make component reactive & add unit tests for checking prop changes * test(packages/vue): add reactivity tests to @lucide/vue * fix(packages): replace cpy-cli, accidentally removed during main merge * docs(packages): upgrade react documentation with nonScalingStroke * fix(tests): update snapshots for lucide-react * feat(docs): upgraded package guides with nonScalingStroke, dropping absoluteStrokeWidth * fix(vue,react-native): fix linting issues * fix(icons): add proper fallback for icon width in calculatedStrokeWidth * fix(packages/svelte): add globalProps.class to icons * fix(packages/shared): wrap width, height & size in isDefined * Update types.ts * fix(packages/svelte): do not pass propsClass to mergeClasses --------- Co-authored-by: Eric Fennis <eric.fennis@gmail.com>
This commit is contained in:
@@ -28,6 +28,9 @@ packages/**/src/aliases.ts
|
||||
!packages/**/src/aliases/index.ts
|
||||
packages/**/src/utils/*.ts
|
||||
!packages/shared/src/utils/*.ts
|
||||
!packages/shared/src/build/
|
||||
!packages/shared/src/build/*.ts
|
||||
packages/shared/src/build/types.d.ts
|
||||
packages/**/src/dynamicIconImports.ts
|
||||
packages/**/DynamicIcon.d.ts
|
||||
packages/**/dynamicIconImports.js
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
title: Combining icons - Angular
|
||||
description: Learn how to combine multiple icons into a single icon nested SVG elements in your Angular application.
|
||||
---
|
||||
|
||||
<script setup>
|
||||
import Sandpack from '~/.vitepress/theme/components/editors/SandpackAngular.vue'
|
||||
</script>
|
||||
@@ -14,28 +15,32 @@ This is useful for if you want to be creative and make your own custom icons by
|
||||
::: sandpack {template=angular showTabs=false editorHeight=400 editorWidthPercentage=60 dependencies="@lucide/angular"}
|
||||
|
||||
```ts /src/app/app.component.ts [active]
|
||||
import { Component, ViewEncapsulation } from "@angular/core";
|
||||
import { LucideScan, LucideUser } from "@lucide/angular";
|
||||
import { Component, ViewEncapsulation } from '@angular/core';
|
||||
import { LucideScan, LucideUser } from '@lucide/angular';
|
||||
|
||||
@Component({
|
||||
selector: 'app',
|
||||
imports: [LucideScan, LucideUser],
|
||||
template: `
|
||||
<svg lucideScan [size]="48">
|
||||
<svg lucideUser
|
||||
[size]="12"
|
||||
x="6"
|
||||
y="6"
|
||||
[strokeWidth]="4"
|
||||
[absoluteStrokeWidth]="true"
|
||||
/>
|
||||
</svg>`,
|
||||
template: ` <svg
|
||||
lucideScan
|
||||
[size]="48"
|
||||
[nonScalingStroke]="true"
|
||||
>
|
||||
<svg
|
||||
lucideUser
|
||||
[size]="12"
|
||||
x="6"
|
||||
y="6"
|
||||
[strokeWidth]="4"
|
||||
[nonScalingStroke]="true"
|
||||
/>
|
||||
</svg>`,
|
||||
styleUrls: ['./app.component.css'],
|
||||
encapsulation: ViewEncapsulation.None,
|
||||
})
|
||||
export class App {
|
||||
}
|
||||
export class App {}
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
This is valid SVG and all SVG properties are supported on the icons.
|
||||
@@ -53,28 +58,29 @@ You can also use SVG elements to create your own icons.
|
||||
|
||||
For example, you can add a notification badge to an icon by using the `circle` SVG element.
|
||||
|
||||
|
||||
::: sandpack {template=angular showTabs=false editorHeight=400 editorWidthPercentage=60 dependencies="@lucide/angular"}
|
||||
|
||||
```ts /src/app/app.component.ts [active]
|
||||
import { Component, ViewEncapsulation, signal } from "@angular/core";
|
||||
import { LucideMail } from "@lucide/angular";
|
||||
import { Component, ViewEncapsulation, signal } from '@angular/core';
|
||||
import { LucideMail } from '@lucide/angular';
|
||||
|
||||
@Component({
|
||||
selector: 'app',
|
||||
imports: [LucideMail],
|
||||
template: `
|
||||
<svg lucideMail [size]="48">
|
||||
@if (hasUnreadMessages()) {
|
||||
<circle
|
||||
r="3"
|
||||
cx="21"
|
||||
cy="5"
|
||||
stroke="none"
|
||||
fill="#F56565"
|
||||
/>
|
||||
}
|
||||
</svg>`,
|
||||
template: ` <svg
|
||||
lucideMail
|
||||
[size]="48"
|
||||
>
|
||||
@if (hasUnreadMessages()) {
|
||||
<circle
|
||||
r="3"
|
||||
cx="21"
|
||||
cy="5"
|
||||
stroke="none"
|
||||
fill="#F56565"
|
||||
/>
|
||||
}
|
||||
</svg>`,
|
||||
styleUrls: ['./app.component.css'],
|
||||
encapsulation: ViewEncapsulation.None,
|
||||
})
|
||||
@@ -82,38 +88,40 @@ export class App {
|
||||
protected readonly hasUnreadMessages = signal<boolean>(true);
|
||||
}
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
### Example with text element
|
||||
|
||||
You can also use the `text` SVG element to add text to your icon.
|
||||
|
||||
|
||||
::: sandpack {template=angular showTabs=false editorHeight=400 editorWidthPercentage=60 dependencies="@lucide/angular"}
|
||||
|
||||
```ts /src/app/app.component.ts [active]
|
||||
import { Component, ViewEncapsulation } from "@angular/core";
|
||||
import { LucideFile } from "@lucide/angular";
|
||||
import { Component, ViewEncapsulation } from '@angular/core';
|
||||
import { LucideFile } from '@lucide/angular';
|
||||
|
||||
@Component({
|
||||
selector: 'app',
|
||||
imports: [LucideFile],
|
||||
template: `
|
||||
<svg lucideFile [size]="48">
|
||||
<text
|
||||
x="7.5"
|
||||
y="19"
|
||||
font-size="8"
|
||||
font-family="Verdana,sans-serif"
|
||||
stroke-width="1"
|
||||
>
|
||||
JS
|
||||
</text>
|
||||
</svg>`,
|
||||
template: ` <svg
|
||||
lucideFile
|
||||
[size]="48"
|
||||
>
|
||||
<text
|
||||
x="7.5"
|
||||
y="19"
|
||||
font-size="8"
|
||||
font-family="Verdana,sans-serif"
|
||||
stroke-width="1"
|
||||
>
|
||||
JS
|
||||
</text>
|
||||
</svg>`,
|
||||
styleUrls: ['./app.component.css'],
|
||||
encapsulation: ViewEncapsulation.None,
|
||||
})
|
||||
export class App {
|
||||
}
|
||||
export class App {}
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
title: Global Styling - Angular
|
||||
description: Learn how to style all icons globally in your Angular application using CSS or the provideLucideConfig provider.
|
||||
---
|
||||
|
||||
<script setup>
|
||||
import Sandpack from '~/.vitepress/theme/components/editors/SandpackAngular.vue'
|
||||
</script>
|
||||
@@ -29,9 +30,9 @@ import { provideLucideConfig } from '@lucide/angular';
|
||||
export const appConfig: ApplicationConfig = {
|
||||
providers: [
|
||||
provideLucideConfig({
|
||||
strokeWidth: 1.5
|
||||
strokeWidth: 1.5,
|
||||
}),
|
||||
]
|
||||
],
|
||||
};
|
||||
```
|
||||
|
||||
@@ -65,7 +66,7 @@ All Lucide icons include the `lucide` class. You can use this class in your styl
|
||||
```
|
||||
|
||||
```ts /src/app/app.component.ts
|
||||
import { Component, ViewEncapsulation } from "@angular/core";
|
||||
import { Component, ViewEncapsulation } from '@angular/core';
|
||||
import {
|
||||
LucideCakeSlice,
|
||||
LucideCandy,
|
||||
@@ -76,7 +77,7 @@ import {
|
||||
LucideSandwich,
|
||||
LucideWine,
|
||||
LucideDessert,
|
||||
} from "@lucide/angular";
|
||||
} from '@lucide/angular';
|
||||
|
||||
@Component({
|
||||
selector: 'app',
|
||||
@@ -92,28 +93,27 @@ import {
|
||||
LucideDessert,
|
||||
],
|
||||
template: `<div class="grid">
|
||||
<svg lucideCakeSlice />
|
||||
<svg lucideCandy />
|
||||
<svg lucideApple />
|
||||
<svg lucideCookie />
|
||||
<svg lucideMartini />
|
||||
<svg lucideIceCream2 />
|
||||
<svg lucideSandwich />
|
||||
<svg lucideWine />
|
||||
<svg lucideDessert />
|
||||
</div>`,
|
||||
<svg lucideCakeSlice />
|
||||
<svg lucideCandy />
|
||||
<svg lucideApple />
|
||||
<svg lucideCookie />
|
||||
<svg lucideMartini />
|
||||
<svg lucideIceCream2 />
|
||||
<svg lucideSandwich />
|
||||
<svg lucideWine />
|
||||
<svg lucideDessert />
|
||||
</div>`,
|
||||
styleUrls: ['./app.component.css', './icon.css'],
|
||||
encapsulation: ViewEncapsulation.None,
|
||||
})
|
||||
export class App {
|
||||
}
|
||||
export class App {}
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
### Absolute stroke width
|
||||
### Non-scaling strokes
|
||||
|
||||
To keep the stroke width constant regardless of icon size, apply `vector-effect: non-scaling-stroke` to the icon's children. See [absolute-stroke-width](../basics/stroke-width.md#absolute-stroke-width) for more details.
|
||||
To keep the stroke width constant regardless of icon size, apply `vector-effect: non-scaling-stroke` to the icon's children. See [non-scaling strokes](../basics/stroke-width.md#non-scaling-strokes) for more details.
|
||||
|
||||
::: sandpack {template=angular editorHeight=300 dependencies="@lucide/angular"}
|
||||
|
||||
@@ -137,7 +137,7 @@ To keep the stroke width constant regardless of icon size, apply `vector-effect:
|
||||
```
|
||||
|
||||
```ts /src/app/app.component.ts
|
||||
import { Component, ViewEncapsulation } from "@angular/core";
|
||||
import { Component, ViewEncapsulation } from '@angular/core';
|
||||
import {
|
||||
LucideTentTree,
|
||||
LucideCaravan,
|
||||
@@ -148,7 +148,7 @@ import {
|
||||
LucideMap,
|
||||
LucideCloudMoon,
|
||||
LucideSparkles,
|
||||
} from "@lucide/angular";
|
||||
} from '@lucide/angular';
|
||||
|
||||
@Component({
|
||||
selector: 'app',
|
||||
@@ -164,21 +164,20 @@ import {
|
||||
LucideSparkles,
|
||||
],
|
||||
template: `<div class="grid">
|
||||
<svg lucideTentTree />
|
||||
<svg lucideCaravan />
|
||||
<svg lucideFlameKindling />
|
||||
<svg lucideMountainSnow />
|
||||
<svg lucideTrees />
|
||||
<svg lucideAxe />
|
||||
<svg lucideMap />
|
||||
<svg lucideCloudMoon />
|
||||
<svg lucideSparkles />
|
||||
</div>`,
|
||||
<svg lucideTentTree />
|
||||
<svg lucideCaravan />
|
||||
<svg lucideFlameKindling />
|
||||
<svg lucideMountainSnow />
|
||||
<svg lucideTrees />
|
||||
<svg lucideAxe />
|
||||
<svg lucideMap />
|
||||
<svg lucideCloudMoon />
|
||||
<svg lucideSparkles />
|
||||
</div>`,
|
||||
styleUrls: ['./app.component.css', './icon.css'],
|
||||
encapsulation: ViewEncapsulation.None,
|
||||
})
|
||||
export class App {
|
||||
}
|
||||
export class App {}
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
---
|
||||
title: Stroke width - Angular
|
||||
description: Learn how to adjust the stroke width of icons in your Angular application using the `strokeWidth` input or adjust the strokeWidth appearance using the `absoluteStrokeWidth` input.
|
||||
description: Learn how to adjust the stroke width of icons in your Angular application using the `strokeWidth` input or adjust the strokeWidth appearance using the `nonScalingStroke` input.
|
||||
---
|
||||
|
||||
<script setup>
|
||||
import Sandpack from '~/.vitepress/theme/components/editors/SandpackAngular.vue'
|
||||
</script>
|
||||
@@ -18,55 +19,58 @@ The `strokeWidth` can be adjusted to create a different look of the icons.
|
||||
::: sandpack {template=angular showTabs=false editorHeight=400 editorWidthPercentage=60 dependencies="@lucide/angular"}
|
||||
|
||||
```ts /src/app/app.component.ts [active]
|
||||
import { Component, ViewEncapsulation } from "@angular/core";
|
||||
import { LucideFolderLock } from "@lucide/angular";
|
||||
import { Component, ViewEncapsulation } from '@angular/core';
|
||||
import { LucideFolderLock } from '@lucide/angular';
|
||||
|
||||
@Component({
|
||||
selector: 'app',
|
||||
imports: [LucideFolderLock],
|
||||
template: `<svg lucideFolderLock [strokeWidth]="1" />`,
|
||||
template: `<svg
|
||||
lucideFolderLock
|
||||
[strokeWidth]="1"
|
||||
/>`,
|
||||
styleUrls: ['./app.component.css'],
|
||||
encapsulation: ViewEncapsulation.None,
|
||||
})
|
||||
export class App {
|
||||
}
|
||||
export class App {}
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
## Absolute stroke width
|
||||
## Non-scaling strokes
|
||||
|
||||
When binding the `size` input, the icon's stroke width will be relative to its size, this is the default SVG behavior. The `absoluteStrokeWidth` input is introduced to adjust this behavior to make the stroke width constant no matter the size of the icon.
|
||||
When binding the `size` input, the icon's stroke width will be relative to its size, this is the default SVG behavior. The `nonScalingStroke` input is introduced to adjust this behavior to make the stroke width constant no matter the size of the icon.
|
||||
|
||||
This means that when `absoluteStrokeWidth` is enabled and the `size` of the icons is set to `48px` the `strokeWidth` will still be `2px` on the screen.
|
||||
This means that when `nonScalingStroke` is enabled and the `size` of the icons is set to `48px` the `strokeWidth` will still be `2px` on the screen.
|
||||
|
||||
Note `2px` is the default stroke width for a Lucide icon, this can be adjusted to all sizes.
|
||||
|
||||

|
||||
<!--@include: ../../../images/non-scaling-stroke-compare.svg -->
|
||||
|
||||
### Adjusting stroke width with `absoluteStrokeWidth` input
|
||||
### Adjusting stroke width with `nonScalingStroke` input
|
||||
|
||||
Setting `absoluteStrokeWidth` to `true` will make the stroke width absolute.
|
||||
Setting `nonScalingStroke` to `true` will make the stroke width non-scaling.
|
||||
|
||||
::: sandpack {template=angular showTabs=false editorHeight=400 editorWidthPercentage=60 dependencies="@lucide/angular"}
|
||||
|
||||
```ts /src/app/app.component.ts [active]
|
||||
import { Component, ViewEncapsulation } from "@angular/core";
|
||||
import { LucideRollerCoaster } from "@lucide/angular";
|
||||
import { Component, ViewEncapsulation } from '@angular/core';
|
||||
import { LucideRollerCoaster } from '@lucide/angular';
|
||||
|
||||
@Component({
|
||||
selector: 'app',
|
||||
imports: [LucideRollerCoaster],
|
||||
template: `
|
||||
<svg
|
||||
<svg
|
||||
lucideRollerCoaster
|
||||
[size]="96"
|
||||
[absoluteStrokeWidth]="true"
|
||||
[nonScalingStroke]="true"
|
||||
></svg>
|
||||
`,
|
||||
`,
|
||||
styleUrls: ['./app.component.css'],
|
||||
encapsulation: ViewEncapsulation.None,
|
||||
})
|
||||
export class App {
|
||||
}
|
||||
export class App {}
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
title: Getting started - Angular
|
||||
description: This guide will help you get started with Lucide in your Angular project.
|
||||
---
|
||||
|
||||
<script setup>
|
||||
import OverviewLink from '../../.vitepress/theme/components/base/OverviewLink.vue'
|
||||
import OverviewLinkGrid from '../../.vitepress/theme/components/base/OverviewLinkGrid.vue'
|
||||
@@ -56,7 +57,7 @@ import { LucideFileText } from '@lucide/angular';
|
||||
template: '<svg lucideFileText></svg>',
|
||||
imports: [LucideFileText],
|
||||
})
|
||||
export class App { }
|
||||
export class App {}
|
||||
```
|
||||
|
||||
### Dynamic icon component
|
||||
@@ -74,7 +75,7 @@ import { LucideDynamicIcon, LucideCircleCheck, LucideCircleX } from '@lucide/ang
|
||||
})
|
||||
export class App {
|
||||
protected readonly model = signal<boolean>(true);
|
||||
protected readonly icon = computed(() => this.model() ? LucideCircleCheck : LucideCircleX);
|
||||
protected readonly icon = computed(() => (this.model() ? LucideCircleCheck : LucideCircleX));
|
||||
}
|
||||
```
|
||||
|
||||
@@ -82,18 +83,24 @@ export class App {
|
||||
|
||||
To customize the appearance of an icon, you can use the following inputs:
|
||||
|
||||
| name | type | default |
|
||||
| ----------------------- | --------- | ------------ |
|
||||
| `size` | *number* | 24 |
|
||||
| `color` | *string* | currentColor |
|
||||
| `strokeWidth` | *number* | 2 |
|
||||
| `absoluteStrokeWidth` | *boolean* | false |
|
||||
| `title` | *string* | null |
|
||||
| name | type | default |
|
||||
| ------------------ | --------- | ------------ |
|
||||
| `size` | _number_ | 24 |
|
||||
| `color` | _string_ | currentColor |
|
||||
| `strokeWidth` | _number_ | 2 |
|
||||
| `nonScalingStroke` | _boolean_ | false |
|
||||
| `title` | _string_ | null |
|
||||
|
||||
Because icons render as SVG elements, all standard SVG attributes can also be applied. See the list of SVG Presentation Attributes on [MDN](https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/Presentation).
|
||||
|
||||
```html
|
||||
<svg lucideHouse [size]="48" color="red" [strokeWidth]="1" title="Home"></svg>
|
||||
<svg
|
||||
lucideHouse
|
||||
[size]="48"
|
||||
color="red"
|
||||
[strokeWidth]="1"
|
||||
title="Home"
|
||||
></svg>
|
||||
```
|
||||
|
||||
For more examples and details on how to use these inputs, continue the guide:
|
||||
|
||||
@@ -27,9 +27,9 @@ Every icon has a class attribute applied called `lucide`. This class name can be
|
||||
}
|
||||
```
|
||||
|
||||
### Absolute stroke width
|
||||
### Non-scaling strokes
|
||||
|
||||
For global absolute stroke width styling the `vector-effect: non-scaling-stroke` CSS property can be applied to the children. This will keep the stroke-width the same size no matter the size of the icon. See [absolute-stroke-width](../basics/stroke-width.md#absolute-stroke-width) for more info.
|
||||
For global non-scaling stroke width styling the `vector-effect: non-scaling-stroke` CSS property can be applied to the children. This will keep the stroke-width the same size no matter the size of the icon. See [non-scaling strokes](../basics/stroke-width.md#non-scaling-strokes) for more info.
|
||||
|
||||
```css
|
||||
.lucide {
|
||||
|
||||
@@ -18,13 +18,19 @@ interface LucideProps extends SVGAttributes<SVGSVGElement> {
|
||||
color?: string;
|
||||
size?: number | string;
|
||||
'stroke-width'?: number | string;
|
||||
nonScalingStroke?: boolean;
|
||||
/**
|
||||
* @deprecated
|
||||
*/
|
||||
absoluteStrokeWidth?: boolean;
|
||||
[key: string]: any; // Any other SVG attributes
|
||||
}
|
||||
```
|
||||
|
||||
### Using `IconProps`
|
||||
|
||||
<!-- Rename this to LucideProps -->
|
||||
|
||||
You can use the `IconProps` interface to type props for your custom icon components.
|
||||
|
||||
```astro
|
||||
@@ -50,7 +56,7 @@ Type for individual icon components, this is use full when you want to type a va
|
||||
import type { Component } from 'astro/types';
|
||||
import type { IconProps } from '@lucide/astro';
|
||||
|
||||
type LucideIcon = Component<IconProps>
|
||||
type LucideIcon = Component<IconProps>;
|
||||
```
|
||||
|
||||
### Using `LucideIcon`
|
||||
@@ -103,12 +109,13 @@ Not commonly used directly in application code. But can be useful for advanced u
|
||||
|
||||
```ts
|
||||
type IconNode = [
|
||||
elementName: 'circle' | 'ellipse'| 'g' | 'line' | 'path' | 'polygon' | 'polyline' | 'rect',
|
||||
attrs: HTMLAttributes<'svg'>
|
||||
elementName: 'circle' | 'ellipse' | 'g' | 'line' | 'path' | 'polygon' | 'polyline' | 'rect',
|
||||
attrs: HTMLAttributes<'svg'>,
|
||||
][];
|
||||
```
|
||||
|
||||
### Using `IconNode`
|
||||
|
||||
You can use the `IconNode` type when you need to work with the raw SVG structure of an icon.
|
||||
|
||||
```astro [CustomIcon.astro]
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
title: Stroke width - Astro
|
||||
description: Learn how to customize the stroke width of Lucide icons in your Astro applications using the strokeWidth and absoluteStrokeWidth props.
|
||||
description: Learn how to customize the stroke width of Lucide icons in your Astro applications using the strokeWidth and nonScalingStroke props.
|
||||
---
|
||||
|
||||
# Stroke width
|
||||
@@ -20,19 +20,19 @@ import FolderLock from '@lucide/astro/icons/folder-lock';
|
||||
<FolderLock strokeWidth={1} />
|
||||
```
|
||||
|
||||
## Absolute stroke width
|
||||
## Non-scaling strokes
|
||||
|
||||
When adjusting the `size` prop the size of the stroke width will be relative to the size of the icon, this is the default SVG behavior. The `absoluteStrokeWidth` prop is introduced to adjust this behavior to make the stroke width constant no matter the size of the icon.
|
||||
When adjusting the `size` prop the size of the stroke width will be relative to the size of the icon, this is the default SVG behavior. The `nonScalingStroke` prop is introduced to adjust this behavior to make the stroke width constant no matter the size of the icon.
|
||||
|
||||
This means that when `absoluteStrokeWidth` is enabled and the `size` of the icons is set to `48px` the `strokeWidth` will still be `2px` on the screen.
|
||||
This means that when `nonScalingStroke` is enabled and the `size` of the icons is set to `48px` the `strokeWidth` will still be `2px` on the screen.
|
||||
|
||||
Note `2px` is the default stroke width for a Lucide icon, this can be adjusted to all sizes.
|
||||
|
||||

|
||||
<!--@include: ../../../images/non-scaling-stroke-compare.svg -->
|
||||
|
||||
### Adjusting stroke width with `absoluteStrokeWidth` prop
|
||||
### Adjusting stroke width with `nonScalingStroke` prop
|
||||
|
||||
Setting `absoluteStrokeWidth` to `true` will make the stroke width absolute.
|
||||
Setting `nonScalingStroke` to `true` will make the stroke width non-scaling.
|
||||
|
||||
```astro
|
||||
---
|
||||
@@ -41,6 +41,6 @@ import RollerCoaster from '@lucide/astro/icons/roller-coaster';
|
||||
|
||||
<RollerCoaster
|
||||
size={96}
|
||||
absoluteStrokeWidth
|
||||
nonScalingStroke
|
||||
/>
|
||||
```
|
||||
|
||||
@@ -54,13 +54,13 @@ import { Camera } from '@lucide/astro';
|
||||
|
||||
To customize the appearance of an icon, you can use the following props:
|
||||
|
||||
| name | type | default |
|
||||
| ----------------------- | --------- | ------------ |
|
||||
| `size` | *number* | 24 |
|
||||
| `color` | *string* | currentColor |
|
||||
| `stroke-width` | *number* | 2 |
|
||||
| `absoluteStrokeWidth` | *boolean* | false |
|
||||
| `default-class` | *string* | lucide-icon |
|
||||
| name | type | default |
|
||||
| ------------------ | --------- | ------------ |
|
||||
| `size` | _number_ | 24 |
|
||||
| `color` | _string_ | currentColor |
|
||||
| `stroke-width` | _number_ | 2 |
|
||||
| `nonScalingStroke` | _boolean_ | false |
|
||||
| `default-class` | _string_ | lucide-icon |
|
||||
|
||||
Because icons render as SVG elements, all standard SVG attributes can also be applied as props. See the list of SVG Presentation Attributes on [MDN](https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/Presentation).
|
||||
|
||||
|
||||
@@ -2,8 +2,7 @@
|
||||
|
||||
`@lucide/icons` is a helper library that exports Lucide **icon data** in a tree-shakable format, also providing utilities for dynamic importing icons.
|
||||
|
||||
It intentionally ships **no real rendering logic or components** — other packages (for example [`@lucide/angular`](http://npmjs.com/package/@lucide/angular)) can consume this data to render icons in their respective
|
||||
frameworks. You can also use this package to build third-party integrations for frameworks we don't (yet) support.
|
||||
It intentionally ships **no real rendering logic or components** — but you can use this package to build third-party integrations for frameworks we don't (yet) support.
|
||||
|
||||
## Installation
|
||||
|
||||
@@ -35,14 +34,11 @@ Each icon is described by the following interface:
|
||||
export type LucideIconData = {
|
||||
name: string;
|
||||
node: LucideIconNode[];
|
||||
} & (
|
||||
| { size: number }
|
||||
| { width: number; height: number; }
|
||||
);
|
||||
} & ({ size: number } | { width: number; height: number });
|
||||
```
|
||||
|
||||
| name | type | description |
|
||||
|------------------------------|--------------------|--------------------------------------------------------------------|
|
||||
| ---------------------------- | ------------------ | ------------------------------------------------------------------ |
|
||||
| `name` | `string` | The name of the icon. |
|
||||
| `node` | `LucideIconNode[]` | SVG child nodes as `[tagName, attributes]` tuples. |
|
||||
| `size` or `width` & `height` | `number` | The dimensions of the icon (`size` is shorthand for square icons). |
|
||||
@@ -65,16 +61,16 @@ All builders accept the same `params` object (`LucideBuildParams`) to customize
|
||||
|
||||
The following parameters are supported (names reflect the current implementation):
|
||||
|
||||
| param | type | effect |
|
||||
|-----------------------|--------------------------|------------------------------------------------------------------------------------|
|
||||
| `color` | `string` | Sets `stroke` (defaults to `currentColor`). |
|
||||
| `size` | `number` | Sets both `width` and `height` (defaults to 24). |
|
||||
| `width` | `number` | Sets `width` only. |
|
||||
| `height` | `number` | Sets `height` only. |
|
||||
| `strokeWidth` | `number` | Sets `stroke-width` (defaults to 2). |
|
||||
| `absoluteStrokeWidth` | `boolean` | Adds [`vector-effect="non-scaling-stroke"`](https://developer.mozilla.org/en-US/docs/Web/SVG/Reference/Attribute/vector-effect) to child elements. |
|
||||
| `className` | `string` | Appended to the generated `class` attribute. |
|
||||
| `attributes` | `Record<string, string>` | Add or override any generated SVG attributes (including `class`, `viewBox`, etc.). |
|
||||
| param | type | effect |
|
||||
| ------------------ | ------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `color` | `string` | Sets `stroke` (defaults to `currentColor`). |
|
||||
| `size` | `number` | Sets both `width` and `height` (defaults to 24). |
|
||||
| `width` | `number` | Sets `width` only. |
|
||||
| `height` | `number` | Sets `height` only. |
|
||||
| `strokeWidth` | `number` | Sets `stroke-width` (defaults to 2). |
|
||||
| `nonScalingStroke` | `boolean` | Adds [`vector-effect="non-scaling-stroke"`](https://developer.mozilla.org/en-US/docs/Web/SVG/Reference/Attribute/vector-effect) to child elements. |
|
||||
| `className` | `string` | Appended to the generated `class` attribute. |
|
||||
| `attributes` | `Record<string, string>` | Add or override any generated SVG attributes (including `class`, `viewBox`, and so on). |
|
||||
|
||||
::: info
|
||||
SVG attributes generated by the builders include a default Lucide setup (`xmlns`, `viewBox`, `fill="none"`, `stroke="currentColor"`, `stroke-width="2"`, `stroke-linecap="round"`, `stroke-linejoin="round"`), plus a class string of the form: `lucide lucide-{iconName}`.
|
||||
@@ -127,6 +123,7 @@ document.body.appendChild(el);
|
||||
Creates a base64-encoded SVG data URI from a Lucide icon object.
|
||||
|
||||
This helper works in both browsers and Node.js:
|
||||
|
||||
- In browsers it uses `btoa` (with proper UTF-8 handling)
|
||||
- In Node.js it falls back to `Buffer`
|
||||
|
||||
@@ -138,15 +135,18 @@ const uri = buildLucideDataUri(House, { size: 24 });
|
||||
```
|
||||
|
||||
The returned value can be used directly in places such as:
|
||||
|
||||
- `<img src="...">`
|
||||
- CSS `background-image`
|
||||
- Canvas drawing
|
||||
- Inline data URLs in HTML or SVG
|
||||
|
||||
::: tip Environment notes
|
||||
- The SVG is encoded as UTF-8 before base64 conversion to ensure correct handling of non-ASCII characters.
|
||||
- No runtime configuration is required — the function automatically selects the appropriate encoding strategy.
|
||||
- If neither `btoa` nor `Buffer` is available, an error is thrown.
|
||||
The SVG is encoded as UTF-8 before base64 conversion to ensure correct handling of non-ASCII characters.
|
||||
|
||||
No runtime configuration is required. The function automatically selects the appropriate encoding strategy.
|
||||
|
||||
If neither `btoa` nor `Buffer` is available, an error is thrown.
|
||||
:::
|
||||
|
||||
## Dynamic imports
|
||||
@@ -156,6 +156,7 @@ Dynamic imports are useful when you only know the icon name at runtime (for exam
|
||||
::: tip
|
||||
Validate `iconName` before indexing the map (and provide a fallback icon) to avoid runtime errors.
|
||||
:::
|
||||
|
||||
## Dynamic imports
|
||||
|
||||
Dynamic imports are useful when the icon name is only known at runtime (for example, icon names stored in a CMS or database). For purely static usage, prefer direct imports for maximum tree-shaking.
|
||||
@@ -1,7 +1,8 @@
|
||||
---
|
||||
title: Stroke width - Lucide
|
||||
description: Learn how to customize the stroke width of Lucide icons in your Vanilla JavaScript applications using the strokeWidth and absoluteStrokeWidth attributes.
|
||||
description: Learn how to customize the stroke width of Lucide icons in your Vanilla JavaScript applications using the strokeWidth and nonScalingStroke attributes.
|
||||
---
|
||||
|
||||
<script setup>
|
||||
import Sandpack from '~/.vitepress/theme/components/editors/Sandpack.vue'
|
||||
</script>
|
||||
@@ -18,10 +19,13 @@ The `strokeWidth` can be adjusted to create a different look of the icons.
|
||||
::: sandpack {template=vanilla showTabs=false editorHeight=250 editorWidthPercentage=70 dependencies="lucide"}
|
||||
|
||||
```html /index.html [active]
|
||||
<!DOCTYPE html>
|
||||
<!doctype html>
|
||||
<html>
|
||||
<body>
|
||||
<i data-lucide="folder-lock" stroke-width="1"></i>
|
||||
<i
|
||||
data-lucide="folder-lock"
|
||||
stroke-width="1"
|
||||
></i>
|
||||
|
||||
<script src="index.js"></script>
|
||||
</body>
|
||||
@@ -29,34 +33,32 @@ The `strokeWidth` can be adjusted to create a different look of the icons.
|
||||
```
|
||||
|
||||
```js /index.js
|
||||
import "./styles.css";
|
||||
import './styles.css';
|
||||
|
||||
import { createIcons, FolderLock } from 'lucide/dist/cjs/lucide';
|
||||
|
||||
createIcons({
|
||||
icons: {
|
||||
FolderLock,
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
<!-- ## Non-scaling strokes
|
||||
|
||||
<!-- ## Absolute stroke width
|
||||
When adjusting the `size` prop the size of the stroke width will be relative to the size of the icon, this is the default SVG behavior. The `nonScalingStroke` prop is introduced to adjust this behavior to make the stroke width constant no matter the size of the icon.
|
||||
|
||||
When adjusting the `size` prop the size of the stroke width will be relative to the size of the icon, this is the default SVG behavior. The `absoluteStrokeWidth` prop is introduced to adjust this behavior to make the stroke width constant no matter the size of the icon.
|
||||
|
||||
This means that when `absoluteStrokeWidth` is enabled and the `size` of the icons is set to `48px` the `strokeWidth` will still be `2px` on the screen.
|
||||
This means that when `nonScalingStroke` is enabled and the `size` of the icons is set to `48px` the `strokeWidth` will still be `2px` on the screen.
|
||||
|
||||
Note `2px` is the default stroke width for a Lucide icon, this can be adjusted to all sizes.
|
||||
|
||||

|
||||
[Non-scaling stroke comparison](../../../images/non-scaling-stroke-compare.svg)
|
||||
|
||||
### Adjusting stroke width with `absoluteStrokeWidth` prop
|
||||
### Adjusting stroke width with `nonScalingStroke` prop
|
||||
|
||||
Setting `absoluteStrokeWidth` to `true` will make the stroke width absolute.
|
||||
Setting `nonScalingStroke` to `true` will make the stroke width non-scaling.
|
||||
|
||||
::: sandpack {template=vanilla showTabs=false editorHeight=250 editorWidthPercentage=70 dependencies="lucide"}
|
||||
|
||||
@@ -64,7 +66,7 @@ Setting `absoluteStrokeWidth` to `true` will make the stroke width absolute.
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<body>
|
||||
<i data-lucide="roller-coaster" stroke-width="96" absolute-stroke-width="true"></i>
|
||||
<i data-lucide="roller-coaster" stroke-width="96" non-scaling-stroke="true"></i>
|
||||
|
||||
<script src="index.js"></script>
|
||||
</body>
|
||||
|
||||
@@ -1,286 +0,0 @@
|
||||
# `@lucide/angular`
|
||||
|
||||
::: warning
|
||||
This documentation is for `@lucide/angular`.
|
||||
|
||||
To learn about our legacy package for Angular, please refer to [`lucide-angular`](https://v0.lucide.dev/guide/packages/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,210 +0,0 @@
|
||||
# Lucide Astro
|
||||
|
||||
Astro components for Lucide icons that work perfectly with Astro's island architecture and multi-framework support. Each icon is an Astro component that renders as an inline SVG, providing excellent performance for static sites and server-side rendering scenarios.
|
||||
|
||||
**What you can accomplish:**
|
||||
- Use icons as Astro components with zero JavaScript runtime overhead
|
||||
- Build fast, static websites with optimized SVG icons
|
||||
- Integrate seamlessly with Astro's component islands and partial hydration
|
||||
- Create multi-framework applications where icons work across different UI libraries
|
||||
- Optimize performance with direct icon imports and build-time rendering
|
||||
|
||||
## Installation
|
||||
|
||||
::: code-group
|
||||
|
||||
```sh [pnpm]
|
||||
pnpm add @lucide/astro
|
||||
```
|
||||
|
||||
```sh [yarn]
|
||||
yarn add @lucide/astro
|
||||
```
|
||||
|
||||
```sh [npm]
|
||||
npm install @lucide/astro
|
||||
```
|
||||
|
||||
```sh [bun]
|
||||
bun add @lucide/astro
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
## How to use
|
||||
|
||||
Lucide is built with ES Modules, so it's completely tree-shakable.
|
||||
|
||||
Each icon can be imported as an Astro 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
|
||||
|
||||
Default usage:
|
||||
|
||||
```astro
|
||||
---
|
||||
import { Skull } from '@lucide/astro';
|
||||
---
|
||||
|
||||
<Skull />
|
||||
```
|
||||
|
||||
Additional props can be passed to adjust the icon:
|
||||
|
||||
```astro
|
||||
---
|
||||
import { Camera } from '@lucide/astro';
|
||||
---
|
||||
|
||||
<Camera color="#ff3e98" />
|
||||
```
|
||||
|
||||
For faster builds and load times, you can import icons directly from the `@lucide/astro/icons` directory:
|
||||
|
||||
```astro
|
||||
---
|
||||
import CircleAlert from '@lucide/astro/icons/circle-alert';
|
||||
---
|
||||
|
||||
<CircleAlert color="#ff3e98" />
|
||||
```
|
||||
|
||||
## Props
|
||||
|
||||
| name | type | default |
|
||||
| --------------------- | --------- | ------------ |
|
||||
| `size` | _number_ | 24 |
|
||||
| `color` | _string_ | currentColor |
|
||||
| `stroke-width` | _number_ | 2 |
|
||||
| `absoluteStrokeWidth` | _boolean_ | false |
|
||||
|
||||
### 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).
|
||||
|
||||
```astro
|
||||
---
|
||||
import { Phone } from '@lucide/astro';
|
||||
---
|
||||
|
||||
<Phone fill="#333" />
|
||||
```
|
||||
|
||||
This results a filled phone icon.
|
||||
|
||||
## Types
|
||||
|
||||
The package includes type definitions for all icons. This is useful if you want to dynamically render icons.
|
||||
|
||||
### Example
|
||||
|
||||
```astro
|
||||
---
|
||||
import { House, Library, Cog, type Icon as IconType } from '@lucide/astro';
|
||||
|
||||
type MenuItem = {
|
||||
name: string;
|
||||
href: string;
|
||||
icon: typeof IconType;
|
||||
};
|
||||
|
||||
const menuItems: MenuItem[] = [
|
||||
{
|
||||
name: 'Home',
|
||||
href: '/',
|
||||
icon: House,
|
||||
},
|
||||
{
|
||||
name: 'Blog',
|
||||
href: '/blog',
|
||||
icon: Library,
|
||||
},
|
||||
{
|
||||
name: 'Projects',
|
||||
href: '/projects',
|
||||
icon: Cog,
|
||||
},
|
||||
];
|
||||
---
|
||||
|
||||
{
|
||||
menuItems.map((item) => (
|
||||
<a href={item.href}>
|
||||
<item.icon />
|
||||
<span>{item.name}</span>
|
||||
</a>
|
||||
))
|
||||
}
|
||||
```
|
||||
|
||||
## 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 of the 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.
|
||||
|
||||
```astro
|
||||
---
|
||||
import { Icon } from '@lucide/astro';
|
||||
import { burger, sausage } from '@lucide/lab';
|
||||
---
|
||||
|
||||
<Icon iconNode={burger} />
|
||||
<Icon iconNode={sausage} color="red"/>
|
||||
```
|
||||
|
||||
## 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. This may be passable if you're doing SSG and SSR in server environments. However if you're doing SSR in serverless environments, it could negatively affect your app's performance, as a bigger bundle size will translate to an increase in cold starts.
|
||||
:::
|
||||
|
||||
### Icon Component Example
|
||||
|
||||
```astro
|
||||
---
|
||||
import { icons, type IconProps } from '@lucide/astro';
|
||||
|
||||
interface Props extends IconProps {
|
||||
name: keyof typeof icons;
|
||||
}
|
||||
|
||||
const { name, ...restProps } = Astro.props;
|
||||
const Icon = icons[name];
|
||||
---
|
||||
|
||||
<Icon {...restProps} />
|
||||
```
|
||||
|
||||
### Using the Icon Component
|
||||
|
||||
```astro
|
||||
---
|
||||
import LucideIcon from './LucideIcon.astro';
|
||||
---
|
||||
|
||||
<LucideIcon name="Menu" />
|
||||
```
|
||||
|
||||
## Accessibility
|
||||
|
||||
By default, we hide icons from screen readers using `aria-hidden="true"`.
|
||||
|
||||
You can add accessibility attributes using aria-labels.
|
||||
|
||||
```jsx
|
||||
---
|
||||
import { Check } from '@lucide/astro';
|
||||
---
|
||||
|
||||
<Check aria-label="Task completed" />
|
||||
```
|
||||
|
||||
For best practices on accessibility, please see our [accessibility guide](../accessibility.md).
|
||||
@@ -1,149 +0,0 @@
|
||||
---
|
||||
title: Lucide Preact
|
||||
---
|
||||
|
||||
# Lucide Preact
|
||||
|
||||
Preact components for Lucide icons that provide React-like development experience with a smaller footprint. Each icon is a lightweight Preact component that renders as an inline SVG, perfect for applications that need React compatibility with minimal bundle size.
|
||||
|
||||
**What you can accomplish:**
|
||||
- Use icons as Preact components with React-like syntax and patterns
|
||||
- Build lightweight applications with Preact's smaller runtime
|
||||
- Create fast, responsive interfaces with minimal JavaScript overhead
|
||||
- Maintain React compatibility while reducing bundle size
|
||||
- Integrate with existing Preact applications and component libraries
|
||||
|
||||
## Installation
|
||||
|
||||
::: code-group
|
||||
|
||||
```sh [pnpm]
|
||||
pnpm add lucide-preact
|
||||
```
|
||||
|
||||
```sh [yarn]
|
||||
yarn add lucide-preact
|
||||
```
|
||||
|
||||
```sh [npm]
|
||||
npm install lucide-preact
|
||||
```
|
||||
|
||||
```sh [bun]
|
||||
bun add lucide-preact
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
## How to use
|
||||
|
||||
Lucide is built with ES Modules, so it's completely tree-shakable.
|
||||
|
||||
Each icon can be imported as a Preact 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
|
||||
|
||||
Additional props can be passed to adjust the icon:
|
||||
|
||||
```jsx
|
||||
import { Camera } from 'lucide-preact';
|
||||
|
||||
// Usage
|
||||
const App = () => {
|
||||
return <Camera color="red" size={48} />;
|
||||
};
|
||||
|
||||
export default App;
|
||||
```
|
||||
|
||||
## Props
|
||||
|
||||
| name | type | default |
|
||||
| --------------------- | --------- | ------------ |
|
||||
| `size` | *number* | 24 |
|
||||
| `color` | *string* | currentColor |
|
||||
| `strokeWidth` | *number* | 2 |
|
||||
| `absoluteStrokeWidth` | *boolean* | false |
|
||||
|
||||
### 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).
|
||||
|
||||
```jsx
|
||||
// Usage
|
||||
const App = () => {
|
||||
return <Camera fill="red" stroke-linejoin="bevel" />;
|
||||
};
|
||||
```
|
||||
|
||||
> SVG attributes in Preact aren't transformed, so if you want to change for example the `stroke-linejoin` you need to pass it in kebabcase. Basically how the SVG spec want you to write it. See this topic in the [Preact documentation](https://preactjs.com/guide/v10/differences-to-react/#svg-inside-jsx).
|
||||
|
||||
## 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.
|
||||
|
||||
```jsx
|
||||
import { Icon } from 'lucide-preact';
|
||||
import { coconut } from '@lucide/lab';
|
||||
|
||||
const App = () => (
|
||||
<Icon iconNode={coconut} />
|
||||
);
|
||||
```
|
||||
|
||||
## 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
|
||||
|
||||
```jsx
|
||||
import { icons } from 'lucide-preact';
|
||||
|
||||
const Icon = ({ name, color, size }) => {
|
||||
const LucideIcon = icons[name];
|
||||
|
||||
return <LucideIcon color={color} size={size} />;
|
||||
};
|
||||
|
||||
export default Icon;
|
||||
```
|
||||
|
||||
#### Using the Icon Component
|
||||
|
||||
```jsx
|
||||
import Icon from './Icon';
|
||||
|
||||
const App = () => {
|
||||
return <Icon name="house" />;
|
||||
};
|
||||
|
||||
export default App;
|
||||
```
|
||||
|
||||
## Accessibility
|
||||
|
||||
By default, we hide icons from screen readers using `aria-hidden="true"`.
|
||||
|
||||
You can add accessibility attributes using aria-labels.
|
||||
|
||||
```jsx
|
||||
import { Check } from 'lucide-preact';
|
||||
|
||||
const App = () => {
|
||||
return <Check aria-label="Task completed" />;
|
||||
};
|
||||
```
|
||||
|
||||
For best practices on accessibility, please see our [accessibility guide](../accessibility.md).
|
||||
@@ -1,133 +0,0 @@
|
||||
# Lucide React Native
|
||||
|
||||
React Native components for Lucide icons that work seamlessly across iOS and Android platforms. Built on top of react-native-svg, each icon renders as a native SVG component, providing consistent visual appearance and performance across mobile devices.
|
||||
|
||||
**What you can accomplish:**
|
||||
- Use icons as React Native components with platform-consistent rendering
|
||||
- Build cross-platform mobile apps with scalable vector icons
|
||||
- Create responsive interfaces that adapt to different screen densities
|
||||
- Integrate with React Native's styling system and animation libraries
|
||||
- Maintain consistent icon appearance across iOS and Android platforms
|
||||
|
||||
## Installation
|
||||
|
||||
First, ensure that you have `react-native-svg` (version between 12 and 15) installed. Then, install the package:
|
||||
|
||||
::: code-group
|
||||
|
||||
```sh [pnpm]
|
||||
pnpm add lucide-react-native
|
||||
```
|
||||
|
||||
```sh [yarn]
|
||||
yarn add lucide-react-native
|
||||
```
|
||||
|
||||
```sh [npm]
|
||||
npm install lucide-react-native
|
||||
```
|
||||
|
||||
```sh [bun]
|
||||
bun add lucide-react-native
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
## How to use
|
||||
|
||||
Each icon can be imported as a React component.
|
||||
|
||||
### Example
|
||||
|
||||
Additional props can be passed to adjust the icon:
|
||||
|
||||
```jsx
|
||||
import { Camera } from 'lucide-react-native';
|
||||
|
||||
// Usage
|
||||
const App = () => {
|
||||
return <Camera color="red" size={48} />;
|
||||
};
|
||||
|
||||
export default App;
|
||||
```
|
||||
|
||||
## Props
|
||||
|
||||
| name | type | default |
|
||||
| --------------------- | --------- | ------------ |
|
||||
| `size` | *number* | 24 |
|
||||
| `color` | *string* | currentColor |
|
||||
| `strokeWidth` | *number* | 2 |
|
||||
| `absoluteStrokeWidth` | *boolean* | false |
|
||||
|
||||
### 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.
|
||||
|
||||
```jsx
|
||||
// Usage
|
||||
const App = () => {
|
||||
return <Camera fill="red" />;
|
||||
};
|
||||
```
|
||||
|
||||
## 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.
|
||||
|
||||
```jsx
|
||||
import { Icon } from 'lucide-react-native';
|
||||
import { coconut } from '@lucide/lab';
|
||||
|
||||
const App = () => (
|
||||
<Icon iconNode={coconut} />
|
||||
);
|
||||
```
|
||||
|
||||
## One generic icon component
|
||||
|
||||
It is possible to create one generic icon component to load icons, but it is not recommended.
|
||||
|
||||
::: warning
|
||||
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 to keep in mind when using bundlers like `Webpack`, `Rollup`, or `Vite`.
|
||||
:::
|
||||
|
||||
### Icon Component Example
|
||||
|
||||
```tsx
|
||||
import * as icons from 'lucide-react-native/icons';
|
||||
|
||||
interface IconProps {
|
||||
name: keyof typeof icons;
|
||||
color?: string;
|
||||
size?: number;
|
||||
}
|
||||
|
||||
const Icon = ({ name, color, size }: IconProps) => {
|
||||
const LucideIcon = icons[name];
|
||||
|
||||
return <LucideIcon color={color} size={size} />;
|
||||
};
|
||||
|
||||
export default Icon;
|
||||
```
|
||||
|
||||
#### Using the Icon Component
|
||||
|
||||
```tsx
|
||||
import Icon from './Icon';
|
||||
|
||||
const App = () => {
|
||||
return <Icon name="House" />;
|
||||
};
|
||||
|
||||
export default App;
|
||||
```
|
||||
@@ -1,162 +0,0 @@
|
||||
# Lucide Solid
|
||||
|
||||
SolidJS components for Lucide icons that leverage Solid's fine-grained reactivity system. Each icon is a reactive Solid component that renders as an inline SVG, providing exceptional performance through Solid's compile-time optimizations and reactive primitives.
|
||||
|
||||
**What you can accomplish:**
|
||||
- Use icons as SolidJS components with fine-grained reactivity
|
||||
- Create highly performant interfaces with Solid's reactive system
|
||||
- Build dynamic icon components that respond to signals and stores
|
||||
- Integrate seamlessly with Solid's JSX and component patterns
|
||||
- Optimize performance with direct icon imports and minimal runtime overhead
|
||||
|
||||
## Installation
|
||||
|
||||
::: code-group
|
||||
|
||||
```sh [pnpm]
|
||||
pnpm add lucide-solid
|
||||
```
|
||||
|
||||
```sh [yarn]
|
||||
yarn add lucide-solid
|
||||
```
|
||||
|
||||
```sh [npm]
|
||||
npm install lucide-solid
|
||||
```
|
||||
|
||||
```sh [bun]
|
||||
bun add lucide-solid
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
## How to use
|
||||
|
||||
Lucide is built with ES Modules, so it's completely tree-shakable.
|
||||
|
||||
Each icon can be imported as a Solid 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
|
||||
|
||||
Additional props can be passed to adjust the icon:
|
||||
|
||||
```jsx
|
||||
import { Camera } from 'lucide-solid';
|
||||
|
||||
// Usage
|
||||
const App = () => {
|
||||
return <Camera color="red" size={48} />;
|
||||
};
|
||||
|
||||
export default App;
|
||||
```
|
||||
|
||||
Vite loading/performing issues with the dev server can be resolved by import icons directly from the `lucide-solid/icons` directory:
|
||||
|
||||
```jsx
|
||||
import Camera from 'lucide-solid/icons/camera';
|
||||
|
||||
// Usage
|
||||
const App = () => {
|
||||
return <Camera color="red" size={48} />;
|
||||
};
|
||||
|
||||
export default App;
|
||||
```
|
||||
|
||||
## Props
|
||||
|
||||
| name | type | default |
|
||||
| --------------------- | --------- | ------------ |
|
||||
| `size` | *number* | 24 |
|
||||
| `color` | *string* | currentColor |
|
||||
| `strokeWidth` | *number* | 2 |
|
||||
| `absoluteStrokeWidth` | *boolean* | false |
|
||||
|
||||
### 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).
|
||||
|
||||
```jsx
|
||||
// Usage
|
||||
const App = () => {
|
||||
return <Camera fill="red" stroke-linejoin="bevel" />;
|
||||
};
|
||||
```
|
||||
|
||||
## 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 the 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.
|
||||
|
||||
```jsx
|
||||
import { Icon } from 'lucide-solid';
|
||||
import { sausage } from '@lucide/lab';
|
||||
|
||||
const App = () => (
|
||||
<Icon iconNode={sausage} color="red"/>
|
||||
);
|
||||
```
|
||||
|
||||
## One generic icon component
|
||||
|
||||
It is possible to create one generic icon component to load icons. It's 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 to keep in mind when using bundlers like `Webpack`, `Rollup`, or `Vite`.
|
||||
:::
|
||||
|
||||
### Icon Component Example
|
||||
|
||||
```tsx
|
||||
import { icons, type LucideProps } from 'lucide-solid';
|
||||
import { splitProps } from 'solid-js';
|
||||
import { Dynamic } from 'solid-js/web';
|
||||
|
||||
interface IconProps extends LucideProps {
|
||||
name: keyof typeof icons;
|
||||
}
|
||||
|
||||
const Icon = (props: IconProps) => {
|
||||
const [local, others] = splitProps(props, ["name"]);
|
||||
|
||||
return <Dynamic component={icons[local.name]} {...others} />
|
||||
};
|
||||
|
||||
export default Icon;
|
||||
```
|
||||
|
||||
#### Using the Icon Component
|
||||
|
||||
```tsx
|
||||
import Icon from './Icon';
|
||||
|
||||
const App = () => {
|
||||
return <Icon name="home" />;
|
||||
};
|
||||
|
||||
export default App;
|
||||
```
|
||||
|
||||
## Accessibility
|
||||
|
||||
By default, we hide icons from screen readers using `aria-hidden="true"`.
|
||||
|
||||
You can add accessibility attributes using aria-labels.
|
||||
|
||||
```jsx
|
||||
import { Check } from 'lucide-solid';
|
||||
|
||||
const App = () => {
|
||||
return <Check aria-label="Task completed" />;
|
||||
};
|
||||
```
|
||||
|
||||
For best practices on accessibility, please see our [accessibility guide](../accessibility.md).
|
||||
@@ -1,265 +0,0 @@
|
||||
# Lucide Static
|
||||
|
||||
Static assets and utilities for Lucide icons that work without JavaScript frameworks. This package provides multiple formats including individual SVG files, SVG sprites, icon fonts, and Node.js utilities for server-side rendering and static site generation.
|
||||
|
||||
**What you can accomplish:**
|
||||
- Use individual SVG files as images or CSS background images
|
||||
- Implement icon fonts for CSS-based icon systems
|
||||
- Create SVG sprites for efficient icon loading in static sites
|
||||
- Import SVG strings in Node.js applications and server-side rendering
|
||||
- Build static websites and applications without JavaScript framework dependencies
|
||||
|
||||
This package includes the following implementations of Lucide icons:
|
||||
|
||||
- Individual SVG files
|
||||
- SVG sprite
|
||||
- Icon font files
|
||||
- A JavaScript library exporting SVG strings
|
||||
|
||||
## Who is this for?
|
||||
|
||||
`lucide-static` is suitable for _very specific use cases_ where you want to use Lucide icons without relying on a JavaScript framework or component system. It's ideal for:
|
||||
|
||||
- Projects that use icon fonts with plain CSS or utility-first frameworks
|
||||
- Embedding raw SVG files or sprites directly in HTML
|
||||
- Using SVGs as CSS background images
|
||||
- Importing SVG strings into Node.js (CommonJS) environments
|
||||
|
||||
::: danger
|
||||
### Not recommended for production {#production-warning}
|
||||
|
||||
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 one of the framework-specific [packages](../../packages.md).
|
||||
:::
|
||||
|
||||
## Installation
|
||||
|
||||
::: code-group
|
||||
|
||||
```sh [pnpm]
|
||||
pnpm add lucide-static
|
||||
```
|
||||
|
||||
```sh [yarn]
|
||||
yarn add lucide-static
|
||||
```
|
||||
|
||||
```sh [npm]
|
||||
npm install lucide-static
|
||||
```
|
||||
|
||||
```sh [bun]
|
||||
bun add lucide-static
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
## SVG Files
|
||||
|
||||
You can use standalone SVG files or SVG sprites in several ways.
|
||||
|
||||
Check out our [codesandbox example](https://codesandbox.io/s/using-the-svg-sprite-lz1kk).
|
||||
|
||||
### SVG file as image
|
||||
|
||||
#### In HTML:
|
||||
|
||||
::: code-group
|
||||
|
||||
```html [Webpack]
|
||||
<!-- SVG file for a single icon -->
|
||||
<img src="~lucide-static/icons/house.svg" />
|
||||
```
|
||||
|
||||
```html [CDN]
|
||||
<!-- SVG file for a single icon -->
|
||||
<img src="https://unpkg.com/lucide-static@latest/icons/house.svg" />
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
#### In CSS:
|
||||
|
||||
::: code-group
|
||||
|
||||
```css [Webpack]
|
||||
.house-icon {
|
||||
background-image: url(~lucide-static/icons/house.svg);
|
||||
}
|
||||
```
|
||||
|
||||
```css [CDN]
|
||||
.house-icon {
|
||||
background-image: url(https://unpkg.com/lucide-static@latest/icons/house.svg);
|
||||
}
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
Make sure you have the correct Webpack loader configured, such as [`url-loader`](https://v4.webpack.js.org/loaders/url-loader/).
|
||||
|
||||
### SVG file as string
|
||||
|
||||
To import an SVG as a string (e.g., for templating):
|
||||
|
||||
::: code-group
|
||||
|
||||
```js [Webpack]
|
||||
import arrowRightIcon from 'lucide-static/icons/arrow-right';
|
||||
```
|
||||
|
||||
```js [Vite]
|
||||
import arrowRightIcon from 'lucide-static/icons/arrow-right.svg?raw';
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
You'll need an SVG loader like [`svg-inline-loader`](https://v4.webpack.js.org/loaders/svg-inline-loader/).
|
||||
|
||||
|
||||
### Using the SVG sprite
|
||||
|
||||
:::danger
|
||||
[Not intended for production use.](#production-warning)
|
||||
:::
|
||||
|
||||
You may also need an additional SVG loader to handle this.
|
||||
|
||||
#### Basic sprite usage (not production-optimized):
|
||||
|
||||
```html
|
||||
<img src="lucide-static/sprite.svg#house" />
|
||||
```
|
||||
|
||||
#### Inline usage:
|
||||
|
||||
```html
|
||||
<svg
|
||||
width="24"
|
||||
height="24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
>
|
||||
<use href="#alert-triangle" />
|
||||
</svg>
|
||||
|
||||
<!-- sprite SVG -->
|
||||
<svg>...</svg>
|
||||
```
|
||||
|
||||
#### Inline with CSS helper class
|
||||
|
||||
If you'd prefer, you can use CSS to hold your base SVG properties:
|
||||
|
||||
```css
|
||||
.lucide-icon {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
stroke: currentColor;
|
||||
fill: none;
|
||||
stroke-width: 2;
|
||||
stroke-linecap: round;
|
||||
stroke-linejoin: round;
|
||||
}
|
||||
```
|
||||
|
||||
...and update the SVG as follows:
|
||||
|
||||
```xml
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
class="lucide-icon"
|
||||
>
|
||||
<use href="#triangle-alert" />
|
||||
</svg>
|
||||
|
||||
<!-- sprite SVG -->
|
||||
<svg>...</svg>
|
||||
```
|
||||
|
||||
## Icon font
|
||||
|
||||
:::danger
|
||||
[Not intended for production use.](#production-warning)
|
||||
:::
|
||||
|
||||
Lucide icons are also available as a web font. To use them, you first need to include the corresponding stylesheet:
|
||||
|
||||
::: code-group
|
||||
|
||||
```css [Vite]
|
||||
@import 'lucide-static/font/lucide.css';
|
||||
```
|
||||
|
||||
```css [Webpack]
|
||||
@import ('~lucide-static/font/lucide.css');
|
||||
```
|
||||
|
||||
```html [CDN]
|
||||
<link rel="stylesheet" href="https://unpkg.com/lucide-static@latest/font/lucide.css" />
|
||||
```
|
||||
|
||||
```html [Static asset]
|
||||
<link rel="stylesheet" href="/your/path/to/lucide.css" />
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
Once included, use the format `icon-{kebab-case-name}`. You can copy icon names from the [Lucide Icons page](https://lucide.dev/icons).
|
||||
|
||||
```html
|
||||
<div class="icon-house"></div>
|
||||
```
|
||||
|
||||
If you're not using a package manager, you can download the font files directly from the [latest release](https://github.com/lucide-icons/lucide/releases/latest).
|
||||
|
||||
## Node.js
|
||||
|
||||
You can also import Lucide icons in Node.js projects:
|
||||
|
||||
::: code-group
|
||||
|
||||
```js [ESM]
|
||||
import {MessageSquare} from 'lucide-static';
|
||||
```
|
||||
|
||||
```js [CommonJs]
|
||||
const {MessageSquare} = require('lucide-static');
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
> Note: Each icon name is in PascalCase.
|
||||
|
||||
#### Express app example in Node.js
|
||||
|
||||
```js
|
||||
import express from 'express';
|
||||
import {MessageSquare} from 'lucide-static';
|
||||
const app = express();
|
||||
const port = 3000;
|
||||
|
||||
app.get('/', (req, res) => {
|
||||
res.send(`
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Page Title</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Lucide Icons</h1>
|
||||
<p>This is a Lucide icon ${MessageSquare}</p>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
`);
|
||||
});
|
||||
|
||||
app.listen(port, () => {
|
||||
console.log(`Example app listening at http://localhost:${port}`);
|
||||
});
|
||||
```
|
||||
@@ -1,349 +0,0 @@
|
||||
# Lucide Svelte
|
||||
|
||||
Svelte components for Lucide icons that work seamlessly with both Svelte 4 and Svelte 5. Each icon is a reactive Svelte component that renders as an inline SVG, providing excellent performance and integration with Svelte's reactive system and modern features.
|
||||
|
||||
**What you can accomplish:**
|
||||
- Use icons as Svelte components with full reactivity and TypeScript support
|
||||
- Bind icon properties to reactive variables and stores
|
||||
- Create dynamic icon systems that respond to application state
|
||||
- Build type-safe interfaces with comprehensive TypeScript definitions
|
||||
- Optimize bundle sizes with direct icon imports and tree-shaking
|
||||
|
||||
## Installation
|
||||
|
||||
::: code-group
|
||||
|
||||
```sh [pnpm]
|
||||
pnpm add @lucide/svelte
|
||||
```
|
||||
|
||||
```sh [yarn]
|
||||
yarn add @lucide/svelte
|
||||
```
|
||||
|
||||
```sh [npm]
|
||||
npm install @lucide/svelte
|
||||
```
|
||||
|
||||
```sh [bun]
|
||||
bun add @lucide/svelte
|
||||
```
|
||||
:::
|
||||
> `@lucide/svelte` is only for Svelte 5, for Svelte 4 use the `lucide-svelte` package.
|
||||
|
||||
## How to use
|
||||
|
||||
Lucide is built with ES Modules, so it's completely tree-shakable.
|
||||
|
||||
Each icon can be imported as a Svelte 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
|
||||
|
||||
Default usage:
|
||||
|
||||
```svelte
|
||||
<script>
|
||||
import { Skull } from '@lucide/svelte';
|
||||
</script>
|
||||
|
||||
<Skull />
|
||||
```
|
||||
|
||||
Additional props can be passed to adjust the icon:
|
||||
|
||||
```svelte
|
||||
<script>
|
||||
import { Camera } from '@lucide/svelte';
|
||||
</script>
|
||||
|
||||
<Camera color="#ff3e98" />
|
||||
```
|
||||
|
||||
For faster builds and load times, you can import icons directly from the `@lucide/svelte/icons` directory:
|
||||
|
||||
```svelte
|
||||
<script>
|
||||
import CircleAlert from '@lucide/svelte/icons/circle-alert';
|
||||
</script>
|
||||
|
||||
<CircleAlert color="#ff3e98" />
|
||||
```
|
||||
|
||||
## Props
|
||||
|
||||
| name | type | default |
|
||||
| --------------------- | --------- | ------------ |
|
||||
| `size` | _number_ | 24 |
|
||||
| `color` | _string_ | currentColor |
|
||||
| `strokeWidth` | _number_ | 2 |
|
||||
| `absoluteStrokeWidth` | _boolean_ | false |
|
||||
|
||||
### 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).
|
||||
|
||||
```svelte
|
||||
<script>
|
||||
import { Phone } from '@lucide/svelte';
|
||||
</script>
|
||||
|
||||
<Phone fill="#333" />
|
||||
```
|
||||
|
||||
This results a filled phone icon.
|
||||
|
||||
## Types
|
||||
|
||||
The package includes type definitions for all icons. This is useful if you want to dynamically load icons with the `svelte:component` directive whether you are using TypeScript or JSDoc.
|
||||
|
||||
### TypeScript Example
|
||||
|
||||
::: code-group
|
||||
|
||||
```svelte [Svelte 5]
|
||||
<script lang="ts">
|
||||
import { Home, Library, Cog, type Icon as IconType } from '@lucide/svelte';
|
||||
|
||||
type MenuItem = {
|
||||
name: string;
|
||||
href: string;
|
||||
icon: typeof IconType;
|
||||
};
|
||||
|
||||
const menuItems: MenuItem[] = [
|
||||
{
|
||||
name: 'Home',
|
||||
href: '/',
|
||||
icon: Home
|
||||
},
|
||||
{
|
||||
name: 'Blog',
|
||||
href: '/blog',
|
||||
icon: Library
|
||||
},
|
||||
{
|
||||
name: 'Projects',
|
||||
href: '/projects',
|
||||
icon: Cog
|
||||
}
|
||||
];
|
||||
</script>
|
||||
|
||||
{#each menuItems as item}
|
||||
{@const Icon = item.icon}
|
||||
<a href={item.href}>
|
||||
<Icon />
|
||||
<span>{item.name}</span>
|
||||
</a>
|
||||
{/each}
|
||||
```
|
||||
|
||||
```svelte [Svelte 4]
|
||||
<script lang="ts">
|
||||
import { Home, Library, Cog, type Icon } from '@lucide/svelte';
|
||||
import type { ComponentType } from 'svelte';
|
||||
|
||||
type MenuItem = {
|
||||
name: string;
|
||||
href: string;
|
||||
icon: ComponentType<Icon>;
|
||||
};
|
||||
|
||||
const menuItems: MenuItem[] = [
|
||||
{
|
||||
name: 'Home',
|
||||
href: '/',
|
||||
icon: Home
|
||||
},
|
||||
{
|
||||
name: 'Blog',
|
||||
href: '/blog',
|
||||
icon: Library
|
||||
},
|
||||
{
|
||||
name: 'Projects',
|
||||
href: '/projects',
|
||||
icon: Cog
|
||||
}
|
||||
];
|
||||
</script>
|
||||
|
||||
{#each menuItems as item}
|
||||
{@const Icon = item.icon}
|
||||
<a href={item.href}>
|
||||
<Icon />
|
||||
<span>{item.name}</span>
|
||||
</a>
|
||||
{/each}
|
||||
|
||||
```
|
||||
:::
|
||||
|
||||
### JSDoc Example
|
||||
|
||||
::: code-group
|
||||
|
||||
```svelte [Svelte 5]
|
||||
<script>
|
||||
import { Home, Library, Cog } from '@lucide/svelte';
|
||||
|
||||
/**
|
||||
* @typedef {Object} MenuItem
|
||||
* @property {string} name
|
||||
* @property {string} href
|
||||
* @property {typeof import('@lucide/svelte').Icon} icon
|
||||
*/
|
||||
|
||||
/** @type {MenuItem[]} */
|
||||
const menuItems = [
|
||||
{
|
||||
name: 'Home',
|
||||
href: '/',
|
||||
icon: Home
|
||||
},
|
||||
{
|
||||
name: 'Blog',
|
||||
href: '/blog',
|
||||
icon: Library
|
||||
},
|
||||
{
|
||||
name: 'Projects',
|
||||
href: '/projects',
|
||||
icon: Cog
|
||||
}
|
||||
];
|
||||
</script>
|
||||
|
||||
{#each menuItems as item}
|
||||
{@const Icon = item.icon}
|
||||
<a href={item.href}>
|
||||
<Icon />
|
||||
<span>{item.name}</span>
|
||||
</a>
|
||||
{/each}
|
||||
```
|
||||
|
||||
```svelte [Svelte 4]
|
||||
<script>
|
||||
import { Home, Library, Cog } from '@lucide/svelte';
|
||||
|
||||
/**
|
||||
* @typedef {Object} MenuItem
|
||||
* @property {string} name
|
||||
* @property {string} href
|
||||
* @property {import('svelte').ComponentType<import('@lucide/svelte').Icon>} icon
|
||||
*/
|
||||
|
||||
/** @type {MenuItem[]} */
|
||||
const menuItems = [
|
||||
{
|
||||
name: 'Home',
|
||||
href: '/',
|
||||
icon: Home,
|
||||
},
|
||||
{
|
||||
name: 'Blog',
|
||||
href: '/blog',
|
||||
icon: Library,
|
||||
},
|
||||
{
|
||||
name: 'Projects',
|
||||
href: '/projects',
|
||||
icon: Cog,
|
||||
}
|
||||
];
|
||||
</script>
|
||||
|
||||
{#each menuItems as item}
|
||||
{@const Icon = item.icon}
|
||||
<a href={item.href}>
|
||||
<Icon />
|
||||
<span>{item.name}</span>
|
||||
</a>
|
||||
{/each}
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
For more details about typing the `svelte:component` directive, see the [Svelte documentation](https://svelte.dev/docs/typescript#types-componenttype).
|
||||
|
||||
## 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 the 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.
|
||||
|
||||
```svelte
|
||||
<script>
|
||||
import { Icon } from '@lucide/svelte';
|
||||
import { pear, sausage } from '@lucide/lab';
|
||||
</script>
|
||||
|
||||
<Icon iconNode={pear} />
|
||||
<Icon iconNode={sausage} color="red"/>
|
||||
```
|
||||
|
||||
## 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
|
||||
|
||||
::: code-group
|
||||
|
||||
```svelte [Svelte 5]
|
||||
<script>
|
||||
import * as icons from '@lucide/svelte';
|
||||
let { name, ...props } = $props();
|
||||
|
||||
const Icon = icons[name];
|
||||
</script>
|
||||
|
||||
<Icon {...props} />
|
||||
```
|
||||
|
||||
```svelte [Svelte 4]
|
||||
<script>
|
||||
import * as icons from '@lucide/svelte';
|
||||
export let name;
|
||||
</script>
|
||||
|
||||
<svelte:component this={icons[name]} {...$$props} />
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
#### Using the Icon Component
|
||||
|
||||
```svelte
|
||||
<script>
|
||||
import LucideIcon from './LucideIcon';
|
||||
</script>
|
||||
|
||||
<LucideIcon name="Menu" />
|
||||
```
|
||||
|
||||
## Accessibility
|
||||
|
||||
By default, we hide icons from screen readers using `aria-hidden="true"`.
|
||||
|
||||
You can add accessibility attributes using aria-labels.
|
||||
|
||||
```svelte
|
||||
<script>
|
||||
import { Check } from '@lucide/svelte';
|
||||
</script>
|
||||
|
||||
<Check aria-label="Task completed" />
|
||||
```
|
||||
|
||||
For best practices on accessibility, please see our [accessibility guide](../accessibility.md).
|
||||
@@ -1,171 +0,0 @@
|
||||
# Lucide Vue
|
||||
|
||||
Vue 2 components for Lucide icons that integrate with Vue's Options API and template system. Each icon is a Vue component that renders as an inline SVG, providing familiar Vue development patterns for legacy applications still using Vue 2.
|
||||
|
||||
**What you can accomplish:**
|
||||
|
||||
- Use icons as Vue 2 components with Options API integration
|
||||
- Maintain legacy Vue 2 applications with modern icon components
|
||||
- Integrate with Vue 2's template system and component lifecycle
|
||||
- Build applications using Vue 2's familiar syntax and patterns
|
||||
- Bridge the gap while planning migration to Vue 3
|
||||
|
||||
## Installation
|
||||
|
||||
::: code-group
|
||||
|
||||
```sh [pnpm]
|
||||
pnpm add @lucide/vue
|
||||
```
|
||||
|
||||
```sh [yarn]
|
||||
yarn add @lucide/vue
|
||||
```
|
||||
|
||||
```sh [npm]
|
||||
npm install @lucide/vue
|
||||
```
|
||||
|
||||
```sh [bun]
|
||||
bun add @lucide/vue
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
## 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';
|
||||
</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';
|
||||
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";
|
||||
|
||||
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>
|
||||
```
|
||||
|
||||
## Accessibility
|
||||
|
||||
By default, we hide icons from screen readers using `aria-hidden="true"`.
|
||||
|
||||
You can add accessibility attributes using aria-labels.
|
||||
|
||||
```vue
|
||||
<script setup>
|
||||
import { Check } from '@lucide/vue';
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Check
|
||||
color="red"
|
||||
:size="32"
|
||||
aria-label="Task completed"
|
||||
/>
|
||||
</template>
|
||||
```
|
||||
|
||||
For best practices on accessibility, please see our [accessibility guide](../accessibility.md).
|
||||
@@ -2,6 +2,7 @@
|
||||
title: Combining icons - Preact
|
||||
description: Learn how to combine multiple icons into a single icon nested SVG elements in your Preact application.
|
||||
---
|
||||
|
||||
<script setup>
|
||||
import Sandpack from '~/.vitepress/theme/components/editors/SandpackPreact.vue'
|
||||
</script>
|
||||
@@ -14,18 +15,21 @@ This is useful if you want to create custom icons by combining existing ones.
|
||||
::: sandpack {showTabs=false editorHeight=400 editorWidthPercentage=60 dependencies="lucide-preact"}
|
||||
|
||||
```jsx App.js [active]
|
||||
import { Scan, User } from "lucide-preact";
|
||||
import { h } from "preact";
|
||||
import { Scan, User } from 'lucide-preact';
|
||||
import { h } from 'preact';
|
||||
|
||||
function App() {
|
||||
return (
|
||||
<div className="app">
|
||||
<Scan size={48}>
|
||||
<Scan
|
||||
size={48}
|
||||
nonScalingStroke
|
||||
>
|
||||
<User
|
||||
size={12}
|
||||
x={6}
|
||||
y={6}
|
||||
absoluteStrokeWidth
|
||||
nonScalingStroke
|
||||
/>
|
||||
</Scan>
|
||||
</div>
|
||||
@@ -33,8 +37,8 @@ function App() {
|
||||
}
|
||||
|
||||
export default App;
|
||||
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
This is valid, since [SVGs can be nested](https://developer.mozilla.org/en-US/docs/Web/SVG/Reference/Element/svg#nested_svg_element), and all SVG properties are supported on the icons.
|
||||
@@ -55,8 +59,8 @@ For example, you can add a notification badge to an icon by using the `circle` S
|
||||
::: sandpack {showTabs=false editorHeight=580 editorWidthPercentage=60 dependencies="lucide-preact"}
|
||||
|
||||
```jsx App.js [active]
|
||||
import { Mail } from "lucide-preact";
|
||||
import { h } from "preact";
|
||||
import { Mail } from 'lucide-preact';
|
||||
import { h } from 'preact';
|
||||
|
||||
function App() {
|
||||
const hasUnreadMessages = true;
|
||||
@@ -79,8 +83,8 @@ function App() {
|
||||
}
|
||||
|
||||
export default App;
|
||||
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
### Example with text element
|
||||
@@ -90,8 +94,8 @@ You can also use the `text` SVG element to add text to your icon.
|
||||
::: sandpack {showTabs=false editorHeight=400 editorWidthPercentage=60 dependencies="lucide-preact"}
|
||||
|
||||
```jsx App.js [active]
|
||||
import { File } from "lucide-preact";
|
||||
import { h } from "preact";
|
||||
import { File } from 'lucide-preact';
|
||||
import { h } from 'preact';
|
||||
|
||||
function App() {
|
||||
return (
|
||||
@@ -112,6 +116,6 @@ function App() {
|
||||
}
|
||||
|
||||
export default App;
|
||||
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
title: Global Styling - Preact
|
||||
description: Learn how to style all Lucide icons globally in your Preact application using CSS or the Lucide context provider.
|
||||
---
|
||||
|
||||
<script setup>
|
||||
import Sandpack from '~/.vitepress/theme/components/editors/SandpackPreact.vue'
|
||||
</script>
|
||||
@@ -34,8 +35,8 @@ const App = () => (
|
||||
|
||||
This will apply the `color`, `size` and `strokeWidth` props to all icons that are children of the `LucideProvider`.
|
||||
|
||||
|
||||
## Style by using CSS
|
||||
|
||||
Styling icons is easy to accomplish using CSS.
|
||||
|
||||
Every icon has a class attribute applied called `lucide`. This class name can be used in the CSS file to target all icons that are being used within the app.
|
||||
@@ -74,9 +75,9 @@ import {
|
||||
Sandwich,
|
||||
Wine,
|
||||
Dessert,
|
||||
} from "lucide-preact";
|
||||
import { h } from "preact";
|
||||
import "./icon.css";
|
||||
} from 'lucide-preact';
|
||||
import { h } from 'preact';
|
||||
import './icon.css';
|
||||
|
||||
function App() {
|
||||
return (
|
||||
@@ -99,10 +100,9 @@ export default App;
|
||||
|
||||
:::
|
||||
|
||||
### Non-scaling strokes
|
||||
|
||||
### Absolute stroke width
|
||||
|
||||
For global absolute stroke width styling the `vector-effect: non-scaling-stroke` CSS property can be applied to the children. This will keep the stroke-width the same size no matter the size of the icon. See [absolute-stroke-width](../basics/stroke-width.md#absolute-stroke-width) for more info.
|
||||
For global non-scaling stroke width styling the `vector-effect: non-scaling-stroke` CSS property can be applied to the children. This will keep the stroke-width the same size no matter the size of the icon. See [non-scaling strokes](../basics/stroke-width.md#non-scaling-strokes) for more info.
|
||||
|
||||
::: sandpack {editorHeight=480 editorWidthPercentage=60 dependencies="lucide-preact"}
|
||||
|
||||
@@ -136,9 +136,9 @@ import {
|
||||
Map,
|
||||
CloudMoon,
|
||||
Sparkles,
|
||||
} from "lucide-preact";
|
||||
import { h } from "preact";
|
||||
import "./icon.css";
|
||||
} from 'lucide-preact';
|
||||
import { h } from 'preact';
|
||||
import './icon.css';
|
||||
|
||||
function App() {
|
||||
return (
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
title: Typescript - Preact
|
||||
description: Learn about the different types exported by the `lucide-preact` package and how to use them in your Preact application.
|
||||
---
|
||||
|
||||
# TypeScript
|
||||
|
||||
List of exported types from the `lucide-preact` package.
|
||||
@@ -16,12 +17,17 @@ interface LucideProps {
|
||||
size?: number | string;
|
||||
color?: string;
|
||||
strokeWidth?: number;
|
||||
nonScalingStroke?: boolean;
|
||||
/**
|
||||
* @deprecated
|
||||
*/
|
||||
absoluteStrokeWidth?: boolean;
|
||||
[key: string]: any; // Any other SVG attributes
|
||||
}
|
||||
```
|
||||
|
||||
### Using `LucideProps`
|
||||
|
||||
You can use the `LucideProps` interface to type your custom icon components or when you need to work with icon props.
|
||||
|
||||
```tsx
|
||||
@@ -76,6 +82,7 @@ type IconNode = [elementName: string, attrs: Record<string, string | number>][];
|
||||
```
|
||||
|
||||
### Using `IconNode`
|
||||
|
||||
You can use the `IconNode` type when you need to work with the raw SVG structure of an icon.
|
||||
|
||||
```tsx
|
||||
@@ -89,7 +96,11 @@ const customIcon: IconNode = [
|
||||
|
||||
const MyCustomIcon = () => {
|
||||
return (
|
||||
<Icon iconNode={customIcon} size={24} color="blue" />
|
||||
<Icon
|
||||
iconNode={customIcon}
|
||||
size={24}
|
||||
color="blue"
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
---
|
||||
title: Stroke width - Preact
|
||||
description: Learn how to adjust the stroke width of icons in your Preact application using the `strokeWidth` prop or adjust the strokeWidth appearance using the `absoluteStrokeWidth` prop.
|
||||
description: Learn how to adjust the stroke width of icons in your Preact application using the `strokeWidth` prop or adjust the strokeWidth appearance using the `nonScalingStroke` prop.
|
||||
---
|
||||
|
||||
<script setup>
|
||||
import Sandpack from '~/.vitepress/theme/components/editors/SandpackPreact.vue'
|
||||
</script>
|
||||
@@ -18,8 +19,8 @@ The `strokeWidth` can be adjusted to create a different look of the icons.
|
||||
::: sandpack {showTabs=false editorHeight=320 editorWidthPercentage=60 dependencies="lucide-preact"}
|
||||
|
||||
```jsx App.js [active]
|
||||
import { h } from "preact";
|
||||
import { FolderLock } from "lucide-preact";
|
||||
import { h } from 'preact';
|
||||
import { FolderLock } from 'lucide-preact';
|
||||
|
||||
function App() {
|
||||
return (
|
||||
@@ -31,34 +32,35 @@ function App() {
|
||||
|
||||
export default App;
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
## Absolute stroke width
|
||||
## Non-scaling strokes
|
||||
|
||||
When adjusting the `size` prop the size of the stroke width will be relative to the size of the icon, this is the default SVG behavior. The `absoluteStrokeWidth` prop is introduced to adjust this behavior to make the stroke width constant no matter the size of the icon.
|
||||
When adjusting the `size` prop the size of the stroke width will be relative to the size of the icon, this is the default SVG behavior. The `nonScalingStroke` prop is introduced to adjust this behavior to make the stroke width constant no matter the size of the icon.
|
||||
|
||||
This means that when `absoluteStrokeWidth` is enabled and the `size` of the icons is set to `48px` the `strokeWidth` will still be `2px` on the screen.
|
||||
This means that when `nonScalingStroke` is enabled and the `size` of the icons is set to `48px` the `strokeWidth` will still be `2px` on the screen.
|
||||
|
||||
Note `2px` is the default stroke width for a Lucide icon, this can be adjusted to all sizes.
|
||||
|
||||

|
||||
<!--@include: ../../../images/non-scaling-stroke-compare.svg -->
|
||||
|
||||
### Adjusting stroke width with `absoluteStrokeWidth` prop
|
||||
### Adjusting stroke width with `nonScalingStroke` prop
|
||||
|
||||
Setting `absoluteStrokeWidth` to `true` will make the stroke width absolute.
|
||||
Setting `nonScalingStroke` to `true` will make the stroke width non-scaling.
|
||||
|
||||
::: sandpack {showTabs=false editorHeight=340 editorWidthPercentage=60 dependencies="lucide-preact"}
|
||||
|
||||
```jsx App.js [active]
|
||||
import { h } from "preact";
|
||||
import { RollerCoaster } from "lucide-preact";
|
||||
import { h } from 'preact';
|
||||
import { RollerCoaster } from 'lucide-preact';
|
||||
|
||||
function App() {
|
||||
return (
|
||||
<div className="app">
|
||||
<RollerCoaster
|
||||
size={96}
|
||||
absoluteStrokeWidth={true}
|
||||
nonScalingStroke
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
@@ -66,4 +68,5 @@ function App() {
|
||||
|
||||
export default App;
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
title: Getting started - Preact
|
||||
description: This guide will help you get started with Lucide in your Preact project.
|
||||
---
|
||||
|
||||
<script setup lang="ts">
|
||||
import OverviewLink from '../../.vitepress/theme/components/base/OverviewLink.vue'
|
||||
import OverviewLinkGrid from '../../.vitepress/theme/components/base/OverviewLinkGrid.vue'
|
||||
@@ -56,19 +57,25 @@ export default App;
|
||||
|
||||
To customize the appearance of an icon, you can use the following props:
|
||||
|
||||
| name | type | default |
|
||||
| --------------------- | --------- | ------------ |
|
||||
| `size` | *number* | 24 |
|
||||
| `color` | *string* | currentColor |
|
||||
| `strokeWidth` | *number* | 2 |
|
||||
| `absoluteStrokeWidth` | *boolean* | false |
|
||||
| name | type | default |
|
||||
| ------------------ | --------- | ------------ |
|
||||
| `size` | _number_ | 24 |
|
||||
| `color` | _string_ | currentColor |
|
||||
| `strokeWidth` | _number_ | 2 |
|
||||
| `nonScalingStroke` | _boolean_ | false |
|
||||
|
||||
Because icons render as SVG elements, all standard SVG attributes can also be applied as props. See the list of SVG Presentation Attributes on [MDN](https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/Presentation).
|
||||
|
||||
```jsx
|
||||
// Usage
|
||||
const App = () => {
|
||||
return <Camera size={48} color="red" strokeWidth={1} />;
|
||||
return (
|
||||
<Camera
|
||||
size={48}
|
||||
color="red"
|
||||
strokeWidth={1}
|
||||
/>
|
||||
);
|
||||
};
|
||||
```
|
||||
|
||||
|
||||
@@ -16,12 +16,12 @@ import { Scan, User} from "lucide-react-native";
|
||||
const App = () => {
|
||||
return (
|
||||
<View style={styles.container}>
|
||||
<Scan size={48}>
|
||||
<Scan size={48} nonScalingStroke>
|
||||
<User
|
||||
size={12}
|
||||
x={6}
|
||||
y={6}
|
||||
absoluteStrokeWidth
|
||||
nonScalingStroke
|
||||
/>
|
||||
</Scan>
|
||||
</View>
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
title: Typescript - React Native
|
||||
description: Learn about the different types exported by the `lucide-react-native` package and how to use them in your React Native application.
|
||||
---
|
||||
|
||||
# TypeScript Support
|
||||
|
||||
List of exported types from the `lucide-react-native` package.
|
||||
@@ -16,12 +17,17 @@ interface LucideProps {
|
||||
size?: number | string;
|
||||
color?: string;
|
||||
strokeWidth?: number;
|
||||
nonScalingStroke?: boolean;
|
||||
/**
|
||||
* @deprecated
|
||||
*/
|
||||
absoluteStrokeWidth?: boolean;
|
||||
[key: string]: any; // Any other SVG props, supported by react-native-svg
|
||||
}
|
||||
```
|
||||
|
||||
### Using `LucideProps`
|
||||
|
||||
You can use the `LucideProps` interface to type your custom icon components or when you need to work with icon props.
|
||||
|
||||
```tsx
|
||||
@@ -75,6 +81,7 @@ type IconNode = [elementName: string, attrs: Record<string, string | number>][];
|
||||
```
|
||||
|
||||
### Using `IconNode`
|
||||
|
||||
You can use the `IconNode` type when you need to work with the raw SVG structure of an icon.
|
||||
|
||||
```tsx
|
||||
@@ -88,7 +95,11 @@ const customIcon: IconNode = [
|
||||
|
||||
const MyCustomIcon = () => {
|
||||
return (
|
||||
<Icon iconNode={customIcon} size={24} color="blue" />
|
||||
<Icon
|
||||
iconNode={customIcon}
|
||||
size={24}
|
||||
color="blue"
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
---
|
||||
title: Stroke width - React Native
|
||||
description: Learn how to adjust the stroke width of icons in your React Native application using the `strokeWidth` prop or adjust the strokeWidth appearance using the `absoluteStrokeWidth` prop.
|
||||
description: Learn how to adjust the stroke width of icons in your React Native application using the `strokeWidth` prop or adjust the strokeWidth appearance using the `nonScalingStroke` prop.
|
||||
---
|
||||
|
||||
# Stroke width
|
||||
|
||||
All icons are designed with SVG elements using strokes.
|
||||
@@ -29,19 +30,19 @@ const App = () => {
|
||||
export default App;
|
||||
```
|
||||
|
||||
## Absolute stroke width
|
||||
## Non-scaling strokes
|
||||
|
||||
When adjusting the `size` prop the size of the stroke width will be relative to the size of the icon, this is the default SVG behavior. The `absoluteStrokeWidth` prop is introduced to adjust this behavior to make the stroke width constant no matter the size of the icon.
|
||||
When adjusting the `size` prop the size of the stroke width will be relative to the size of the icon, this is the default SVG behavior. The `nonScalingStroke` prop is introduced to adjust this behavior to make the stroke width constant no matter the size of the icon.
|
||||
|
||||
This means that when `absoluteStrokeWidth` is enabled and the `size` of the icons is set to `48px` the `strokeWidth` will still be `2px` on the screen.
|
||||
This means that when `nonScalingStroke` is enabled and the `size` of the icons is set to `48px` the `strokeWidth` will still be `2px` on the screen.
|
||||
|
||||
Note `2px` is the default stroke width for a Lucide icon, this can be adjusted to all sizes.
|
||||
|
||||

|
||||
<!--@include: ../../../images/non-scaling-stroke-compare.svg -->
|
||||
|
||||
### Adjusting stroke width with `absoluteStrokeWidth` prop
|
||||
### Adjusting stroke width with `nonScalingStroke` prop
|
||||
|
||||
Setting `absoluteStrokeWidth` to `true` will make the stroke width absolute.
|
||||
Setting `nonScalingStroke` to `true` will make the stroke width non-scaling.
|
||||
|
||||
```SnackPlayer name=State&ext=js&dependencies=react-native-svg,lucide-react-native
|
||||
import React, {useState, useEffect} from 'react';
|
||||
@@ -55,7 +56,7 @@ const App = () => {
|
||||
<View style={style}>
|
||||
<RollerCoaster
|
||||
size={96}
|
||||
absoluteStrokeWidth={true}
|
||||
nonScalingStroke
|
||||
/>
|
||||
</View>
|
||||
);
|
||||
@@ -67,7 +68,7 @@ export default App;
|
||||
<!-- <Sandpack
|
||||
template="react"
|
||||
:theme="sandpackTheme"
|
||||
:files="absoluteStrokeWidth"
|
||||
:files="nonScalingStroke"
|
||||
:customSetup='{
|
||||
dependencies: {
|
||||
"lucide-react": "latest"
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
title: Getting started - React Native
|
||||
description: This guide will help you get started with Lucide in your React Native project.
|
||||
---
|
||||
|
||||
<script setup>
|
||||
import OverviewLink from '../../.vitepress/theme/components/base/OverviewLink.vue'
|
||||
import OverviewLinkGrid from '../../.vitepress/theme/components/base/OverviewLinkGrid.vue'
|
||||
@@ -58,19 +59,25 @@ export default App;
|
||||
|
||||
To customize the appearance of an icon, you can use the following props:
|
||||
|
||||
| name | type | default |
|
||||
| --------------------- | --------- | ------------ |
|
||||
| `size` | *number* | 24 |
|
||||
| `color` | *string* | currentColor |
|
||||
| `strokeWidth` | *number* | 2 |
|
||||
| `absoluteStrokeWidth` | *boolean* | false |
|
||||
| name | type | default |
|
||||
| ------------------ | --------- | ------------ |
|
||||
| `size` | _number_ | 24 |
|
||||
| `color` | _string_ | currentColor |
|
||||
| `strokeWidth` | _number_ | 2 |
|
||||
| `nonScalingStroke` | _boolean_ | false |
|
||||
|
||||
Because icons render as SVG elements, all standard SVG attributes can also be applied as props. See the list of SVG Presentation Attributes on [MDN](https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/Presentation).
|
||||
|
||||
```jsx
|
||||
// Usage
|
||||
const App = () => {
|
||||
return <Camera size={48} color="red" strokeWidth={1} />;
|
||||
return (
|
||||
<Camera
|
||||
size={48}
|
||||
color="red"
|
||||
strokeWidth={1}
|
||||
/>
|
||||
);
|
||||
};
|
||||
```
|
||||
|
||||
|
||||
@@ -19,12 +19,12 @@ import { Scan, User } from "lucide-react";
|
||||
function App() {
|
||||
return (
|
||||
<div className="app">
|
||||
<Scan size={48}>
|
||||
<Scan size={48} nonScalingStroke>
|
||||
<User
|
||||
size={12}
|
||||
x={6}
|
||||
y={6}
|
||||
absoluteStrokeWidth
|
||||
nonScalingStroke
|
||||
/>
|
||||
</Scan>
|
||||
</div>
|
||||
|
||||
@@ -99,9 +99,9 @@ export default App;
|
||||
|
||||
:::
|
||||
|
||||
### Absolute stroke width
|
||||
### Non-scaling strokes
|
||||
|
||||
For global absolute stroke width styling the `vector-effect: non-scaling-stroke` CSS property can be applied to the children. This will keep the stroke-width the same size no matter the size of the icon. See [absolute-stroke-width](../basics/stroke-width.md#absolute-stroke-width) for more info.
|
||||
For global non-scaling stroke width styling the `vector-effect: non-scaling-stroke` CSS property can be applied to the children. This will keep the stroke-width the same size no matter the size of the icon. See [non-scaling strokes](../basics/stroke-width.md#non-scaling-strokes) for more info.
|
||||
|
||||
::: sandpack {template=react editorHeight=300 dependencies="lucide-react"}
|
||||
|
||||
|
||||
@@ -16,6 +16,10 @@ interface LucideProps {
|
||||
size?: number | string;
|
||||
color?: string;
|
||||
strokeWidth?: number;
|
||||
nonScalingStroke?: boolean;
|
||||
/**
|
||||
* @deprecated
|
||||
*/
|
||||
absoluteStrokeWidth?: boolean;
|
||||
[key: string]: any; // Any other SVG attributes
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
title: Stroke width - React
|
||||
description: Learn how to adjust the stroke width of icons in your React application using the `strokeWidth` prop or adjust the strokeWidth appearance using the `absoluteStrokeWidth` prop.
|
||||
description: Learn how to adjust the stroke width of icons in your React application using the `strokeWidth` prop or adjust the strokeWidth appearance using the `nonScalingStroke` prop.
|
||||
---
|
||||
<script setup>
|
||||
import Sandpack from '~/.vitepress/theme/components/editors/Sandpack.vue'
|
||||
@@ -33,19 +33,19 @@ export default App;
|
||||
:::
|
||||
|
||||
|
||||
## Absolute stroke width
|
||||
## Non-scaling strokes
|
||||
|
||||
When adjusting the `size` prop the size of the stroke width will be relative to the size of the icon, this is the default SVG behavior. The `absoluteStrokeWidth` prop is introduced to adjust this behavior to make the stroke width constant no matter the size of the icon.
|
||||
When adjusting the `size` prop the size of the stroke width will be relative to the size of the icon, this is the default SVG behavior. The `nonScalingStroke` prop is introduced to adjust this behavior to make the stroke width constant no matter the size of the icon.
|
||||
|
||||
This means that when `absoluteStrokeWidth` is enabled and the `size` of the icons is set to `48px` the `strokeWidth` will still be `2px` on the screen.
|
||||
This means that when `nonScalingStroke` is enabled and the `size` of the icons is set to `48px` the `strokeWidth` will still be `2px` on the screen.
|
||||
|
||||
Note `2px` is the default stroke width for a Lucide icon, this can be adjusted to all sizes.
|
||||
|
||||

|
||||
<!--@include: ../../../images/non-scaling-stroke-compare.svg -->
|
||||
|
||||
### Adjusting stroke width with `absoluteStrokeWidth` prop
|
||||
### Adjusting stroke width with `nonScalingStroke` prop
|
||||
|
||||
Setting `absoluteStrokeWidth` to `true` will make the stroke width absolute.
|
||||
Setting `nonScalingStroke` to `true` will make the stroke width non-scaling.
|
||||
|
||||
::: sandpack {template=react showTabs=false editorHeight=320 editorWidthPercentage=60 dependencies="lucide-react"}
|
||||
|
||||
@@ -57,7 +57,7 @@ function App() {
|
||||
<div className="app">
|
||||
<RollerCoaster
|
||||
size={96}
|
||||
absoluteStrokeWidth={true}
|
||||
nonScalingStroke
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -54,12 +54,12 @@ export default App;
|
||||
|
||||
To customize the appearance of an icon, you can use the following props:
|
||||
|
||||
| name | type | default |
|
||||
| --------------------- | --------- | ------------ |
|
||||
| `size` | *number* | 24 |
|
||||
| `color` | *string* | currentColor |
|
||||
| `strokeWidth` | *number* | 2 |
|
||||
| `absoluteStrokeWidth` | *boolean* | false |
|
||||
| name | type | default |
|
||||
|--------------------| --------- | ------------ |
|
||||
| `size` | *number* | 24 |
|
||||
| `color` | *string* | currentColor |
|
||||
| `strokeWidth` | *number* | 2 |
|
||||
| `nonScalingStroke` | *boolean* | false |
|
||||
|
||||
Because icons render as SVG elements, all standard SVG attributes can also be applied as props. See the list of SVG Presentation Attributes on [MDN](https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/Presentation).
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
title: Combining icons - Solid
|
||||
description: Learn how to combine multiple icons into a single icon nested SVG elements in your Solid application.
|
||||
---
|
||||
|
||||
<!-- Not working yet -->
|
||||
<script setup>
|
||||
import Sandpack from '~/.vitepress/theme/components/editors/Sandpack.vue'
|
||||
@@ -21,12 +22,15 @@ import User from 'lucide-solid/icons/user';
|
||||
function App() {
|
||||
return (
|
||||
<div class="app">
|
||||
<Scan size={48}>
|
||||
<Scan
|
||||
size={48}
|
||||
nonScalingStroke
|
||||
>
|
||||
<User
|
||||
size={12}
|
||||
x={6}
|
||||
y={6}
|
||||
absoluteStrokeWidth
|
||||
nonScalingStroke
|
||||
/>
|
||||
</Scan>
|
||||
</div>
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
title: Global Styling - Solid
|
||||
description: Learn how to style all Lucide icons globally in your Solid application using CSS or the Lucide context provider.
|
||||
---
|
||||
|
||||
<script setup>
|
||||
import Sandpack from '~/.vitepress/theme/components/editors/Sandpack.vue'
|
||||
</script>
|
||||
@@ -36,8 +37,8 @@ const App = () => (
|
||||
|
||||
This will apply the `color`, `size` and `strokeWidth` props to all icons that are children of the `LucideProvider`.
|
||||
|
||||
|
||||
## Style by using CSS
|
||||
|
||||
Styling icons is easy to accomplish using CSS.
|
||||
|
||||
Every icon has a class attribute applied called `lucide`. This class name can be used in the CSS file to target all icons that are being used within the app.
|
||||
@@ -75,7 +76,7 @@ import IceCream2 from 'lucide-solid/icons/ice-cream-2';
|
||||
import Sandwich from 'lucide-solid/icons/sandwich';
|
||||
import Wine from 'lucide-solid/icons/wine';
|
||||
import Dessert from 'lucide-solid/icons/dessert';
|
||||
import "./icon.css";
|
||||
import './icon.css';
|
||||
|
||||
function App() {
|
||||
return (
|
||||
@@ -95,11 +96,12 @@ function App() {
|
||||
|
||||
export default App;
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
### Absolute stroke width
|
||||
### Non-scaling strokes
|
||||
|
||||
For global absolute stroke width styling the `vector-effect: non-scaling-stroke` CSS property can be applied to the children. This will keep the stroke-width the same size no matter the size of the icon. See [absolute-stroke-width](../basics/stroke-width.md#absolute-stroke-width) for more info.
|
||||
For global non-scaling stroke width styling the `vector-effect: non-scaling-stroke` CSS property can be applied to the children. This will keep the stroke-width the same size no matter the size of the icon. See [non-scaling strokes](../basics/stroke-width.md#non-scaling-strokes) for more info.
|
||||
|
||||
::: sandpack {template=vite-solid editorHeight=300 editorWidthPercentage=60 dependencies="lucide-solid"}
|
||||
|
||||
@@ -120,7 +122,6 @@ For global absolute stroke width styling the `vector-effect: non-scaling-stroke`
|
||||
grid-template-rows: 1fr 1fr 1fr;
|
||||
gap: 6px;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
```tsx App.tsx
|
||||
@@ -133,7 +134,7 @@ import Axe from 'lucide-solid/icons/axe';
|
||||
import Map from 'lucide-solid/icons/map';
|
||||
import CloudMoon from 'lucide-solid/icons/cloud-moon';
|
||||
import Sparkles from 'lucide-solid/icons/sparkles';
|
||||
import "./icon.css";
|
||||
import './icon.css';
|
||||
|
||||
function App() {
|
||||
return (
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
title: Typescript - Solid
|
||||
description: Learn about the different types exported by the `lucide-solid` package and how to use them in your Solid application.
|
||||
---
|
||||
|
||||
# TypeScript Support
|
||||
|
||||
List of exported types from the `lucide-solid` package.
|
||||
@@ -16,12 +17,17 @@ interface LucideProps extends SVGAttributes {
|
||||
size?: number | string;
|
||||
color?: string;
|
||||
strokeWidth?: number;
|
||||
nonScalingStroke?: boolean;
|
||||
/**
|
||||
* @deprecated
|
||||
*/
|
||||
absoluteStrokeWidth?: boolean;
|
||||
[key: string]: any; // Any other SVG attributes
|
||||
}
|
||||
```
|
||||
|
||||
### Using `LucideProps`
|
||||
|
||||
You can use the `LucideProps` interface to type your custom icon components or when you need to work with icon props.
|
||||
|
||||
```tsx
|
||||
@@ -76,6 +82,7 @@ type IconNode = [elementName: string, attrs: Record<string, string | number>][];
|
||||
```
|
||||
|
||||
### Using `IconNode`
|
||||
|
||||
You can use the `IconNode` type when you need to work with the raw SVG structure of an icon.
|
||||
|
||||
```tsx
|
||||
@@ -89,7 +96,11 @@ const customIcon: IconNode = [
|
||||
|
||||
const MyCustomIcon = () => {
|
||||
return (
|
||||
<Icon iconNode={customIcon} size={24} color="blue" />
|
||||
<Icon
|
||||
iconNode={customIcon}
|
||||
size={24}
|
||||
color="blue"
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
---
|
||||
title: Stroke width - Solid
|
||||
description: Learn how to adjust the stroke width of icons in your Solid application using the `strokeWidth` prop or adjust the strokeWidth appearance using the `absoluteStrokeWidth` prop.
|
||||
description: Learn how to adjust the stroke width of icons in your Solid application using the `strokeWidth` prop or adjust the strokeWidth appearance using the `nonScalingStroke` prop.
|
||||
---
|
||||
|
||||
<script setup>
|
||||
import Sandpack from '~/.vitepress/theme/components/editors/Sandpack.vue'
|
||||
</script>
|
||||
@@ -30,21 +31,22 @@ function App() {
|
||||
|
||||
export default App;
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
## Absolute stroke width
|
||||
## Non-scaling strokes
|
||||
|
||||
When adjusting the `size` prop the size of the stroke width will be relative to the size of the icon, this is the default SVG behavior. The `absoluteStrokeWidth` prop is introduced to adjust this behavior to make the stroke width constant no matter the size of the icon.
|
||||
When adjusting the `size` prop the size of the stroke width will be relative to the size of the icon, this is the default SVG behavior. The `nonScalingStroke` prop is introduced to adjust this behavior to make the stroke width constant no matter the size of the icon.
|
||||
|
||||
This means that when `absoluteStrokeWidth` is enabled and the `size` of the icons is set to `48px` the `strokeWidth` will still be `2px` on the screen.
|
||||
This means that when `nonScalingStroke` is enabled and the `size` of the icons is set to `48px` the `strokeWidth` will still be `2px` on the screen.
|
||||
|
||||
Note `2px` is the default stroke width for a Lucide icon, this can be adjusted to all sizes.
|
||||
|
||||

|
||||
<!--@include: ../../../images/non-scaling-stroke-compare.svg -->
|
||||
|
||||
### Adjusting stroke width with `absoluteStrokeWidth` prop
|
||||
### Adjusting stroke width with `nonScalingStroke` prop
|
||||
|
||||
Setting `absoluteStrokeWidth` to `true` will make the stroke width absolute.
|
||||
Setting `nonScalingStroke` to `true` will make the stroke width non-scaling.
|
||||
|
||||
::: sandpack {template=vite-solid showTabs=false editorHeight=320 editorWidthPercentage=60 dependencies="lucide-solid"}
|
||||
|
||||
@@ -56,7 +58,7 @@ function App() {
|
||||
<div class="app">
|
||||
<RollerCoaster
|
||||
size={96}
|
||||
absoluteStrokeWidth={true}
|
||||
nonScalingStroke
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
@@ -64,4 +66,5 @@ function App() {
|
||||
|
||||
export default App;
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
@@ -57,19 +57,25 @@ export default App;
|
||||
|
||||
To customize the appearance of an icon, you can use the following props:
|
||||
|
||||
| name | type | default |
|
||||
| --------------------- | --------- | ------------ |
|
||||
| `size` | *number* | 24 |
|
||||
| `color` | *string* | currentColor |
|
||||
| `strokeWidth` | *number* | 2 |
|
||||
| `absoluteStrokeWidth` | *boolean* | false |
|
||||
| name | type | default |
|
||||
| ------------------ | --------- | ------------ |
|
||||
| `size` | _number_ | 24 |
|
||||
| `color` | _string_ | currentColor |
|
||||
| `strokeWidth` | _number_ | 2 |
|
||||
| `nonScalingStroke` | _boolean_ | false |
|
||||
|
||||
Because icons render as SVG elements, all standard SVG attributes can also be applied as props. See the list of SVG Presentation Attributes on [MDN](https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/Presentation).
|
||||
|
||||
```jsx
|
||||
// Usage
|
||||
const App = () => {
|
||||
return <Camera size={48} color="red" strokeWidth={1} />;
|
||||
return (
|
||||
<Camera
|
||||
size={48}
|
||||
color="red"
|
||||
strokeWidth={1}
|
||||
/>
|
||||
);
|
||||
};
|
||||
```
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
title: Combining icons - Svelte
|
||||
description: Learn how to combine multiple icons into a single icon nested SVG elements in your Svelte application.
|
||||
---
|
||||
|
||||
<script setup>
|
||||
import Sandpack from '~/.vitepress/theme/components/editors/SandpackSvelte.vue';
|
||||
</script>
|
||||
@@ -20,12 +21,12 @@ import User from '@lucide/svelte/icons/user';
|
||||
</script>
|
||||
|
||||
<div class="app">
|
||||
<Scan size="48">
|
||||
<Scan size="48" nonScalingStroke>
|
||||
<User
|
||||
size="12"
|
||||
x="6"
|
||||
y="6"
|
||||
absoluteStrokeWidth
|
||||
nonScalingStroke
|
||||
/>
|
||||
</Scan>
|
||||
</div>
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
title: Global Styling - Svelte
|
||||
description: Learn how to style all Lucide icons globally in your Svelte application using CSS or the Lucide context provider.
|
||||
---
|
||||
|
||||
<script setup>
|
||||
import Sandpack from '~/.vitepress/theme/components/editors/SandpackSvelte.vue';
|
||||
</script>
|
||||
@@ -89,11 +90,12 @@ import "./icon.css";
|
||||
<Dessert />
|
||||
</div>
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
### Absolute stroke width
|
||||
### Non-scaling strokes
|
||||
|
||||
For global absolute stroke width styling the `vector-effect: non-scaling-stroke` CSS property can be applied to the children. This will keep the stroke-width the same size no matter the size of the icon. See [absolute-stroke-width](../basics/stroke-width.md#absolute-stroke-width) for more info.
|
||||
For global non-scaling stroke width styling the `vector-effect: non-scaling-stroke` CSS property can be applied to the children. This will keep the stroke-width the same size no matter the size of the icon. See [non-scaling strokes](../basics/stroke-width.md#non-scaling-strokes) for more info.
|
||||
|
||||
::: sandpack {template=vite-svelte editorHeight=420 editorWidthPercentage=55}
|
||||
|
||||
@@ -143,4 +145,5 @@ import "./icon.css";
|
||||
<Sparkles />
|
||||
</div>
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
title: Typescript - Svelte
|
||||
description: Learn about the different types exported by the `@lucide/svelte` package and how to use them in your Svelte application.
|
||||
---
|
||||
|
||||
# TypeScript Support
|
||||
|
||||
List of exported types from the `@lucide/svelte` package.
|
||||
@@ -17,6 +18,10 @@ interface LucideProps extends SVGAttributes<SVGSVGElement> {
|
||||
color?: string;
|
||||
size?: number | string;
|
||||
strokeWidth?: number | string;
|
||||
nonScalingStroke?: boolean;
|
||||
/**
|
||||
* @deprecated
|
||||
*/
|
||||
absoluteStrokeWidth?: boolean;
|
||||
children?: Snippet;
|
||||
[key: string]: any; // Any other SVG attributes
|
||||
@@ -24,9 +29,11 @@ interface LucideProps extends SVGAttributes<SVGSVGElement> {
|
||||
```
|
||||
|
||||
### Using `LucideProps`
|
||||
|
||||
You can use the `LucideProps` interface to type props for your custom icon components.
|
||||
|
||||
::: code-group
|
||||
|
||||
```svelte [IconWrapper.svelte]
|
||||
<script lang="ts">
|
||||
import { Camera, type LucideProps } from '@lucide/svelte';
|
||||
@@ -40,6 +47,7 @@ let props: LucideProps = $props();
|
||||
</div>
|
||||
</template>
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
## `LucideIcon`
|
||||
@@ -49,7 +57,7 @@ Type for individual icon components, this is use full when you want to type a va
|
||||
```ts
|
||||
import type { Component } from 'svelte';
|
||||
|
||||
type LucideIcon = Component<LucideProps>
|
||||
type LucideIcon = Component<LucideProps>;
|
||||
```
|
||||
|
||||
### Using `LucideIcon`
|
||||
@@ -135,6 +143,7 @@ You can use the `LucideIcon` type when you need to work with icon components dir
|
||||
{/each}
|
||||
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
## `IconNode`
|
||||
@@ -144,15 +153,17 @@ Not commonly used directly in application code. But can be useful for advanced u
|
||||
|
||||
```ts
|
||||
type IconNode = [
|
||||
elementName: 'circle' | 'ellipse'| 'g' | 'line' | 'path' | 'polygon' | 'polyline' | 'rect',
|
||||
attrs: SVGAttributes<SVGSVGElement>
|
||||
elementName: 'circle' | 'ellipse' | 'g' | 'line' | 'path' | 'polygon' | 'polyline' | 'rect',
|
||||
attrs: SVGAttributes<SVGSVGElement>,
|
||||
][];
|
||||
```
|
||||
|
||||
### Using `IconNode`
|
||||
|
||||
You can use the `IconNode` type when you need to work with the raw SVG structure of an icon.
|
||||
|
||||
::: code-group
|
||||
|
||||
```svelte [CustomIcon.svelte]
|
||||
<script lang="ts">
|
||||
import { type IconNode, Icon } from '@lucide/svelte';
|
||||
@@ -166,4 +177,5 @@ const customIcon: IconNode = [
|
||||
|
||||
<Icon iconNode={customIcon} size="24" color="blue" />
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
---
|
||||
title: Stroke width - Svelte
|
||||
description: Learn how to adjust the stroke width of icons in your Svelte application using the `strokeWidth` prop or adjust the strokeWidth appearance using the `absoluteStrokeWidth` prop.
|
||||
description: Learn how to adjust the stroke width of icons in your Svelte application using the `strokeWidth` prop or adjust the strokeWidth appearance using the `nonScalingStroke` prop.
|
||||
---
|
||||
|
||||
<script setup>
|
||||
import Sandpack from '~/.vitepress/theme/components/editors/SandpackSvelte.vue'
|
||||
</script>
|
||||
@@ -24,21 +25,22 @@ import FolderLock from "@lucide/svelte/icons/folder-lock";
|
||||
|
||||
<FolderLock strokeWidth={1} />
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
## Absolute stroke width
|
||||
## Non-scaling strokes
|
||||
|
||||
When adjusting the `size` prop the size of the stroke width will be relative to the size of the icon, this is the default SVG behavior. The `absoluteStrokeWidth` prop is introduced to adjust this behavior to make the stroke width constant no matter the size of the icon.
|
||||
When adjusting the `size` prop the size of the stroke width will be relative to the size of the icon, this is the default SVG behavior. The `nonScalingStroke` prop is introduced to adjust this behavior to make the stroke width constant no matter the size of the icon.
|
||||
|
||||
This means that when `absoluteStrokeWidth` is enabled and the `size` of the icons is set to `48px` the `strokeWidth` will still be `2px` on the screen.
|
||||
This means that when `nonScalingStroke` is enabled and the `size` of the icons is set to `48px` the `strokeWidth` will still be `2px` on the screen.
|
||||
|
||||
Note `2px` is the default stroke width for a Lucide icon, this can be adjusted to all sizes.
|
||||
|
||||

|
||||
<!--@include: ../../../images/non-scaling-stroke-compare.svg -->
|
||||
|
||||
### Adjusting stroke width with `absoluteStrokeWidth` prop
|
||||
### Adjusting stroke width with `nonScalingStroke` prop
|
||||
|
||||
Setting `absoluteStrokeWidth` to `true` will make the stroke width absolute.
|
||||
Setting `nonScalingStroke` to `true` will make the stroke width non-scaling.
|
||||
|
||||
::: sandpack {template=vite-svelte editorHeight=240 editorWidthPercentage=60}
|
||||
|
||||
@@ -49,7 +51,7 @@ import RollerCoaster from "@lucide/svelte/icons/roller-coaster";
|
||||
|
||||
<RollerCoaster
|
||||
size={96}
|
||||
absoluteStrokeWidth
|
||||
nonScalingStroke
|
||||
/>
|
||||
```
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
title: Getting started - Svelte
|
||||
description: This guide will help you get started with Lucide in your Svelte project.
|
||||
---
|
||||
|
||||
<script setup>
|
||||
import OverviewLink from '../../.vitepress/theme/components/base/OverviewLink.vue'
|
||||
import OverviewLinkGrid from '../../.vitepress/theme/components/base/OverviewLinkGrid.vue'
|
||||
@@ -53,13 +54,13 @@ Each icon can be imported as a Svelte component, which renders an inline SVG ele
|
||||
|
||||
To customize the appearance of an icon, you can use the following props:
|
||||
|
||||
| name | type | default |
|
||||
| ----------------------- | --------- | ------------ |
|
||||
| `size` | *number* | 24 |
|
||||
| `color` | *string* | currentColor |
|
||||
| `stroke-width` | *number* | 2 |
|
||||
| `absoluteStrokeWidth` | *boolean* | false |
|
||||
| `default-class` | *string* | lucide-icon |
|
||||
| name | type | default |
|
||||
| ------------------ | --------- | ------------ |
|
||||
| `size` | _number_ | 24 |
|
||||
| `color` | _string_ | currentColor |
|
||||
| `stroke-width` | _number_ | 2 |
|
||||
| `nonScalingStroke` | _boolean_ | false |
|
||||
| `default-class` | _string_ | lucide-icon |
|
||||
|
||||
Because icons render as SVG elements, all standard SVG attributes can also be applied as props. See the list of SVG Presentation Attributes on [MDN](https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/Presentation).
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
title: Combining icons - Vue
|
||||
description: Learn how to combine multiple icons into a single icon nested SVG elements in your Vue application.
|
||||
---
|
||||
|
||||
<script setup>
|
||||
import Sandpack from '~/.vitepress/theme/components/editors/SandpackVue.vue'
|
||||
</script>
|
||||
@@ -15,22 +16,24 @@ This is useful if you want to create custom icons by combining existing ones.
|
||||
|
||||
```vue src/App.vue [active]
|
||||
<script setup>
|
||||
import { Scan, User } from "@lucide/vue";
|
||||
import { Scan, User } from '@lucide/vue';
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="app">
|
||||
<Scan :size="48">
|
||||
<Scan
|
||||
:size="48"
|
||||
nonScalingStroke
|
||||
>
|
||||
<User
|
||||
:size="12"
|
||||
x="6"
|
||||
y="6"
|
||||
absoluteStrokeWidth
|
||||
nonScalingStroke
|
||||
/>
|
||||
</Scan>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
```
|
||||
|
||||
:::
|
||||
@@ -54,7 +57,7 @@ For example, you can add a notification badge to an icon by using the `circle` S
|
||||
|
||||
```vue src/App.vue [active]
|
||||
<script setup>
|
||||
import { Mail } from "@lucide/vue";
|
||||
import { Mail } from '@lucide/vue';
|
||||
|
||||
const hasUnreadMessages = true;
|
||||
</script>
|
||||
@@ -73,7 +76,6 @@ const hasUnreadMessages = true;
|
||||
</Mail>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
```
|
||||
|
||||
:::
|
||||
@@ -86,7 +88,7 @@ You can also use the `text` SVG element to add text to your icon.
|
||||
|
||||
```vue src/App.vue [active]
|
||||
<script setup>
|
||||
import { File } from "@lucide/vue";
|
||||
import { File } from '@lucide/vue';
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -104,7 +106,6 @@ import { File } from "@lucide/vue";
|
||||
</File>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
title: Global Styling - Vue
|
||||
description: Learn how to style all Lucide icons globally in your Vue application using CSS or the Lucide context provider.
|
||||
---
|
||||
|
||||
<script setup>
|
||||
import Sandpack from '~/.vitepress/theme/components/editors/SandpackVue.vue'
|
||||
</script>
|
||||
@@ -74,9 +75,9 @@ import {
|
||||
Sandwich,
|
||||
Wine,
|
||||
Dessert,
|
||||
} from "@lucide/vue";
|
||||
} from '@lucide/vue';
|
||||
|
||||
import "./icon.css";
|
||||
import './icon.css';
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -93,11 +94,12 @@ import "./icon.css";
|
||||
</div>
|
||||
</template>
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
### Absolute stroke width
|
||||
### Non-scaling strokes
|
||||
|
||||
For global absolute stroke width styling the `vector-effect: non-scaling-stroke` CSS property can be applied to the children. This will keep the stroke-width the same size no matter the size of the icon. See [absolute-stroke-width](../basics/stroke-width.md#absolute-stroke-width) for more info.
|
||||
For global non-scaling stroke width styling the `vector-effect: non-scaling-stroke` CSS property can be applied to the children. This will keep the stroke-width the same size no matter the size of the icon. See [non-scaling strokes](../basics/stroke-width.md#non-scaling-strokes) for more info.
|
||||
|
||||
::: sandpack {template=vue editorHeight=300 editorWidthPercentage=55 dependencies="@lucide/vue"}
|
||||
|
||||
@@ -132,9 +134,9 @@ import {
|
||||
Map,
|
||||
CloudMoon,
|
||||
Sparkles,
|
||||
} from "@lucide/vue";
|
||||
} from '@lucide/vue';
|
||||
|
||||
import "./icon.css";
|
||||
import './icon.css';
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -150,6 +152,6 @@ import "./icon.css";
|
||||
<Sparkles />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
title: Typescript - Vue
|
||||
description: Learn about the different types exported by the `@lucide/vue` package and how to use them in your Vue application.
|
||||
---
|
||||
|
||||
# TypeScript Support
|
||||
|
||||
List of exported types from the `@lucide/vue` package.
|
||||
@@ -16,15 +17,21 @@ interface LucideProps {
|
||||
size?: number | string;
|
||||
color?: string;
|
||||
strokeWidth?: number;
|
||||
nonScalingStroke?: boolean;
|
||||
/**
|
||||
* @deprecated
|
||||
*/
|
||||
absoluteStrokeWidth?: boolean;
|
||||
[key: string]: any; // Any other SVG attributes
|
||||
}
|
||||
```
|
||||
|
||||
### Using `LucideProps`
|
||||
|
||||
You can use the `LucideProps` interface to type props for your custom icon components.
|
||||
|
||||
::: code-group
|
||||
|
||||
```vue [IconWrapper.vue]
|
||||
<script lang="ts" setup>
|
||||
import { type LucideProps } from '@lucide/vue';
|
||||
@@ -39,6 +46,7 @@ defineProps<LucideProps>();
|
||||
</div>
|
||||
</template>
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
## `LucideIcon`
|
||||
@@ -54,6 +62,7 @@ type LucideIcon = React.FC<LucideProps>;
|
||||
You can use the `LucideIcon` type when you need to work with icon components directly.
|
||||
|
||||
::: code-group
|
||||
|
||||
```vue [IconButton.vue]
|
||||
<script lang="ts" setup>
|
||||
import { type LucideProps } from '@lucide/vue';
|
||||
@@ -67,10 +76,14 @@ defineProps<{
|
||||
|
||||
<template>
|
||||
<button :aria-label="label">
|
||||
<component :is="icon" :size="16" />
|
||||
<component
|
||||
:is="icon"
|
||||
:size="16"
|
||||
/>
|
||||
</button>
|
||||
</template>
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
## `IconNode`
|
||||
@@ -83,9 +96,11 @@ type IconNode = [elementName: string, attrs: Record<string, string | number>][];
|
||||
```
|
||||
|
||||
### Using `IconNode`
|
||||
|
||||
You can use the `IconNode` type when you need to work with the raw SVG structure of an icon.
|
||||
|
||||
::: code-group
|
||||
|
||||
```vue [CustomIcon.vue]
|
||||
<script lang="ts" setup>
|
||||
import { type IconNode, Icon } from '@lucide/vue';
|
||||
@@ -98,7 +113,12 @@ const customIcon: IconNode = [
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Icon :iconNode="customIcon" size="24" color="blue" />
|
||||
<Icon
|
||||
:iconNode="customIcon"
|
||||
size="24"
|
||||
color="blue"
|
||||
/>
|
||||
</template>
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
---
|
||||
title: Stroke width - Vue
|
||||
description: Learn how to adjust the stroke width of icons in your Vue application using the `strokeWidth` prop or adjust the strokeWidth appearance using the `absoluteStrokeWidth` prop.
|
||||
description: Learn how to adjust the stroke width of icons in your Vue application using the `strokeWidth` prop or adjust the strokeWidth appearance using the `nonScalingStroke` prop.
|
||||
---
|
||||
|
||||
<script setup>
|
||||
import Sandpack from '~/.vitepress/theme/components/editors/SandpackVue.vue'
|
||||
</script>
|
||||
@@ -19,42 +20,43 @@ The `strokeWidth` can be adjusted to create a different look of the icons.
|
||||
|
||||
```vue src/App.vue [active]
|
||||
<script setup>
|
||||
import { FolderLock } from "@lucide/vue";
|
||||
import { FolderLock } from '@lucide/vue';
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<FolderLock :strokeWidth="1" />
|
||||
</template>
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
## Absolute stroke width
|
||||
## Non-scaling strokes
|
||||
|
||||
When adjusting the `size` prop the size of the stroke width will be relative to the size of the icon, this is the default SVG behavior. The `absoluteStrokeWidth` prop is introduced to adjust this behavior to make the stroke width constant no matter the size of the icon.
|
||||
When adjusting the `size` prop the size of the stroke width will be relative to the size of the icon, this is the default SVG behavior. The `nonScalingStroke` prop is introduced to adjust this behavior to make the stroke width constant no matter the size of the icon.
|
||||
|
||||
This means that when `absoluteStrokeWidth` is enabled and the `size` of the icons is set to `48px` the `strokeWidth` will still be `2px` on the screen.
|
||||
This means that when `nonScalingStroke` is enabled and the `size` of the icons is set to `48px` the `strokeWidth` will still be `2px` on the screen.
|
||||
|
||||
Note `2px` is the default stroke width for a Lucide icon, this can be adjusted to all sizes.
|
||||
|
||||

|
||||
<!--@include: ../../../images/non-scaling-stroke-compare.svg -->
|
||||
|
||||
### Adjusting stroke width with `absoluteStrokeWidth` prop
|
||||
### Adjusting stroke width with `nonScalingStroke` prop
|
||||
|
||||
Setting `absoluteStrokeWidth` to `true` will make the stroke width absolute.
|
||||
Setting `nonScalingStroke` to `true` will make the stroke width non-scaling.
|
||||
|
||||
::: sandpack {template=vue showTabs=false editorHeight=320 editorWidthPercentage=60 dependencies="@lucide/vue"}
|
||||
|
||||
```vue src/App.vue [active]
|
||||
<script setup>
|
||||
import { RollerCoaster } from "@lucide/vue";
|
||||
import { RollerCoaster } from '@lucide/vue';
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<RollerCoaster
|
||||
:size="96"
|
||||
absoluteStrokeWidth
|
||||
nonScalingStroke
|
||||
/>
|
||||
</template>
|
||||
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
title: Getting started - Vue
|
||||
description: This guide will help you get started with Lucide in your Vue project.
|
||||
---
|
||||
|
||||
<script setup>
|
||||
import OverviewLink from '../../.vitepress/theme/components/base/OverviewLink.vue'
|
||||
import OverviewLinkGrid from '../../.vitepress/theme/components/base/OverviewLinkGrid.vue'
|
||||
@@ -55,13 +56,13 @@ import { Camera } from '@lucide/vue';
|
||||
|
||||
To customize the appearance of an icon, you can use the following props:
|
||||
|
||||
| name | type | default |
|
||||
| ----------------------- | --------- | ------------ |
|
||||
| `size` | *number* | 24 |
|
||||
| `color` | *string* | currentColor |
|
||||
| `stroke-width` | *number* | 2 |
|
||||
| `absoluteStrokeWidth` | *boolean* | false |
|
||||
| `default-class` | *string* | lucide-icon |
|
||||
| name | type | default |
|
||||
| ------------------ | --------- | ------------ |
|
||||
| `size` | _number_ | 24 |
|
||||
| `color` | _string_ | currentColor |
|
||||
| `stroke-width` | _number_ | 2 |
|
||||
| `nonScalingStroke` | _boolean_ | false |
|
||||
| `default-class` | _string_ | lucide-icon |
|
||||
|
||||
### Applying props
|
||||
|
||||
@@ -69,7 +70,11 @@ Because icons render as SVG elements, all standard SVG attributes can also be ap
|
||||
|
||||
```vue
|
||||
<template>
|
||||
<Camera :size="48" color="red" :stroke-width="1" />
|
||||
<Camera
|
||||
:size="48"
|
||||
color="red"
|
||||
:stroke-width="1"
|
||||
/>
|
||||
</template>
|
||||
```
|
||||
|
||||
|
||||
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 117 KiB |
+2
-2
@@ -6,8 +6,8 @@ outline: 2
|
||||
outlineTitle: Packages
|
||||
---
|
||||
<script setup>
|
||||
import PageContainer from '.vitepress/theme/components/PageContainer.vue'
|
||||
import PackageList from '.vitepress/theme/components/packages/PackageList.vue'
|
||||
import PageContainer from '~/.vitepress/theme/components/PageContainer.vue'
|
||||
import PackageList from '~/.vitepress/theme/components/packages/PackageList.vue'
|
||||
</script>
|
||||
|
||||
<div class="VPDoc content">
|
||||
|
||||
+2
-2
@@ -5,8 +5,8 @@ outline: 2
|
||||
outlineTitle: Showcase
|
||||
---
|
||||
<script setup>
|
||||
import PageContainer from '.vitepress/theme/components/PageContainer.vue'
|
||||
import ShowcaseList from '.vitepress/theme/components/showcase/ShowcaseList.vue'
|
||||
import PageContainer from '~/.vitepress/theme/components/PageContainer.vue'
|
||||
import ShowcaseList from '~/.vitepress/theme/components/showcase/ShowcaseList.vue'
|
||||
</script>
|
||||
|
||||
<div class="VPDoc content">
|
||||
|
||||
+5
-40
@@ -13,7 +13,7 @@
|
||||
},
|
||||
{
|
||||
"source": "/docs/:slug(lucide-?.*)",
|
||||
"destination": "/guide/packages/:slug",
|
||||
"destination": "/guide/:slug",
|
||||
"permanent": true
|
||||
},
|
||||
{
|
||||
@@ -58,48 +58,13 @@
|
||||
"permanent": true
|
||||
},
|
||||
{
|
||||
"source": "/guide/packages/lucide-react",
|
||||
"destination": "/guide/react",
|
||||
"source": "/guide/packages/lucide-:package",
|
||||
"destination": "/guide/:package",
|
||||
"permanent": true
|
||||
},
|
||||
{
|
||||
"source": "/guide/packages/lucide-vue-next",
|
||||
"destination": "/guide/vue",
|
||||
"permanent": true
|
||||
},
|
||||
{
|
||||
"source": "/guide/packages/lucide-vue",
|
||||
"destination": "/guide/vue",
|
||||
"permanent": true
|
||||
},
|
||||
{
|
||||
"source": "/guide/packages/lucide-svelte",
|
||||
"destination": "/guide/svelte",
|
||||
"permanent": true
|
||||
},
|
||||
{
|
||||
"source": "/guide/packages/lucide-solid",
|
||||
"destination": "/guide/solid",
|
||||
"permanent": true
|
||||
},
|
||||
{
|
||||
"source": "/guide/packages/lucide-angular",
|
||||
"destination": "/guide/angular",
|
||||
"permanent": true
|
||||
},
|
||||
{
|
||||
"source": "/guide/packages/lucide-preact",
|
||||
"destination": "/guide/preact",
|
||||
"permanent": true
|
||||
},
|
||||
{
|
||||
"source": "/guide/packages/lucide-astro",
|
||||
"destination": "/guide/astro",
|
||||
"permanent": true
|
||||
},
|
||||
{
|
||||
"source": "/guide/packages/lucide-static",
|
||||
"destination": "/guide/static",
|
||||
"source": "/guide/packages/:package",
|
||||
"destination": "/guide/:package",
|
||||
"permanent": true
|
||||
},
|
||||
{
|
||||
|
||||
@@ -60,6 +60,7 @@
|
||||
"@vitest/coverage-v8": "4.1.10",
|
||||
"@vitest/ui": "4.1.10",
|
||||
"ajv-cli": "^5.0.0",
|
||||
"cpy-cli": "^7.0.0",
|
||||
"cspell": "^10.0.1",
|
||||
"dotenv": "^17.4.2",
|
||||
"eslint": "^10.8.0",
|
||||
|
||||
@@ -17,14 +17,15 @@
|
||||
"scripts": {
|
||||
"ng": "ng",
|
||||
"watch": "ng build --watch --configuration development",
|
||||
"prebuild": "pnpm clean && pnpm copy:license && pnpm build:icons",
|
||||
"prebuild": "pnpm clean && pnpm copy:license && pnpm copy:utils && pnpm build:icons",
|
||||
"build": "pnpm prebuild && pnpm build:ng",
|
||||
"copy:license": "cp ../../LICENSE ./LICENSE",
|
||||
"copy:utils": "cpy ../../packages/shared/src/build/{buildLucideIconNode.ts,defaultAttributes.ts,types.ts} ../../packages/shared/src/utils/mergeClasses.ts ./src/utils/",
|
||||
"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 build:icons && ng test --no-watch",
|
||||
"test:watch": "ng test",
|
||||
"test": "pnpm copy:utils && pnpm build:icons && ng test --no-watch",
|
||||
"test:watch": "pnpm copy:utils && ng test",
|
||||
"lint": "eslint 'src/**/*.{js,jsx,ts,tsx,html,css,scss}' --quiet --fix",
|
||||
"e2e": "ng e2e"
|
||||
},
|
||||
|
||||
@@ -19,6 +19,11 @@ export interface LucideConfig {
|
||||
* @default 2
|
||||
*/
|
||||
strokeWidth: number;
|
||||
/**
|
||||
* Whether to use absolute stroke width.
|
||||
* @deprecated Use `nonScalingStroke` instead.
|
||||
*/
|
||||
absoluteStrokeWidth: boolean;
|
||||
/**
|
||||
* Whether stroke width should be scaled to appear uniform regardless of icon size.
|
||||
* @default false
|
||||
@@ -31,7 +36,7 @@ export interface LucideConfig {
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
absoluteStrokeWidth: boolean;
|
||||
nonScalingStroke: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -42,6 +47,7 @@ export const lucideDefaultConfig: LucideConfig = {
|
||||
size: 24,
|
||||
strokeWidth: 2,
|
||||
absoluteStrokeWidth: false,
|
||||
nonScalingStroke: false,
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -8,7 +8,7 @@ import { LucideBadgeAlert } from './icons/badge-alert';
|
||||
@Component({
|
||||
// eslint-disable-next-line @angular-eslint/component-selector
|
||||
selector: 'lucide-static-hydration-root',
|
||||
template: `<svg lucideBadgeAlert [absoluteStrokeWidth]="true"></svg>`,
|
||||
template: `<svg lucideBadgeAlert [nonScalingStroke]="true"></svg>`,
|
||||
imports: [LucideBadgeAlert],
|
||||
})
|
||||
class StaticHydrationRootComponent {}
|
||||
|
||||
@@ -47,6 +47,7 @@ describe('LucideIconBase', () => {
|
||||
let size: WritableSignal<string | number | undefined>;
|
||||
let strokeWidth: WritableSignal<string | number | undefined>;
|
||||
let absoluteStrokeWidth: WritableSignal<boolean | undefined>;
|
||||
let nonScalingStroke: WritableSignal<boolean | undefined>;
|
||||
const getSvgAttribute = (attr: string) => fixture.nativeElement.getAttribute(attr);
|
||||
const expectSvgClasses = (classes: string[], svg: SVGElement = fixture.nativeElement) => {
|
||||
for (const cssClass of classes) {
|
||||
@@ -63,6 +64,7 @@ describe('LucideIconBase', () => {
|
||||
inputBinding('size', size),
|
||||
inputBinding('strokeWidth', strokeWidth),
|
||||
inputBinding('absoluteStrokeWidth', absoluteStrokeWidth),
|
||||
inputBinding('nonScalingStroke', nonScalingStroke),
|
||||
],
|
||||
});
|
||||
}
|
||||
@@ -72,6 +74,7 @@ describe('LucideIconBase', () => {
|
||||
size = signal(undefined);
|
||||
strokeWidth = signal(undefined);
|
||||
absoluteStrokeWidth = signal(undefined);
|
||||
nonScalingStroke = signal(undefined);
|
||||
fixture = createComponent();
|
||||
component = fixture.componentInstance;
|
||||
});
|
||||
@@ -135,6 +138,11 @@ describe('LucideIconBase', () => {
|
||||
expect(getSvgAttribute('width')).toBe('18');
|
||||
expect(getSvgAttribute('height')).toBe('18');
|
||||
});
|
||||
it('should set viewBox', () => {
|
||||
size.set('18');
|
||||
fixture.detectChanges();
|
||||
expect(getSvgAttribute('viewBox')).toBe('0 0 24 24');
|
||||
});
|
||||
});
|
||||
|
||||
describe('strokeWidth', () => {
|
||||
@@ -155,22 +163,38 @@ describe('LucideIconBase', () => {
|
||||
});
|
||||
|
||||
describe('absoluteStrokeWidth', () => {
|
||||
it('should adjust stroke width', () => {
|
||||
strokeWidth.set(2);
|
||||
size.set(32);
|
||||
absoluteStrokeWidth.set(true);
|
||||
fixture.detectChanges();
|
||||
expect(getSvgAttribute('stroke-width')).toBe('1.5');
|
||||
});
|
||||
it('should not set vector-effect on children', () => {
|
||||
absoluteStrokeWidth.set(true);
|
||||
for (const child of fixture.nativeElement.children) {
|
||||
expect(child.getAttribute('vector-effect')).toBeNull();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
describe('nonScalingStroke', () => {
|
||||
it('should not adjust stroke width', () => {
|
||||
strokeWidth.set(2);
|
||||
size.set(12);
|
||||
absoluteStrokeWidth.set(true);
|
||||
nonScalingStroke.set(false);
|
||||
fixture.detectChanges();
|
||||
expect(getSvgAttribute('stroke-width')).toBe('2');
|
||||
});
|
||||
it('should not set vector-effect on children', () => {
|
||||
absoluteStrokeWidth.set(false);
|
||||
nonScalingStroke.set(false);
|
||||
fixture.detectChanges();
|
||||
for (const child of getRenderedChildren()) {
|
||||
expect(child.getAttribute('vector-effect')).toBeNull();
|
||||
}
|
||||
});
|
||||
it('should set vector-effect on children', () => {
|
||||
absoluteStrokeWidth.set(true);
|
||||
nonScalingStroke.set(true);
|
||||
fixture.detectChanges();
|
||||
for (const child of getRenderedChildren()) {
|
||||
expect(child.getAttribute('vector-effect')).toBe('non-scaling-stroke');
|
||||
@@ -207,6 +231,7 @@ describe('LucideIconBase', () => {
|
||||
color: 'red',
|
||||
strokeWidth: 1,
|
||||
size: 12,
|
||||
nonScalingStroke: true,
|
||||
absoluteStrokeWidth: true,
|
||||
}),
|
||||
],
|
||||
@@ -229,12 +254,12 @@ describe('LucideIconBase', () => {
|
||||
describe('strokeWidth', () => {
|
||||
it('should use stroke width from config', () => {
|
||||
fixture.detectChanges();
|
||||
expect(getSvgAttribute('stroke-width')).toBe('1');
|
||||
expect(getSvgAttribute('stroke-width')).toBe('2');
|
||||
});
|
||||
it('should use override stroke width from config', () => {
|
||||
strokeWidth.set(3);
|
||||
fixture.detectChanges();
|
||||
expect(getSvgAttribute('stroke-width')).toBe('3');
|
||||
expect(getSvgAttribute('stroke-width')).toBe('6');
|
||||
});
|
||||
});
|
||||
describe('size', () => {
|
||||
@@ -253,14 +278,23 @@ describe('LucideIconBase', () => {
|
||||
describe('absoluteStrokeWidth', () => {
|
||||
it('should use absoluteStrokeWidth from config', () => {
|
||||
fixture.detectChanges();
|
||||
for (const child of getRenderedChildren()) {
|
||||
expect(child.getAttribute('vector-effect')).toBe('non-scaling-stroke');
|
||||
}
|
||||
expect(getSvgAttribute('stroke-width')).toBe('2');
|
||||
});
|
||||
it('should override absoluteStrokeWidth', () => {
|
||||
absoluteStrokeWidth.set(false);
|
||||
fixture.detectChanges();
|
||||
for (const child of getRenderedChildren()) {
|
||||
expect(getSvgAttribute('stroke-width')).toBe('1');
|
||||
});
|
||||
});
|
||||
describe('nonScalingStroke', () => {
|
||||
it('should use nonScalingStroke from config', () => {
|
||||
for (const child of fixture.nativeElement.children) {
|
||||
expect(child.getAttribute('vector-effect')).toBe('non-scaling-stroke');
|
||||
}
|
||||
});
|
||||
it('should override nonScalingStroke', () => {
|
||||
nonScalingStroke.set(false);
|
||||
for (const child of fixture.nativeElement.children) {
|
||||
expect(child.getAttribute('vector-effect')).toBeNull();
|
||||
}
|
||||
});
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
import { Component, computed, inject, input, Signal } from '@angular/core';
|
||||
import { LUCIDE_CONFIG } from './lucide-config';
|
||||
import { LucideIconData, Nullable } from './types';
|
||||
import { LucideIconData, LucideIconNode, Nullable } from './types';
|
||||
import defaultAttributes from './default-attributes';
|
||||
import { lucideIconTemplate } from './lucide-icon-template';
|
||||
import buildLucideIconNode from './utils/buildLucideIconNode';
|
||||
|
||||
/**
|
||||
* @internal
|
||||
@@ -12,38 +13,17 @@ import { lucideIconTemplate } from './lucide-icon-template';
|
||||
template: lucideIconTemplate,
|
||||
host: {
|
||||
...defaultAttributes,
|
||||
class: 'lucide',
|
||||
'[class]': 'iconClasses()',
|
||||
'[attr.width]': 'size()',
|
||||
'[attr.height]': 'size()',
|
||||
'[attr.stroke]': 'color()',
|
||||
'[attr.stroke-width]': 'strokeWidth()',
|
||||
'[attr.aria-hidden]': '!title()',
|
||||
'[attr.class]': 'computedClass()',
|
||||
'[attr.width]': 'computedWidth()',
|
||||
'[attr.height]': 'computedHeight()',
|
||||
'[attr.viewBox]': 'computedViewbox()',
|
||||
'[attr.stroke]': 'computedStroke()',
|
||||
'[attr.stroke-width]': 'computedStrokeWidth()',
|
||||
'[attr.aria-hidden]': 'computedAriaHidden()',
|
||||
},
|
||||
})
|
||||
export abstract class LucideIconBase {
|
||||
protected abstract readonly icon: Signal<Nullable<LucideIconData>>;
|
||||
protected readonly iconNodes = computed<LucideIconData['node']>(() => {
|
||||
const node = this.icon()?.node ?? [];
|
||||
if (!this.absoluteStrokeWidth()) {
|
||||
return node;
|
||||
}
|
||||
return node.map<LucideIconData['node'][number]>(([name, attrs]) => [
|
||||
name,
|
||||
{
|
||||
'vector-effect': 'non-scaling-stroke',
|
||||
...attrs,
|
||||
},
|
||||
]);
|
||||
});
|
||||
protected readonly iconClasses = computed(() => {
|
||||
const icon = this.icon();
|
||||
if (!icon) {
|
||||
return '';
|
||||
}
|
||||
const { name, aliases = [] } = icon;
|
||||
return [name, ...aliases].map((item) => `lucide-${item}`).join(' ');
|
||||
});
|
||||
protected readonly iconConfig = inject(LUCIDE_CONFIG);
|
||||
/**
|
||||
* An optional accessible label for the icon.
|
||||
@@ -58,6 +38,10 @@ export abstract class LucideIconBase {
|
||||
* - If your icon is functional (e.g. used in place of a label), feel free to use this property.
|
||||
*/
|
||||
readonly title = input<Nullable<string>>();
|
||||
/**
|
||||
* Optional CSS classes for the icon.
|
||||
*/
|
||||
readonly class = input<Nullable<string>>();
|
||||
/**
|
||||
* Width and height.
|
||||
* @default 24
|
||||
@@ -65,6 +49,16 @@ export abstract class LucideIconBase {
|
||||
readonly size = input(this.iconConfig.size, {
|
||||
transform: (value: Nullable<string | number>) => value ?? this.iconConfig.size,
|
||||
});
|
||||
/**
|
||||
* Icon width.
|
||||
* @default 24
|
||||
*/
|
||||
readonly width = input(null);
|
||||
/**
|
||||
* Icon height.
|
||||
* @default 24
|
||||
*/
|
||||
readonly height = input(null);
|
||||
/**
|
||||
* Stroke color.
|
||||
* @default currentColor
|
||||
@@ -80,9 +74,95 @@ export abstract class LucideIconBase {
|
||||
transform: (value: Nullable<string | number>) => value ?? this.iconConfig.strokeWidth,
|
||||
});
|
||||
/**
|
||||
* If set to true, it adds [`vector-effect="non-scaling-stroke"`](https://developer.mozilla.org/en-US/docs/Web/SVG/Reference/Attribute/vector-effect) to child elements.
|
||||
* Whether to use absolute stroke width.
|
||||
*/
|
||||
readonly absoluteStrokeWidth = input(this.iconConfig.absoluteStrokeWidth, {
|
||||
transform: (value: Nullable<boolean>) => value ?? this.iconConfig.absoluteStrokeWidth,
|
||||
});
|
||||
/**
|
||||
* If set to true, it adds [`vector-effect="non-scaling-stroke"`](https://developer.mozilla.org/en-US/docs/Web/SVG/Reference/Attribute/vector-effect) to child elements.
|
||||
*/
|
||||
readonly nonScalingStroke = input(this.iconConfig.nonScalingStroke, {
|
||||
transform: (value: Nullable<boolean>) => value ?? this.iconConfig.nonScalingStroke,
|
||||
});
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
protected readonly computedIcon = computed(() => {
|
||||
const icon = this.icon();
|
||||
return icon
|
||||
? buildLucideIconNode(icon, {
|
||||
width: this.width() ?? this.size(),
|
||||
height: this.height() ?? this.size(),
|
||||
color: this.color(),
|
||||
strokeWidth: this.strokeWidth(),
|
||||
absoluteStrokeWidth: this.absoluteStrokeWidth(),
|
||||
nonScalingStroke: this.nonScalingStroke(),
|
||||
className: this.class() ?? undefined,
|
||||
hasA11yProp: this.title() != null,
|
||||
})
|
||||
: null;
|
||||
});
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
protected readonly computedAttributes = computed<LucideIconNode[1] | undefined>(
|
||||
() => this.computedIcon()?.[1],
|
||||
);
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
protected readonly computedIconNode = computed(() => this.computedIcon()?.[2] ?? []);
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
protected readonly computedWidth = computed(
|
||||
() => this.computedAttributes()?.['width'] ?? this.iconConfig.size,
|
||||
);
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
protected readonly computedHeight = computed(
|
||||
() => this.computedAttributes()?.['height'] ?? this.iconConfig.size,
|
||||
);
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
protected readonly computedStroke = computed(
|
||||
() => this.computedAttributes()?.['stroke'] ?? this.iconConfig.color,
|
||||
);
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
protected readonly computedStrokeWidth = computed(
|
||||
() => this.computedAttributes()?.['stroke-width'] ?? this.iconConfig.strokeWidth,
|
||||
);
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
protected readonly computedAriaHidden = computed(
|
||||
() => this.computedAttributes()?.['aria-hidden'] === 'true',
|
||||
);
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
protected readonly computedViewbox = computed(
|
||||
() => this.computedAttributes()?.['viewBox'] ?? '0 0 24 24',
|
||||
);
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
protected readonly computedClass = computed(
|
||||
() => this.computedAttributes()?.['class'] ?? 'lucide',
|
||||
);
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ export const lucideIconTemplate = `@if (title(); as titleValue) {
|
||||
<title>{{ titleValue }}</title>
|
||||
}
|
||||
<ng-content select="title"></ng-content>
|
||||
@for (child of iconNodes(); track child[1]['key'] ?? $index) {
|
||||
@for (child of computedIconNode(); track child[1]['key'] ?? $index) {
|
||||
@let attrs = child[1];
|
||||
@switch (child[0]) {
|
||||
@case ('path') {
|
||||
|
||||
@@ -1,18 +1,16 @@
|
||||
import { Signal, Type } from '@angular/core';
|
||||
import {
|
||||
LucideIconNode as SharedLucideIconNode,
|
||||
LucideIconData as SharedLucideIconData,
|
||||
} from './utils/types';
|
||||
|
||||
type HtmlAttributes = { [key: string]: string | number };
|
||||
export type LucideIconNode = readonly [string, HtmlAttributes];
|
||||
export type LucideIconNode = SharedLucideIconNode;
|
||||
export type LucideIcons = { [key: string]: LucideIconData };
|
||||
|
||||
/**
|
||||
* A Lucide icon object that fully describes an icon to be displayed.
|
||||
*/
|
||||
export type LucideIconData = {
|
||||
name: string;
|
||||
size?: number;
|
||||
node: LucideIconNode[];
|
||||
aliases?: string[];
|
||||
};
|
||||
export type LucideIconData = SharedLucideIconData & { name: string };
|
||||
|
||||
/**
|
||||
* Input signal map of Lucide icon components.
|
||||
@@ -22,7 +20,11 @@ interface LucideIconProps {
|
||||
size: Signal<Nullable<number | string>>;
|
||||
color: Signal<Nullable<string>>;
|
||||
strokeWidth: Signal<Nullable<number | string>>;
|
||||
/**
|
||||
* @deprecated Use `nonScalingStroke` instead.
|
||||
*/
|
||||
absoluteStrokeWidth: Signal<Nullable<boolean>>;
|
||||
nonScalingStroke: Signal<Nullable<boolean>>;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -43,7 +43,7 @@
|
||||
"build:icons": "build-icons --output=./src --templateSrc=./scripts/exportTemplate.mts --renderUniqueKey --withAliases --aliasesFileExtension=.ts --iconFileExtension=.ts --exportFileName=index.ts --pretty=false",
|
||||
"clean": "rm -rf dist && rm -rf stats && rm -rf ./src/icons/*.ts",
|
||||
"copy:license": "cp ../../LICENSE ./LICENSE",
|
||||
"copy:utils": "mkdir -p ./src/utils && for f in hasA11yProp toKebabCase mergeClasses; do cp -f ../../packages/shared/src/utils/$f.ts ./src/utils/; done",
|
||||
"copy:utils": "cpy ../../packages/shared/src/build/{buildLucideIconNode.ts,defaultAttributes.ts,types.ts} ../../packages/shared/src/utils/{hasA11yProp.ts,toKebabCase.ts,mergeClasses.ts} ./src/utils/",
|
||||
"test": "pnpm copy:utils && pnpm build:icons && vitest run",
|
||||
"test:watch": "pnpm build:icons && vitest run --watch"
|
||||
},
|
||||
|
||||
@@ -1,28 +1,27 @@
|
||||
import base64SVG from '@lucide/build-icons/utils/base64SVG';
|
||||
import defineExportTemplate from '@lucide/build-icons/utils/defineExportTemplate';
|
||||
|
||||
export default defineExportTemplate(async ({
|
||||
componentName,
|
||||
iconName,
|
||||
children,
|
||||
getSvg,
|
||||
deprecated,
|
||||
deprecationReason,
|
||||
}) => {
|
||||
const svgContents = await getSvg();
|
||||
const svgBase64 = base64SVG(svgContents);
|
||||
export default defineExportTemplate(
|
||||
async ({ componentName, iconName, iconData, getSvg, deprecated, deprecationReason }) => {
|
||||
const svgContents = await getSvg();
|
||||
const svgBase64 = base64SVG(svgContents);
|
||||
|
||||
// Astro doesn't need keyed children in loops
|
||||
const keylessChildren = children.map((c) => {
|
||||
const [element, { key, ...otherAttrs }] = c;
|
||||
return [element, otherAttrs];
|
||||
});
|
||||
// Astro doesn't need keyed children in loops
|
||||
const keylessIconData = {
|
||||
...iconData,
|
||||
node: iconData.node.map((child) => {
|
||||
const [element, { key, ...otherAttrs }] = child;
|
||||
return [element, otherAttrs];
|
||||
}),
|
||||
};
|
||||
|
||||
// TODO: build-icons' `pretty` is set to false as the prettier
|
||||
// formatter uses babel which I'm not sure it supports typescript
|
||||
return `
|
||||
// TODO: build-icons' `pretty` is set to false as the prettier
|
||||
// formatter uses babel which I'm not sure it supports typescript
|
||||
return `
|
||||
import createLucideIcon from '../createLucideIcon';
|
||||
import type { AstroComponent } from '../types'
|
||||
import type { AstroComponent, LucideIconData } from '../types'
|
||||
|
||||
const iconData: LucideIconData = ${JSON.stringify(keylessIconData)};
|
||||
|
||||
/**
|
||||
* @component @name ${componentName}
|
||||
@@ -35,8 +34,9 @@ import type { AstroComponent } from '../types'
|
||||
* @returns {any} Astro Component
|
||||
* ${deprecated ? `@deprecated ${deprecationReason}` : ''}
|
||||
*/
|
||||
const ${componentName} = createLucideIcon('${iconName}', ${JSON.stringify(keylessChildren)}) as AstroComponent;
|
||||
const ${componentName} = createLucideIcon(iconData) as AstroComponent;
|
||||
|
||||
export default ${componentName};
|
||||
`;
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
@@ -1,32 +1,44 @@
|
||||
---
|
||||
import defaultAttributes from './defaultAttributes';
|
||||
import buildLucideIconNode from './utils/buildLucideIconNode';
|
||||
import type { IconProps as Props } from './types';
|
||||
import { hasA11yProp } from './utils/hasA11yProp';
|
||||
|
||||
|
||||
const {
|
||||
color = 'currentColor',
|
||||
size = 24,
|
||||
width,
|
||||
height,
|
||||
'stroke-width': strokeWidth = 2,
|
||||
absoluteStrokeWidth = false,
|
||||
iconNode = [],
|
||||
nonScalingStroke = false,
|
||||
iconNode,
|
||||
icon = {
|
||||
node: iconNode,
|
||||
aliases: [],
|
||||
size: 24,
|
||||
},
|
||||
class: className,
|
||||
...rest
|
||||
} = Astro.props;
|
||||
|
||||
const [, builtIconAttributes, builtIconNode = []] = buildLucideIconNode(icon, {
|
||||
color,
|
||||
width: width ?? size,
|
||||
height: height ?? size,
|
||||
strokeWidth,
|
||||
absoluteStrokeWidth,
|
||||
nonScalingStroke,
|
||||
className,
|
||||
hasA11yProp: hasA11yProp(rest),
|
||||
});
|
||||
|
||||
const iconAttributes = {
|
||||
...builtIconAttributes,
|
||||
...rest,
|
||||
};
|
||||
---
|
||||
|
||||
<svg
|
||||
{...{
|
||||
...defaultAttributes,
|
||||
width: size,
|
||||
height: size,
|
||||
stroke: color,
|
||||
'stroke-width': absoluteStrokeWidth ? (Number(strokeWidth) * 24) / Number(size) : strokeWidth,
|
||||
...(!hasA11yProp(rest) && { 'aria-hidden': 'true' }),
|
||||
...rest,
|
||||
}}
|
||||
class:list={['lucide', className]}
|
||||
>
|
||||
{iconNode.map(([Tag, attrs]) => <Tag {...attrs} />)}
|
||||
<svg {...iconAttributes}>
|
||||
{builtIconNode.map(([Tag, attrs]) => <Tag {...attrs} />)}
|
||||
<slot />
|
||||
</svg>
|
||||
|
||||
@@ -1,11 +1,43 @@
|
||||
import type { AstroComponentFactory } from 'astro/runtime/server/render/astro/factory.js';
|
||||
import type { IconNode } from './types';
|
||||
import type { LucideIconData, LucideIconNode } from './types';
|
||||
import { render, renderSlot, createComponent, renderComponent } from 'astro/compiler-runtime';
|
||||
import Icon from './Icon.astro';
|
||||
import { mergeClasses } from './utils/mergeClasses';
|
||||
import { toKebabCase } from './utils/toKebabCase';
|
||||
|
||||
export default (iconName: string, iconNode: IconNode): AstroComponentFactory => {
|
||||
/**
|
||||
* Creates a Lucide icon component from icon data.
|
||||
*
|
||||
* @param icon Icon data object.
|
||||
* @returns Lucide icon component.
|
||||
*/
|
||||
function createLucideIcon(icon: LucideIconData): AstroComponentFactory;
|
||||
|
||||
/**
|
||||
* Creates a Lucide icon component from the legacy icon arguments.
|
||||
*
|
||||
* @param iconName Icon name.
|
||||
* @param iconNode Icon node.
|
||||
* @param aliases Optional icon aliases.
|
||||
* @returns Lucide icon component.
|
||||
*/
|
||||
function createLucideIcon(
|
||||
iconName: string,
|
||||
iconNode: LucideIconNode[],
|
||||
aliases?: string[],
|
||||
): AstroComponentFactory;
|
||||
|
||||
function createLucideIcon(
|
||||
iconOrIconName: string | LucideIconData,
|
||||
iconNode: LucideIconNode[] = [],
|
||||
aliases: string[] = [],
|
||||
): AstroComponentFactory {
|
||||
const icon =
|
||||
typeof iconOrIconName === 'string'
|
||||
? {
|
||||
name: iconOrIconName,
|
||||
node: iconNode,
|
||||
aliases,
|
||||
}
|
||||
: iconOrIconName;
|
||||
const Component = createComponent(
|
||||
($$result, $$props: Record<string, unknown>, $$slots) => {
|
||||
const { class: className, ...restProps } = $$props;
|
||||
@@ -14,11 +46,8 @@ export default (iconName: string, iconNode: IconNode): AstroComponentFactory =>
|
||||
'Icon',
|
||||
Icon,
|
||||
{
|
||||
class: mergeClasses(
|
||||
Boolean(iconName) && `lucide-${toKebabCase(iconName)}`,
|
||||
Boolean(className) && className,
|
||||
),
|
||||
iconNode,
|
||||
class: className,
|
||||
icon,
|
||||
...restProps,
|
||||
},
|
||||
{ default: () => render`${renderSlot($$result, $$slots['default'])}` },
|
||||
@@ -28,4 +57,6 @@ export default (iconName: string, iconNode: IconNode): AstroComponentFactory =>
|
||||
'none',
|
||||
);
|
||||
return Component;
|
||||
};
|
||||
}
|
||||
|
||||
export default createLucideIcon;
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
import type { SVGAttributes } from './types';
|
||||
|
||||
const defaultAttributes: SVGAttributes = {
|
||||
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',
|
||||
};
|
||||
|
||||
export default defaultAttributes;
|
||||
@@ -3,6 +3,6 @@ export * as icons from './icons/index';
|
||||
export * from './aliases';
|
||||
export * from './types';
|
||||
|
||||
export { default as defaultAttributes } from './defaultAttributes';
|
||||
export { default as defaultAttributes } from './utils/defaultAttributes';
|
||||
export { default as createLucideIcon } from './createLucideIcon';
|
||||
export { default as Icon } from './Icon.astro';
|
||||
|
||||
@@ -1,23 +1,47 @@
|
||||
import type { HTMLAttributes } from 'astro/types';
|
||||
import type {
|
||||
LucideIconData as SharedLucideIconData,
|
||||
LucideIconNode as SharedLucideIconNode,
|
||||
} from './utils/types';
|
||||
|
||||
// Type that the Astro language server needs to infer component props in Astro files
|
||||
export type AstroComponent = (_props: IconProps) => unknown;
|
||||
export type AstroComponent = (_props: LucideProps) => unknown;
|
||||
|
||||
export interface IconProps extends SVGAttributes {
|
||||
export type LucideProps = SVGAttributes & {
|
||||
color?: string;
|
||||
size?: number | string;
|
||||
'stroke-width'?: number | string;
|
||||
/**
|
||||
* @deprecated Use `nonScalingStroke` instead.
|
||||
*/
|
||||
absoluteStrokeWidth?: boolean;
|
||||
nonScalingStroke?: boolean;
|
||||
class?: string;
|
||||
iconNode?: IconNode;
|
||||
title?: string;
|
||||
}
|
||||
};
|
||||
|
||||
export type IconProps = LucideProps &
|
||||
(
|
||||
| {
|
||||
icon: LucideIconData;
|
||||
iconNode?: never;
|
||||
}
|
||||
| {
|
||||
icon?: never;
|
||||
iconNode: LucideIconNode[];
|
||||
}
|
||||
);
|
||||
|
||||
export type SVGAttributes = HTMLAttributes<'svg'>;
|
||||
|
||||
export type IconNode = IconNodeChild[];
|
||||
export type LucideIconNode = SharedLucideIconNode<SVGElements, SVGAttributes>;
|
||||
|
||||
type IconNodeChild = [elementName: SVGElements, attrs: SVGAttributes];
|
||||
export type LucideIconData = SharedLucideIconData<SVGElements, SVGAttributes>;
|
||||
|
||||
/**
|
||||
* @deprecated Use LucideIconNode instead.
|
||||
*/
|
||||
export type IconNode = LucideIconNode[];
|
||||
|
||||
// All possible svg elements according to the Astro definitions
|
||||
type SVGElements =
|
||||
|
||||
@@ -10,8 +10,8 @@ exports[`Using Icon Component > should render icon and match snapshot 1`] = `
|
||||
stroke-width="1"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
aria-hidden="true"
|
||||
class="lucide"
|
||||
aria-hidden="true"
|
||||
>
|
||||
<path d="M6 12H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h16a2 2 0 0 1 2 2v5a2 2 0 0 1-2 2h-2">
|
||||
</path>
|
||||
|
||||
@@ -10,8 +10,8 @@ exports[`Using createLucideIcon > should create a component from an iconNode 1`]
|
||||
stroke-width="2"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
aria-hidden="true"
|
||||
class="lucide lucide-air-vent"
|
||||
aria-hidden="true"
|
||||
>
|
||||
<path d="M6 12H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h16a2 2 0 0 1 2 2v5a2 2 0 0 1-2 2h-2">
|
||||
</path>
|
||||
|
||||
@@ -10,9 +10,9 @@ exports[`Using lucide icon components > should add a non-default attribute to th
|
||||
stroke-width="2"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
class="lucide lucide-face-slightly-smiling lucide-smile"
|
||||
aria-hidden="true"
|
||||
style="position: absolute"
|
||||
class="lucide lucide-face-slightly-smiling"
|
||||
>
|
||||
<path d="M15 10V9">
|
||||
</path>
|
||||
@@ -38,8 +38,8 @@ exports[`Using lucide icon components > should adjust the size, stroke color and
|
||||
stroke-width="4"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
class="lucide lucide-grid-3x3 lucide-grid lucide-grid-3-x-3"
|
||||
aria-hidden="true"
|
||||
class="lucide lucide-grid-3x3"
|
||||
>
|
||||
<rect width="18"
|
||||
height="18"
|
||||
@@ -69,41 +69,50 @@ exports[`Using lucide icon components > should apply all classes to the element
|
||||
stroke-width="2"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
class="lucide lucide-droplet lucide-drop my-icon"
|
||||
aria-hidden="true"
|
||||
class="lucide lucide-droplet my-icon"
|
||||
>
|
||||
<path d="M12 22a7 7 0 0 0 7-7c0-2-1-3.9-3-5.5s-3.5-4-4-6.5c-.5 2.5-2 4.9-4 6.5C6 11.1 5 13 5 15a7 7 0 0 0 7 7z">
|
||||
</path>
|
||||
</svg>
|
||||
`;
|
||||
|
||||
exports[`Using lucide icon components > should not scale the strokeWidth when absoluteStrokeWidth is set 1`] = `
|
||||
exports[`Using lucide icon components > should apply vector-effect when nonScalingStroke is set 1`] = `
|
||||
<svg xmlns="http://www.w3.org/2000/svg"
|
||||
width="48"
|
||||
height="48"
|
||||
width="12"
|
||||
height="12"
|
||||
viewbox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="red"
|
||||
stroke-width="1"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
class="lucide lucide-grid-3x3 lucide-grid lucide-grid-3-x-3"
|
||||
aria-hidden="true"
|
||||
class="lucide lucide-grid-3x3"
|
||||
>
|
||||
<rect width="18"
|
||||
<rect vector-effect="non-scaling-stroke"
|
||||
width="18"
|
||||
height="18"
|
||||
x="3"
|
||||
y="3"
|
||||
rx="2"
|
||||
>
|
||||
</rect>
|
||||
<path d="M3 9h18">
|
||||
<path vector-effect="non-scaling-stroke"
|
||||
d="M3 9h18"
|
||||
>
|
||||
</path>
|
||||
<path d="M3 15h18">
|
||||
<path vector-effect="non-scaling-stroke"
|
||||
d="M3 15h18"
|
||||
>
|
||||
</path>
|
||||
<path d="M9 3v18">
|
||||
<path vector-effect="non-scaling-stroke"
|
||||
d="M9 3v18"
|
||||
>
|
||||
</path>
|
||||
<path d="M15 3v18">
|
||||
<path vector-effect="non-scaling-stroke"
|
||||
d="M15 3v18"
|
||||
>
|
||||
</path>
|
||||
</svg>
|
||||
`;
|
||||
@@ -118,8 +127,8 @@ exports[`Using lucide icon components > should pass children to the icon slot 1`
|
||||
stroke-width="2"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
class="lucide lucide-face-slightly-smiling lucide-smile"
|
||||
aria-hidden="true"
|
||||
class="lucide lucide-face-slightly-smiling"
|
||||
>
|
||||
<path d="M15 10V9">
|
||||
</path>
|
||||
@@ -148,8 +157,8 @@ exports[`Using lucide icon components > should render a component 1`] = `
|
||||
stroke-width="2"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
class="lucide lucide-grid-3x3 lucide-grid lucide-grid-3-x-3"
|
||||
aria-hidden="true"
|
||||
class="lucide lucide-grid-3x3"
|
||||
>
|
||||
<rect width="18"
|
||||
height="18"
|
||||
@@ -179,8 +188,39 @@ exports[`Using lucide icon components > should render the icon with default attr
|
||||
stroke-width="2"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
class="lucide lucide-grid-3x3 lucide-grid lucide-grid-3-x-3"
|
||||
aria-hidden="true"
|
||||
>
|
||||
<rect width="18"
|
||||
height="18"
|
||||
x="3"
|
||||
y="3"
|
||||
rx="2"
|
||||
>
|
||||
</rect>
|
||||
<path d="M3 9h18">
|
||||
</path>
|
||||
<path d="M3 15h18">
|
||||
</path>
|
||||
<path d="M9 3v18">
|
||||
</path>
|
||||
<path d="M15 3v18">
|
||||
</path>
|
||||
</svg>
|
||||
`;
|
||||
|
||||
exports[`Using lucide icon components > should scale the strokeWidth when absoluteStrokeWidth is set 1`] = `
|
||||
<svg xmlns="http://www.w3.org/2000/svg"
|
||||
width="48"
|
||||
height="48"
|
||||
viewbox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="red"
|
||||
stroke-width="1"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
class="lucide lucide-grid-3x3 lucide-grid lucide-grid-3-x-3"
|
||||
aria-hidden="true"
|
||||
class="lucide lucide-grid-3x3"
|
||||
>
|
||||
<rect width="18"
|
||||
height="18"
|
||||
|
||||
@@ -5,7 +5,10 @@ import { render } from './utils';
|
||||
|
||||
describe('Using createLucideIcon', () => {
|
||||
it('should create a component from an iconNode', async () => {
|
||||
const AirVent = createLucideIcon('AirVent', airVent);
|
||||
const AirVent = createLucideIcon({
|
||||
name: 'air-vent',
|
||||
node: airVent,
|
||||
});
|
||||
const { container } = await render(AirVent);
|
||||
|
||||
expect(container.innerHTML).toBeDefined();
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import { describe, it, expect } from 'vitest';
|
||||
import { Pen, Edit2, Grid, Droplet, Smile, Rocket } from '../src/lucide-astro';
|
||||
import defaultAttributes from '../src/defaultAttributes';
|
||||
import { Pen, Edit2, Grid, Droplet, Smile, Rocket, type LucideIconData } from '../src/lucide-astro';
|
||||
import defaultAttributes from '../src/utils/defaultAttributes';
|
||||
import { createAstroHTMLString, render } from './utils';
|
||||
import createLucideIcon from '../src/createLucideIcon.ts';
|
||||
|
||||
describe('Using lucide icon components', () => {
|
||||
it('should render a component', async () => {
|
||||
@@ -64,11 +65,11 @@ describe('Using lucide icon components', () => {
|
||||
expect(PenIconContainer.innerHTML).toBe(Edit2Container.innerHTML);
|
||||
});
|
||||
|
||||
it('should not scale the strokeWidth when absoluteStrokeWidth is set', async () => {
|
||||
it('should scale the strokeWidth when absoluteStrokeWidth is set', async () => {
|
||||
const { container } = await render(Grid, {
|
||||
props: {
|
||||
size: 48,
|
||||
stroke: 'red',
|
||||
color: 'red',
|
||||
absoluteStrokeWidth: true,
|
||||
},
|
||||
});
|
||||
@@ -83,6 +84,24 @@ describe('Using lucide icon components', () => {
|
||||
expect(container.innerHTML).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should apply vector-effect when nonScalingStroke is set', async () => {
|
||||
const { container } = await render(Grid, {
|
||||
props: {
|
||||
size: 12,
|
||||
nonScalingStroke: true,
|
||||
},
|
||||
});
|
||||
|
||||
const SVGElement = container.firstElementChild;
|
||||
|
||||
expect(SVGElement).toHaveAttribute('width', '12');
|
||||
expect(SVGElement).toHaveAttribute('height', '12');
|
||||
expect(SVGElement).toHaveAttribute('stroke-width', '2');
|
||||
expect(SVGElement?.firstElementChild).toHaveAttribute('vector-effect', 'non-scaling-stroke');
|
||||
|
||||
expect(container.innerHTML).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should add a non-default attribute to the element', async () => {
|
||||
const { container } = await render(Smile, {
|
||||
props: {
|
||||
@@ -112,7 +131,20 @@ describe('Using lucide icon components', () => {
|
||||
});
|
||||
|
||||
it('should apply all classes to the element', async () => {
|
||||
const { container } = await render(Droplet, {
|
||||
const iconData: LucideIconData = {
|
||||
name: 'droplet',
|
||||
size: 24,
|
||||
node: [
|
||||
[
|
||||
'path',
|
||||
{
|
||||
d: 'M12 22a7 7 0 0 0 7-7c0-2-1-3.9-3-5.5s-3.5-4-4-6.5c-.5 2.5-2 4.9-4 6.5C6 11.1 5 13 5 15a7 7 0 0 0 7 7z',
|
||||
},
|
||||
],
|
||||
],
|
||||
aliases: ['drop'],
|
||||
};
|
||||
const { container } = await render(createLucideIcon(iconData), {
|
||||
props: {
|
||||
class: 'my-icon',
|
||||
},
|
||||
@@ -122,6 +154,7 @@ describe('Using lucide icon components', () => {
|
||||
expect(SVGElement).toHaveClass('my-icon');
|
||||
expect(SVGElement).toHaveClass('lucide');
|
||||
expect(SVGElement).toHaveClass('lucide-droplet');
|
||||
expect(SVGElement).toHaveClass('lucide-drop');
|
||||
|
||||
expect(container.innerHTML).toMatchSnapshot();
|
||||
});
|
||||
|
||||
@@ -63,6 +63,7 @@
|
||||
"@lucide/build-icons": "workspace:*",
|
||||
"@lucide/helpers": "^1.0.0",
|
||||
"@lucide/rollup-plugins": "workspace:*",
|
||||
"@lucide/shared": "workspace:*",
|
||||
"@rollup/plugin-replace": "^6.0.3",
|
||||
"@testing-library/jest-dom": "^6.9.1",
|
||||
"jest-serializer-html": "^7.1.0",
|
||||
|
||||
@@ -2,6 +2,11 @@ import plugins from '@lucide/rollup-plugins';
|
||||
import pkg from './package.json' with { type: 'json' };
|
||||
import dts from 'rollup-plugin-dts';
|
||||
|
||||
const dtsOptions = {
|
||||
includeExternal: ['@lucide/shared/types'],
|
||||
tsconfig: './tsconfig.json',
|
||||
};
|
||||
|
||||
const packageName = '@lucide/icons';
|
||||
const outputFileName = 'lucide-icons';
|
||||
const inputs = [`src/lucide-icons.ts`];
|
||||
@@ -81,7 +86,7 @@ export default [
|
||||
format: 'cjs',
|
||||
},
|
||||
],
|
||||
plugins: [dts()],
|
||||
plugins: [dts(dtsOptions)],
|
||||
})),
|
||||
...configs,
|
||||
];
|
||||
|
||||
@@ -1,30 +1 @@
|
||||
import { LucideBuildParams, LucideIconData } from './types';
|
||||
import buildLucideSvg from './buildLucideSvg';
|
||||
|
||||
/**
|
||||
* Creates a base64 encoded data URI from a Lucide icon object.
|
||||
*
|
||||
* @param icon The icon to build.
|
||||
* @param params Additional build parameters.
|
||||
*/
|
||||
function buildLucideDataUri(icon: LucideIconData, params: LucideBuildParams = {}) {
|
||||
const svg = buildLucideSvg(icon, params);
|
||||
|
||||
// Browser
|
||||
if (typeof btoa === 'function') {
|
||||
// Ensure proper UTF-8 handling before base64
|
||||
const utf8Bytes = new TextEncoder().encode(svg);
|
||||
let binary = '';
|
||||
for (const element of utf8Bytes) binary += String.fromCodePoint(element);
|
||||
return `data:image/svg+xml;base64,${btoa(binary)}`;
|
||||
}
|
||||
|
||||
// Node.js (and other JS runtimes with Buffer)
|
||||
if (typeof Buffer !== 'undefined') {
|
||||
return `data:image/svg+xml;base64,${Buffer.from(svg, 'utf8').toString('base64')}`;
|
||||
}
|
||||
|
||||
throw new Error('No base64 encoder available in this environment.');
|
||||
}
|
||||
|
||||
export default buildLucideDataUri;
|
||||
export { buildLucideDataUri as default } from '@lucide/shared';
|
||||
|
||||
@@ -1,34 +1 @@
|
||||
import { LucideBuildParams, LucideIconData, LucideIconNode } from './types';
|
||||
import buildLucideIconNode from './buildLucideIconNode';
|
||||
|
||||
const buildDomElement = (
|
||||
document: Document,
|
||||
[tagName, attributes, children = []]: LucideIconNode,
|
||||
): Element => {
|
||||
const element = document.createElementNS('http://www.w3.org/2000/svg', tagName);
|
||||
for (const [attrName, value] of Object.entries(attributes)) {
|
||||
element.setAttribute(attrName, value);
|
||||
}
|
||||
for (const node of children) {
|
||||
const childNode = buildDomElement(document, node);
|
||||
element.appendChild(childNode);
|
||||
}
|
||||
return element;
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates an SvgElement from a Lucide icon object.
|
||||
*
|
||||
* @param document The document to create the Element in.
|
||||
* @param icon The icon to build.
|
||||
* @param params Additional build parameters.
|
||||
*/
|
||||
function buildLucideIconElement(
|
||||
document: Document,
|
||||
icon: LucideIconData,
|
||||
params: LucideBuildParams = {},
|
||||
) {
|
||||
return buildDomElement(document, buildLucideIconNode(icon, params));
|
||||
}
|
||||
|
||||
export default buildLucideIconElement;
|
||||
export { buildLucideIconElement as default } from '@lucide/shared';
|
||||
|
||||
@@ -1,55 +1 @@
|
||||
import { LucideBuildParams, LucideIconData, LucideIconNode } from './types';
|
||||
|
||||
const defaultAttributes = {
|
||||
xmlns: 'http://www.w3.org/2000/svg',
|
||||
width: '24',
|
||||
height: '24',
|
||||
viewBox: '0 0 24 24',
|
||||
fill: 'none',
|
||||
stroke: 'currentColor',
|
||||
'stroke-width': '2',
|
||||
'stroke-linecap': 'round',
|
||||
'stroke-linejoin': 'round',
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates a Lucide icon node (an svgson-like format) from a Lucide icon object.
|
||||
*
|
||||
* @param icon The icon to build.
|
||||
* @param params Additional build parameters.
|
||||
*/
|
||||
function buildLucideIconNode(icon: LucideIconData, params: LucideBuildParams = {}): LucideIconNode {
|
||||
const viewBoxWidth = ('size' in icon ? icon.size : icon.width) ?? defaultAttributes.width;
|
||||
const viewBoxHeight = ('size' in icon ? icon.size : icon.height) ?? defaultAttributes.height;
|
||||
const aliasClassNames = icon.aliases?.map((alias) => `lucide-${alias}`) ?? [];
|
||||
const classList = ['lucide', `lucide-${icon.name}`, ...aliasClassNames];
|
||||
if (params['className']) {
|
||||
classList.push(params['className']);
|
||||
}
|
||||
const attributes = {
|
||||
...defaultAttributes,
|
||||
...('color' in params && { stroke: params['color'] }),
|
||||
...('size' in params &&
|
||||
params['size'] && {
|
||||
width: params['size'].toString(10),
|
||||
height: params['size'].toString(10),
|
||||
}),
|
||||
...('width' in params && params['width'] && { width: params['width'].toString(10) }),
|
||||
...('height' in params && params['height'] && { height: params['height'].toString(10) }),
|
||||
...('strokeWidth' in params &&
|
||||
params['strokeWidth'] && { 'stroke-width': params['strokeWidth'].toString(10) }),
|
||||
class: classList.join(' '),
|
||||
viewBox: `0 0 ${viewBoxWidth} ${viewBoxHeight}`,
|
||||
...('attributes' in params && params.attributes),
|
||||
};
|
||||
return [
|
||||
'svg',
|
||||
attributes,
|
||||
icon.node.map(([name, attrs]) => [
|
||||
name,
|
||||
params['absoluteStrokeWidth'] ? { 'vector-effect': 'non-scaling-stroke', ...attrs } : attrs,
|
||||
]),
|
||||
];
|
||||
}
|
||||
|
||||
export default buildLucideIconNode;
|
||||
export { buildLucideIconNode as default } from '@lucide/shared';
|
||||
|
||||
@@ -1,19 +1 @@
|
||||
import { LucideBuildParams, LucideIconData, LucideIconNode } from './types';
|
||||
import buildLucideIconNode from './buildLucideIconNode';
|
||||
|
||||
const buildDomNode = ([tagName, attributes, children = []]: LucideIconNode): string =>
|
||||
`<${tagName} ${Object.entries(attributes)
|
||||
.map(([attrName, value]) => `${attrName}="${value}"`)
|
||||
.join(' ')}>${children?.map((child) => buildDomNode(child)).join('')}</${tagName}>`;
|
||||
|
||||
/**
|
||||
* Creates an SVG string from a Lucide icon object.
|
||||
*
|
||||
* @param icon The icon to build.
|
||||
* @param params Additional build parameters.
|
||||
*/
|
||||
function buildLucideSvg(icon: LucideIconData, params: LucideBuildParams = {}) {
|
||||
return buildDomNode(buildLucideIconNode(icon, params));
|
||||
}
|
||||
|
||||
export default buildLucideSvg;
|
||||
export { buildLucideSvg as default } from '@lucide/shared';
|
||||
|
||||
+10
-43
@@ -1,43 +1,10 @@
|
||||
export type SVGProps = Record<string, string>;
|
||||
|
||||
/**
|
||||
* A Lucide icon node (an svgson-like internal format)
|
||||
*/
|
||||
export type LucideIconNode =
|
||||
| [attrName: string, attributes: SVGProps]
|
||||
| [attrName: string, attributes: SVGProps, children: LucideIconNode[]];
|
||||
|
||||
/**
|
||||
* A Lucide icon object that fully describes an icon to be displayed.
|
||||
*/
|
||||
export type LucideIconData = {
|
||||
name: string;
|
||||
node: LucideIconNode[];
|
||||
aliases?: string[];
|
||||
} & ({ size: number } | { width: number; height: number });
|
||||
|
||||
/**
|
||||
* Build parameters for creating a Lucide icon instance for display.
|
||||
*/
|
||||
export type LucideBuildParams = {
|
||||
/**
|
||||
* The color of the icon.
|
||||
*/
|
||||
color?: string;
|
||||
/**
|
||||
* The stroke width.
|
||||
*/
|
||||
strokeWidth?: number;
|
||||
/**
|
||||
* Adds [`vector-effect="non-scaling-stroke"`](https://developer.mozilla.org/en-US/docs/Web/SVG/Reference/Attribute/vector-effect) to child elements.
|
||||
*/
|
||||
absoluteStrokeWidth?: boolean;
|
||||
/**
|
||||
* Extra CSS class names to pass to the SVG element.
|
||||
*/
|
||||
className?: string;
|
||||
/**
|
||||
* Any extra attributes to pass to the SVG element.
|
||||
*/
|
||||
attributes?: SVGProps;
|
||||
} & ({ size?: number } | { width?: number; height?: number });
|
||||
import type {
|
||||
LucideBuildParams as SharedLucideBuildParams,
|
||||
LucideIconData as SharedLucideIconData,
|
||||
LucideIconNode as SharedLucideIconNode,
|
||||
SVGProps as SharedSvgProps,
|
||||
} from '@lucide/shared/types';
|
||||
export type LucideBuildParams = SharedLucideBuildParams;
|
||||
export type LucideIconData = SharedLucideIconData;
|
||||
export type LucideIconNode = SharedLucideIconNode;
|
||||
export type SVGProps = SharedSvgProps;
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
|
||||
|
||||
exports[`buildLucideIconNode > should match the snapshot 1`] = `"{"xmlns":"http://www.w3.org/2000/svg","width":"24","height":"24","viewBox":"0 0 24 24","fill":"none","stroke":"currentColor","stroke-width":"2","stroke-linecap":"round","stroke-linejoin":"round","class":"lucide lucide-house lucide-home"}"`;
|
||||
exports[`buildLucideIconNode > should match the snapshot 1`] = `"{"xmlns":"http://www.w3.org/2000/svg","width":24,"height":24,"viewBox":"0 0 24 24","fill":"none","stroke":"currentColor","stroke-width":2,"stroke-linecap":"round","stroke-linejoin":"round","class":"lucide lucide-house lucide-home"}"`;
|
||||
|
||||
@@ -18,24 +18,24 @@ describe('buildLucideIconNode', () => {
|
||||
it('should override dimensions, but not viewBox', () => {
|
||||
const HouseSVG = buildLucideIconNode(House, { size: 12 });
|
||||
|
||||
expect(HouseSVG[1]['width']).toBe('12');
|
||||
expect(HouseSVG[1]['height']).toBe('12');
|
||||
expect(HouseSVG[1]['width']).toBe(12);
|
||||
expect(HouseSVG[1]['height']).toBe(12);
|
||||
expect(HouseSVG[1]['viewBox']).toBe('0 0 24 24');
|
||||
});
|
||||
|
||||
it('should override width, but not height', () => {
|
||||
const HouseSVG = buildLucideIconNode(House, { width: 12 });
|
||||
|
||||
expect(HouseSVG[1]['width']).toBe('12');
|
||||
expect(HouseSVG[1]['height']).toBe('24');
|
||||
expect(HouseSVG[1]['width']).toBe(12);
|
||||
expect(HouseSVG[1]['height']).toBe(24);
|
||||
expect(HouseSVG[1]['viewBox']).toBe('0 0 24 24');
|
||||
});
|
||||
|
||||
it('should override height, but not width', () => {
|
||||
const HouseSVG = buildLucideIconNode(House, { height: 12 });
|
||||
|
||||
expect(HouseSVG[1]['width']).toBe('24');
|
||||
expect(HouseSVG[1]['height']).toBe('12');
|
||||
expect(HouseSVG[1]['width']).toBe(24);
|
||||
expect(HouseSVG[1]['height']).toBe(12);
|
||||
expect(HouseSVG[1]['viewBox']).toBe('0 0 24 24');
|
||||
});
|
||||
|
||||
@@ -49,11 +49,31 @@ describe('buildLucideIconNode', () => {
|
||||
it('should override stroke width', () => {
|
||||
const HouseSVG = buildLucideIconNode(House, { strokeWidth: 12 });
|
||||
|
||||
expect(HouseSVG[1]['stroke-width']).toBe('12');
|
||||
expect(HouseSVG[1]['stroke-width']).toBe(12);
|
||||
});
|
||||
|
||||
it('should scale the stroke width', () => {
|
||||
const HouseSVG = buildLucideIconNode(House, {
|
||||
size: 12,
|
||||
strokeWidth: 2,
|
||||
absoluteStrokeWidth: true,
|
||||
});
|
||||
|
||||
expect(HouseSVG[1]['stroke-width']).toBe(4);
|
||||
});
|
||||
|
||||
it('should not scale the stroke width', () => {
|
||||
const HouseSVG = buildLucideIconNode(House, {
|
||||
size: 12,
|
||||
strokeWidth: 2,
|
||||
absoluteStrokeWidth: false,
|
||||
});
|
||||
|
||||
expect(HouseSVG[1]['stroke-width']).toBe(2);
|
||||
});
|
||||
|
||||
it('should set non-scaling-stroke to child nodes', () => {
|
||||
const HouseSVG = buildLucideIconNode(House, { absoluteStrokeWidth: true });
|
||||
const HouseSVG = buildLucideIconNode(House, { nonScalingStroke: true });
|
||||
|
||||
for (const node of HouseSVG[2]!) {
|
||||
expect(node[1]['vector-effect']).toBe('non-scaling-stroke');
|
||||
@@ -61,7 +81,7 @@ describe('buildLucideIconNode', () => {
|
||||
});
|
||||
|
||||
it('should not set non-scaling-stroke', () => {
|
||||
const HouseSVG = buildLucideIconNode(House, { absoluteStrokeWidth: false });
|
||||
const HouseSVG = buildLucideIconNode(House, { nonScalingStroke: false });
|
||||
|
||||
expect(HouseSVG[1]['vector-effect']).toBeUndefined();
|
||||
});
|
||||
@@ -89,4 +109,30 @@ describe('buildLucideIconNode', () => {
|
||||
|
||||
expect(HouseSVG[1]['class']).toBe('lucide lucide-house lucide-home icon');
|
||||
});
|
||||
|
||||
it('should support className with multiple classes', () => {
|
||||
const HouseSVG = buildLucideIconNode(House, {
|
||||
className: ' icon custom lucide-house ',
|
||||
});
|
||||
|
||||
expect(HouseSVG[1]['class']).toBe('lucide lucide-house lucide-home icon custom');
|
||||
});
|
||||
|
||||
it('should not include default classes when includeDefaultClasses is false', () => {
|
||||
const HouseSVG = buildLucideIconNode(House, { includeDefaultClasses: false });
|
||||
|
||||
expect(HouseSVG[1]['class']).toBeUndefined();
|
||||
});
|
||||
|
||||
it('should add aria-hidden when hasA11yProp is false', () => {
|
||||
const HouseSVG = buildLucideIconNode(House, { hasA11yProp: false });
|
||||
|
||||
expect(HouseSVG[1]['aria-hidden']).toBe('true');
|
||||
});
|
||||
|
||||
it('should not add aria-hidden when hasA11yProp is true', () => {
|
||||
const HouseSVG = buildLucideIconNode(House, { hasA11yProp: true });
|
||||
|
||||
expect(HouseSVG[1]['aria-hidden']).toBeUndefined();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -8,6 +8,11 @@
|
||||
"moduleResolution": "node",
|
||||
"module": "ESNext",
|
||||
"target": "ESNext",
|
||||
"baseUrl": ".",
|
||||
"paths": {
|
||||
"@lucide/shared": ["../shared/src/index.ts"],
|
||||
"@lucide/shared/types": ["../shared/src/build/types.ts"],
|
||||
},
|
||||
"esModuleInterop": true,
|
||||
"isolatedModules": true,
|
||||
"lib": ["esnext", "dom"],
|
||||
|
||||
@@ -2,6 +2,11 @@ import plugins from '@lucide/rollup-plugins';
|
||||
import dts from 'rollup-plugin-dts';
|
||||
import pkg from './package.json' with { type: 'json' };
|
||||
|
||||
const dtsOptions = {
|
||||
includeExternal: ['@lucide/shared/types'],
|
||||
tsconfig: './tsconfig.json',
|
||||
};
|
||||
|
||||
const packageName = 'LucidePreact';
|
||||
const outputFileName = 'lucide-preact';
|
||||
const outputDir = 'dist';
|
||||
@@ -58,7 +63,7 @@ export default [
|
||||
format: 'es',
|
||||
},
|
||||
],
|
||||
plugins: [dts()],
|
||||
plugins: [dts(dtsOptions)],
|
||||
},
|
||||
{
|
||||
input: `src/${outputFileName}.suffixed.ts`,
|
||||
@@ -68,7 +73,7 @@ export default [
|
||||
format: 'es',
|
||||
},
|
||||
],
|
||||
plugins: [dts()],
|
||||
plugins: [dts(dtsOptions)],
|
||||
},
|
||||
{
|
||||
input: `src/${outputFileName}.prefixed.ts`,
|
||||
@@ -78,7 +83,7 @@ export default [
|
||||
format: 'es',
|
||||
},
|
||||
],
|
||||
plugins: [dts()],
|
||||
plugins: [dts(dtsOptions)],
|
||||
},
|
||||
...configs,
|
||||
];
|
||||
|
||||
@@ -1,19 +1,16 @@
|
||||
import base64SVG from '@lucide/build-icons/utils/base64SVG';
|
||||
import defineExportTemplate from '@lucide/build-icons/utils/defineExportTemplate';
|
||||
|
||||
export default defineExportTemplate(async ({
|
||||
componentName,
|
||||
iconName,
|
||||
children,
|
||||
getSvg,
|
||||
deprecated,
|
||||
deprecationReason,
|
||||
}) => {
|
||||
const svgContents = await getSvg();
|
||||
const svgBase64 = base64SVG(svgContents);
|
||||
export default defineExportTemplate(
|
||||
async ({ componentName, iconName, iconData, getSvg, deprecated, deprecationReason }) => {
|
||||
const svgContents = await getSvg();
|
||||
const svgBase64 = base64SVG(svgContents);
|
||||
|
||||
return `
|
||||
return `
|
||||
import createLucideIcon from '../createLucideIcon';
|
||||
import type { LucideIconData } from '../types';
|
||||
|
||||
const iconData: LucideIconData = ${JSON.stringify(iconData)};
|
||||
|
||||
/**
|
||||
* @component @name ${componentName}
|
||||
@@ -26,8 +23,9 @@ import createLucideIcon from '../createLucideIcon';
|
||||
* @returns {JSX.Element} JSX Element
|
||||
* ${deprecated ? `@deprecated ${deprecationReason}` : ''}
|
||||
*/
|
||||
const ${componentName} = createLucideIcon('${iconName}', ${JSON.stringify(children)});
|
||||
const ${componentName} = createLucideIcon(iconData);
|
||||
|
||||
export default ${componentName};
|
||||
`;
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
@@ -1,13 +1,19 @@
|
||||
import { h, toChildArray } from 'preact';
|
||||
import defaultAttributes from './defaultAttributes';
|
||||
import type { IconNode, LucideProps } from './types';
|
||||
import { buildLucideIconNode, hasA11yProp, mergeClasses } from '@lucide/shared';
|
||||
import type { LucideIconData, LucideIconNode, LucideProps } from './types';
|
||||
import { useLucideContext } from './context';
|
||||
import { mergeClasses } from '@lucide/shared';
|
||||
import { hasA11yProp } from '@lucide/shared';
|
||||
|
||||
interface IconComponentProps extends LucideProps {
|
||||
iconNode: IconNode;
|
||||
}
|
||||
type IconComponentProps = LucideProps &
|
||||
(
|
||||
| {
|
||||
icon: LucideIconData;
|
||||
iconNode?: never;
|
||||
}
|
||||
| {
|
||||
iconNode: LucideIconNode[];
|
||||
icon?: never;
|
||||
}
|
||||
);
|
||||
|
||||
/**
|
||||
* Lucide icon component
|
||||
@@ -18,19 +24,28 @@ interface IconComponentProps extends LucideProps {
|
||||
* @param {number} props.size - The size of the icon
|
||||
* @param {number} props.strokeWidth - The stroke width of the icon
|
||||
* @param {boolean} props.absoluteStrokeWidth - Whether to use absolute stroke width
|
||||
* @param {boolean} props.nonScalingStroke - Whether to use non scaling strokes
|
||||
* @param {string} props.class - The class name of the icon
|
||||
* @param {IconNode} props.children - The children of the icon
|
||||
* @param {IconNode} props.iconNode - The icon node of the icon
|
||||
* @param {LucideIconNode[]} props.children - The children of the icon
|
||||
* @param {LucideIconNode[]} props.iconNode - The icon node of the icon
|
||||
*
|
||||
* @returns {ForwardRefExoticComponent} LucideIcon
|
||||
*/
|
||||
const Icon = ({
|
||||
color,
|
||||
size,
|
||||
width,
|
||||
height,
|
||||
strokeWidth,
|
||||
absoluteStrokeWidth,
|
||||
nonScalingStroke,
|
||||
children,
|
||||
iconNode,
|
||||
iconNode = [],
|
||||
icon = {
|
||||
node: iconNode,
|
||||
aliases: [],
|
||||
size: 24,
|
||||
},
|
||||
class: classes = '',
|
||||
...rest
|
||||
}: IconComponentProps) => {
|
||||
@@ -38,29 +53,27 @@ const Icon = ({
|
||||
size: contextSize = 24,
|
||||
strokeWidth: contextStrokeWidth = 2,
|
||||
absoluteStrokeWidth: contextAbsoluteStrokeWidth = false,
|
||||
nonScalingStroke: contextNonScalingStroke = false,
|
||||
color: contextColor = 'currentColor',
|
||||
class: contextClass = '',
|
||||
} = useLucideContext() ?? {};
|
||||
|
||||
const calculatedStrokeWidth =
|
||||
absoluteStrokeWidth ?? contextAbsoluteStrokeWidth
|
||||
? (Number(strokeWidth ?? contextStrokeWidth) * 24) / Number(size ?? contextSize)
|
||||
: strokeWidth ?? contextStrokeWidth;
|
||||
const [name, svgAttributes, builtIconNode = []] = buildLucideIconNode(icon, {
|
||||
color: color ?? contextColor,
|
||||
width: width ?? size ?? contextSize,
|
||||
height: height ?? size ?? contextSize,
|
||||
strokeWidth: strokeWidth ?? contextStrokeWidth,
|
||||
absoluteStrokeWidth: absoluteStrokeWidth ?? contextAbsoluteStrokeWidth,
|
||||
nonScalingStroke: nonScalingStroke ?? contextNonScalingStroke,
|
||||
className: mergeClasses(contextClass, classes as string),
|
||||
hasA11yProp: Boolean(children) || hasA11yProp(rest),
|
||||
attributes: rest,
|
||||
});
|
||||
|
||||
return h(
|
||||
'svg',
|
||||
{
|
||||
...defaultAttributes,
|
||||
width: size ?? contextSize ?? 24,
|
||||
height: size ?? contextSize ?? 24,
|
||||
stroke: color ?? contextColor,
|
||||
['stroke-width' as 'strokeWidth']: calculatedStrokeWidth,
|
||||
class: mergeClasses('lucide', contextClass, classes),
|
||||
...(!children && !hasA11yProp(rest) && { 'aria-hidden': 'true' }),
|
||||
...rest,
|
||||
},
|
||||
[...iconNode.map(([tag, attrs]) => h(tag, attrs)), ...toChildArray(children)],
|
||||
);
|
||||
return h(name, { ...svgAttributes }, [
|
||||
...builtIconNode.map(([tag, attrs]) => h(tag, attrs)),
|
||||
...toChildArray(children),
|
||||
]);
|
||||
};
|
||||
|
||||
export default Icon;
|
||||
|
||||
@@ -5,13 +5,18 @@ const LucideContext = createContext<{
|
||||
size?: number;
|
||||
color?: string;
|
||||
strokeWidth?: number;
|
||||
/**
|
||||
* @deprecated Use `nonScalingStroke` instead.
|
||||
*/
|
||||
absoluteStrokeWidth?: boolean;
|
||||
nonScalingStroke?: boolean;
|
||||
class?: string;
|
||||
}>({
|
||||
size: 24,
|
||||
color: 'currentColor',
|
||||
strokeWidth: 2,
|
||||
absoluteStrokeWidth: false,
|
||||
nonScalingStroke: false,
|
||||
class: '',
|
||||
});
|
||||
|
||||
@@ -20,7 +25,11 @@ interface LucideProviderProps {
|
||||
size?: number;
|
||||
color?: string;
|
||||
strokeWidth?: number;
|
||||
/**
|
||||
* @deprecated Use `nonScalingStroke` instead.
|
||||
*/
|
||||
absoluteStrokeWidth?: boolean;
|
||||
nonScalingStroke?: boolean;
|
||||
class?: string;
|
||||
}
|
||||
|
||||
@@ -30,6 +39,7 @@ export function LucideProvider({
|
||||
color,
|
||||
strokeWidth,
|
||||
absoluteStrokeWidth,
|
||||
nonScalingStroke,
|
||||
class: className,
|
||||
}: LucideProviderProps) {
|
||||
const value = useMemo(
|
||||
@@ -38,9 +48,10 @@ export function LucideProvider({
|
||||
color,
|
||||
strokeWidth,
|
||||
absoluteStrokeWidth,
|
||||
nonScalingStroke,
|
||||
class: className,
|
||||
}),
|
||||
[size, color, strokeWidth, absoluteStrokeWidth, className],
|
||||
[size, color, strokeWidth, absoluteStrokeWidth, nonScalingStroke, className],
|
||||
);
|
||||
|
||||
return h(LucideContext.Provider, { value }, children);
|
||||
|
||||
@@ -1,34 +1,56 @@
|
||||
import { h, type JSX } from 'preact';
|
||||
import { mergeClasses, toKebabCase, toPascalCase } from '@lucide/shared';
|
||||
import { h, JSX } from 'preact';
|
||||
import { mergeClasses, toLucideIconData, toPascalCase } from '@lucide/shared';
|
||||
import Icon from './Icon';
|
||||
import type { IconNode, LucideIcon, LucideProps } from './types';
|
||||
import type { LucideIcon, LucideIconData, LucideIconNode, LucideProps } from './types';
|
||||
|
||||
/**
|
||||
* Create a Lucide icon component
|
||||
* @param {string} iconName
|
||||
* @param {array} iconNode
|
||||
* @returns {FunctionComponent} LucideIcon
|
||||
* Creates a Lucide icon component from icon data.
|
||||
*
|
||||
* @param icon Icon data object.
|
||||
* @returns Lucide icon component.
|
||||
*/
|
||||
const createLucideIcon = (iconName: string, iconNode: IconNode): LucideIcon => {
|
||||
function createLucideIcon(icon: LucideIconData): LucideIcon;
|
||||
|
||||
/**
|
||||
* Creates a Lucide icon component from the legacy icon arguments.
|
||||
*
|
||||
* @param iconName Icon name.
|
||||
* @param iconNode Icon node.
|
||||
* @param aliases Optional icon aliases.
|
||||
* @returns Lucide icon component.
|
||||
*/
|
||||
function createLucideIcon(
|
||||
iconName: string,
|
||||
iconNode: LucideIconNode[],
|
||||
aliases?: string[],
|
||||
): LucideIcon;
|
||||
|
||||
function createLucideIcon(
|
||||
iconDataOrName: LucideIconData | string,
|
||||
iconNode?: LucideIconNode[],
|
||||
aliases: string[] = [],
|
||||
): LucideIcon {
|
||||
const iconData =
|
||||
typeof iconDataOrName === 'string'
|
||||
? toLucideIconData(iconDataOrName, iconNode as LucideIconNode[], aliases)
|
||||
: iconDataOrName;
|
||||
|
||||
const Component = ({ class: classes = '', className = '', children, ...props }: LucideProps) =>
|
||||
h(
|
||||
Icon,
|
||||
{
|
||||
...props,
|
||||
iconNode,
|
||||
class: mergeClasses<string | JSX.SignalLike<string | undefined>>(
|
||||
`lucide-${toKebabCase(toPascalCase(iconName))}`,
|
||||
`lucide-${toKebabCase(iconName)}`,
|
||||
classes,
|
||||
className,
|
||||
),
|
||||
icon: iconData,
|
||||
class: mergeClasses<string | JSX.SignalLike<string | undefined>>(classes, className),
|
||||
},
|
||||
children,
|
||||
);
|
||||
|
||||
Component.displayName = toPascalCase(iconName);
|
||||
if (iconData.name) {
|
||||
Component.displayName = toPascalCase(iconData.name);
|
||||
}
|
||||
|
||||
return Component;
|
||||
};
|
||||
}
|
||||
|
||||
export default createLucideIcon;
|
||||
|
||||
@@ -1,13 +1 @@
|
||||
import type { JSX } from 'preact';
|
||||
|
||||
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',
|
||||
} satisfies JSX.SVGAttributes;
|
||||
export { defaultAttributes as default } from '@lucide/shared';
|
||||
|
||||
@@ -1,12 +1,29 @@
|
||||
import { type FunctionComponent, type JSX } from 'preact';
|
||||
import type {
|
||||
LucideIconData as SharedLucideIconData,
|
||||
LucideIconNode as SharedLucideIconNode,
|
||||
} from '@lucide/shared/types';
|
||||
|
||||
export type IconNode = [elementName: keyof JSX.IntrinsicElements, attrs: Record<string, string>][];
|
||||
export type LucideIconNode = SharedLucideIconNode;
|
||||
|
||||
export type LucideIconData = SharedLucideIconData;
|
||||
|
||||
/**
|
||||
* @deprecated Use LucideIconNode instead.
|
||||
*/
|
||||
export type IconNode = LucideIconNode[];
|
||||
|
||||
export interface LucideProps extends Partial<Omit<JSX.SVGAttributes, 'ref' | 'size'>> {
|
||||
color?: string;
|
||||
size?: string | number;
|
||||
width?: string | number;
|
||||
height?: string | number;
|
||||
strokeWidth?: string | number;
|
||||
/**
|
||||
* @deprecated Use `nonScalingStroke` instead.
|
||||
*/
|
||||
absoluteStrokeWidth?: boolean;
|
||||
nonScalingStroke?: boolean;
|
||||
}
|
||||
|
||||
export type LucideIcon = FunctionComponent<LucideProps>;
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
exports[`Using LucideProvider > should render the icon with LucideProvider 1`] = `
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
class="lucide lucide-house"
|
||||
class="lucide lucide-house lucide-home"
|
||||
fill="none"
|
||||
height="48"
|
||||
stroke="red"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
|
||||
|
||||
exports[`Using createLucideIcon > should create a component from an iconNode 1`] = `
|
||||
exports[`Using createLucideIcon > should create a component from icon data 1`] = `
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
class="lucide lucide-air-vent"
|
||||
@@ -29,10 +29,10 @@ exports[`Using createLucideIcon > should create a component from an iconNode 1`]
|
||||
</svg>
|
||||
`;
|
||||
|
||||
exports[`Using createLucideIcon > should create a component from an iconNode with iconName 1`] = `
|
||||
exports[`Using createLucideIcon > should include aliases from icon data 1`] = `
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
class="lucide lucide-air-vent"
|
||||
class="lucide lucide-circle-check lucide-check-circle"
|
||||
fill="none"
|
||||
height="24"
|
||||
stroke="currentColor"
|
||||
@@ -58,10 +58,10 @@ exports[`Using createLucideIcon > should create a component from an iconNode wit
|
||||
</svg>
|
||||
`;
|
||||
|
||||
exports[`Using createLucideIcon > should include backwards compatible className 1`] = `
|
||||
exports[`Using createLucideIcon > should merge className prop with icon classes 1`] = `
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
class="lucide lucide-layout2 lucide-layout-2"
|
||||
class="lucide lucide-circle-check lucide-check-circle custom-class"
|
||||
fill="none"
|
||||
height="24"
|
||||
stroke="currentColor"
|
||||
|
||||
@@ -10,7 +10,7 @@ exports[`Using lucide icon components > should adjust the size, stroke color and
|
||||
stroke-width="4"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
class="lucide lucide-grid3x3 lucide-grid-3x3"
|
||||
class="lucide lucide-grid-3x3 lucide-grid lucide-grid-3-x-3"
|
||||
aria-hidden="true"
|
||||
>
|
||||
<rect width="18"
|
||||
@@ -31,33 +31,42 @@ exports[`Using lucide icon components > should adjust the size, stroke color and
|
||||
</svg>
|
||||
`;
|
||||
|
||||
exports[`Using lucide icon components > should not scale the strokeWidth when absoluteStrokeWidth is set 1`] = `
|
||||
exports[`Using lucide icon components > should apply vector-effect when nonScalingStroke is set 1`] = `
|
||||
<svg xmlns="http://www.w3.org/2000/svg"
|
||||
width="48"
|
||||
height="48"
|
||||
viewbox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="red"
|
||||
stroke-width="1"
|
||||
stroke-width="2"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
class="lucide lucide-grid3x3 lucide-grid-3x3"
|
||||
class="lucide lucide-grid-3x3 lucide-grid lucide-grid-3-x-3"
|
||||
aria-hidden="true"
|
||||
>
|
||||
<rect width="18"
|
||||
<rect vector-effect="non-scaling-stroke"
|
||||
width="18"
|
||||
height="18"
|
||||
x="3"
|
||||
y="3"
|
||||
rx="2"
|
||||
>
|
||||
</rect>
|
||||
<path d="M3 9h18">
|
||||
<path vector-effect="non-scaling-stroke"
|
||||
d="M3 9h18"
|
||||
>
|
||||
</path>
|
||||
<path d="M3 15h18">
|
||||
<path vector-effect="non-scaling-stroke"
|
||||
d="M3 15h18"
|
||||
>
|
||||
</path>
|
||||
<path d="M9 3v18">
|
||||
<path vector-effect="non-scaling-stroke"
|
||||
d="M9 3v18"
|
||||
>
|
||||
</path>
|
||||
<path d="M15 3v18">
|
||||
<path vector-effect="non-scaling-stroke"
|
||||
d="M15 3v18"
|
||||
>
|
||||
</path>
|
||||
</svg>
|
||||
`;
|
||||
@@ -72,7 +81,38 @@ exports[`Using lucide icon components > should render an component 1`] = `
|
||||
stroke-width="2"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
class="lucide lucide-grid3x3 lucide-grid-3x3"
|
||||
class="lucide lucide-grid-3x3 lucide-grid lucide-grid-3-x-3"
|
||||
aria-hidden="true"
|
||||
>
|
||||
<rect width="18"
|
||||
height="18"
|
||||
x="3"
|
||||
y="3"
|
||||
rx="2"
|
||||
>
|
||||
</rect>
|
||||
<path d="M3 9h18">
|
||||
</path>
|
||||
<path d="M3 15h18">
|
||||
</path>
|
||||
<path d="M9 3v18">
|
||||
</path>
|
||||
<path d="M15 3v18">
|
||||
</path>
|
||||
</svg>
|
||||
`;
|
||||
|
||||
exports[`Using lucide icon components > should scale the strokeWidth when absoluteStrokeWidth is set 1`] = `
|
||||
<svg xmlns="http://www.w3.org/2000/svg"
|
||||
width="48"
|
||||
height="48"
|
||||
viewbox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="red"
|
||||
stroke-width="1"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
class="lucide lucide-grid-3x3 lucide-grid lucide-grid-3-x-3"
|
||||
aria-hidden="true"
|
||||
>
|
||||
<rect width="18"
|
||||
|
||||
@@ -51,6 +51,22 @@ describe('Using LucideProvider', () => {
|
||||
expect(IconComponent).toHaveAttribute('stroke-width', '1');
|
||||
});
|
||||
|
||||
it('should render the icon with LucideProvider and custom nonScalingStroke', () => {
|
||||
const { container } = render(
|
||||
<LucideProvider
|
||||
size={48}
|
||||
color="red"
|
||||
nonScalingStroke
|
||||
>
|
||||
<House />
|
||||
</LucideProvider>,
|
||||
);
|
||||
|
||||
const IconComponent = container.firstElementChild;
|
||||
|
||||
expect(IconComponent?.firstElementChild).toHaveAttribute('vector-effect', 'non-scaling-stroke');
|
||||
});
|
||||
|
||||
it("should override the provider's global props when passing props to the icon", () => {
|
||||
const { container } = render(
|
||||
<LucideProvider
|
||||
@@ -83,6 +99,9 @@ describe('Using LucideProvider', () => {
|
||||
|
||||
const IconComponent = container.firstElementChild;
|
||||
|
||||
expect(IconComponent).toHaveAttribute('class', 'lucide provider-class lucide-house icon-class');
|
||||
expect(IconComponent).toHaveAttribute(
|
||||
'class',
|
||||
'lucide lucide-house lucide-home provider-class icon-class',
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -4,30 +4,58 @@ import { airVent } from './testIconNodes';
|
||||
import { render } from '@testing-library/preact';
|
||||
|
||||
describe('Using createLucideIcon', () => {
|
||||
it('should create a component from an iconNode', () => {
|
||||
it('should create a component from icon data', () => {
|
||||
const AirVent = createLucideIcon({
|
||||
name: 'air-vent',
|
||||
node: airVent,
|
||||
});
|
||||
|
||||
const { container } = render(<AirVent />);
|
||||
|
||||
expect(container.firstChild).toMatchSnapshot();
|
||||
expect(container.firstChild).toBeDefined();
|
||||
});
|
||||
|
||||
it('should include aliases from icon data', () => {
|
||||
const CircleCheck = createLucideIcon({
|
||||
name: 'circle-check',
|
||||
aliases: ['check-circle'],
|
||||
node: airVent,
|
||||
});
|
||||
|
||||
const { container } = render(<CircleCheck />);
|
||||
|
||||
expect(container.firstChild).toMatchSnapshot();
|
||||
expect(container.firstChild).toBeDefined();
|
||||
});
|
||||
|
||||
it('should merge className prop with icon classes', () => {
|
||||
const CircleCheck = createLucideIcon({
|
||||
name: 'circle-check',
|
||||
aliases: ['check-circle'],
|
||||
node: airVent,
|
||||
});
|
||||
|
||||
const { container } = render(<CircleCheck class="custom-class" />);
|
||||
|
||||
expect(container.firstChild).toMatchSnapshot();
|
||||
expect(container.firstChild).toBeDefined();
|
||||
});
|
||||
|
||||
it('should create a component from legacy icon arguments', () => {
|
||||
const AirVent = createLucideIcon('AirVent', airVent);
|
||||
|
||||
const { container } = render(<AirVent />);
|
||||
|
||||
expect(container.firstChild).toMatchSnapshot();
|
||||
expect(container.firstChild).toBeDefined();
|
||||
expect(container.firstChild).toHaveClass('lucide-air-vent');
|
||||
});
|
||||
|
||||
it('should create a component from an iconNode with iconName', () => {
|
||||
const AirVent = createLucideIcon('air-vent', airVent);
|
||||
it('should include aliases from legacy icon arguments', () => {
|
||||
const CircleCheck = createLucideIcon('CircleCheck', airVent, ['check-circle']);
|
||||
|
||||
const { container } = render(<AirVent />);
|
||||
const { container } = render(<CircleCheck />);
|
||||
|
||||
expect(container.firstChild).toMatchSnapshot();
|
||||
expect(container.firstChild).toBeDefined();
|
||||
});
|
||||
|
||||
it('should include backwards compatible className', () => {
|
||||
const Layout2 = createLucideIcon('layout-2', airVent);
|
||||
|
||||
const { container } = render(<Layout2 />);
|
||||
|
||||
expect(container.firstChild).toMatchSnapshot();
|
||||
expect(container.firstChild).toBeDefined();
|
||||
expect(container.firstChild).toHaveClass('lucide-circle-check');
|
||||
expect(container.firstChild).toHaveClass('lucide-check-circle');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { describe, it, expect } from 'vitest';
|
||||
import { render, cleanup } from '@testing-library/preact';
|
||||
import { Pen, Edit2, Grid, Droplet } from '../src/lucide-preact';
|
||||
import { Pen, Edit2, Grid, Droplet, LucideIconData, createLucideIcon } from '../src/lucide-preact';
|
||||
import defaultAttributes from '../src/defaultAttributes';
|
||||
|
||||
type AttributesAssertion = { attributes: Record<string, { value: string }> };
|
||||
@@ -70,7 +70,7 @@ describe('Using lucide icon components', () => {
|
||||
expect(PenIconRenderedHTML).toBe(Edit2Container.innerHTML);
|
||||
});
|
||||
|
||||
it('should not scale the strokeWidth when absoluteStrokeWidth is set', () => {
|
||||
it('should scale the strokeWidth when absoluteStrokeWidth is set', () => {
|
||||
const { container } = render(
|
||||
<Grid
|
||||
size={48}
|
||||
@@ -89,12 +89,48 @@ describe('Using lucide icon components', () => {
|
||||
expect(container.innerHTML).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should apply vector-effect when nonScalingStroke is set', () => {
|
||||
const { container } = render(
|
||||
<Grid
|
||||
size={48}
|
||||
stroke="red"
|
||||
nonScalingStroke
|
||||
/>,
|
||||
);
|
||||
|
||||
const SVGElement = container.firstElementChild;
|
||||
|
||||
expect(SVGElement).toHaveAttribute('stroke', 'red');
|
||||
expect(SVGElement).toHaveAttribute('width', '48');
|
||||
expect(SVGElement).toHaveAttribute('height', '48');
|
||||
expect(SVGElement).toHaveAttribute('stroke-width', '2');
|
||||
expect(SVGElement?.firstElementChild).toHaveAttribute('vector-effect', 'non-scaling-stroke');
|
||||
|
||||
expect(container.innerHTML).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should apply all classes to the element', () => {
|
||||
const iconData: LucideIconData = {
|
||||
name: 'droplet',
|
||||
size: 24,
|
||||
node: [
|
||||
[
|
||||
'path',
|
||||
{
|
||||
d: 'M12 22a7 7 0 0 0 7-7c0-2-1-3.9-3-5.5s-3.5-4-4-6.5c-.5 2.5-2 4.9-4 6.5C6 11.1 5 13 5 15a7 7 0 0 0 7 7z',
|
||||
key: 'abc123',
|
||||
},
|
||||
],
|
||||
],
|
||||
aliases: ['drop'],
|
||||
};
|
||||
const testClass = 'my-class';
|
||||
const { container } = render(<Droplet class={testClass} />);
|
||||
const Icon = createLucideIcon(iconData);
|
||||
const { container } = render(<Icon class={testClass} />);
|
||||
|
||||
expect(container.firstChild).toHaveClass(testClass);
|
||||
expect(container.firstChild).toHaveClass('lucide');
|
||||
expect(container.firstChild).toHaveClass('lucide-droplet');
|
||||
expect(container.firstChild).toHaveClass('lucide-drop');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -8,6 +8,11 @@
|
||||
"moduleResolution": "node",
|
||||
"module": "ESNext",
|
||||
"target": "ESNext",
|
||||
"baseUrl": ".",
|
||||
"paths": {
|
||||
"@lucide/shared": ["../shared/src/index.ts"],
|
||||
"@lucide/shared/types": ["../shared/src/build/types.ts"],
|
||||
},
|
||||
"esModuleInterop": true,
|
||||
"isolatedModules": true,
|
||||
"lib": ["esnext", "dom"],
|
||||
|
||||
@@ -3,6 +3,11 @@ import dts from 'rollup-plugin-dts';
|
||||
import pkg from './package.json' with { type: 'json' };
|
||||
import getIconEntryNamesAndAliases from './scripts/getIconEntryNamesAndAliases.mts';
|
||||
|
||||
const dtsOptions = {
|
||||
includeExternal: ['@lucide/shared/types'],
|
||||
tsconfig: './tsconfig.json',
|
||||
};
|
||||
|
||||
const packageName = 'LucideReact';
|
||||
const outputFileName = 'lucide-react-native';
|
||||
const outputDir = 'dist';
|
||||
@@ -60,7 +65,7 @@ export default [
|
||||
format: 'es',
|
||||
},
|
||||
],
|
||||
plugins: [dts()],
|
||||
plugins: [dts(dtsOptions)],
|
||||
},
|
||||
{
|
||||
input: 'src/icons/index.ts',
|
||||
@@ -70,7 +75,7 @@ export default [
|
||||
format: 'es',
|
||||
},
|
||||
],
|
||||
plugins: [dts()],
|
||||
plugins: [dts(dtsOptions)],
|
||||
},
|
||||
{
|
||||
input: iconAndAliasEntries,
|
||||
@@ -95,7 +100,7 @@ export default [
|
||||
format: 'es',
|
||||
},
|
||||
],
|
||||
plugins: [dts()],
|
||||
plugins: [dts(dtsOptions)],
|
||||
},
|
||||
{
|
||||
input: `src/${outputFileName}.prefixed.ts`,
|
||||
@@ -105,7 +110,7 @@ export default [
|
||||
format: 'es',
|
||||
},
|
||||
],
|
||||
plugins: [dts()],
|
||||
plugins: [dts(dtsOptions)],
|
||||
},
|
||||
...configs,
|
||||
];
|
||||
|
||||
@@ -1,19 +1,16 @@
|
||||
import base64SVG from '@lucide/build-icons/utils/base64SVG';
|
||||
import defineExportTemplate from '@lucide/build-icons/utils/defineExportTemplate';
|
||||
|
||||
export default defineExportTemplate(async ({
|
||||
componentName,
|
||||
iconName,
|
||||
children,
|
||||
getSvg,
|
||||
deprecated,
|
||||
deprecationReason,
|
||||
}) => {
|
||||
const svgContents = await getSvg();
|
||||
const svgBase64 = base64SVG(svgContents);
|
||||
export default defineExportTemplate(
|
||||
async ({ componentName, iconName, iconData, getSvg, deprecated, deprecationReason }) => {
|
||||
const svgContents = await getSvg();
|
||||
const svgBase64 = base64SVG(svgContents);
|
||||
|
||||
return `
|
||||
return `
|
||||
import createLucideIcon from '../createLucideIcon';
|
||||
import type { LucideIconData } from '../types';
|
||||
|
||||
const iconData: LucideIconData = ${JSON.stringify(iconData)};
|
||||
|
||||
/**
|
||||
* @component @name ${componentName}
|
||||
@@ -26,8 +23,9 @@ import createLucideIcon from '../createLucideIcon';
|
||||
* @returns {JSX.Element} JSX Element
|
||||
* ${deprecated ? `@deprecated ${deprecationReason}` : ''}
|
||||
*/
|
||||
const ${componentName} = createLucideIcon('${componentName}', ${JSON.stringify(children)});
|
||||
const ${componentName} = createLucideIcon(iconData);
|
||||
|
||||
export default ${componentName};
|
||||
`;
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
@@ -1,14 +1,40 @@
|
||||
import { createElement, forwardRef, type FunctionComponent } from 'react';
|
||||
import * as NativeSvg from 'react-native-svg';
|
||||
import defaultAttributes, { childDefaultAttributes } from './defaultAttributes';
|
||||
import { IconNode, LucideProps } from './types';
|
||||
import { buildLucideIconForReact, hasA11yProp, mergeClasses } from '@lucide/shared';
|
||||
import { childDefaultAttributes } from './defaultAttributes';
|
||||
import { LucideIconData, LucideIconNode, LucideProps } from './types';
|
||||
import { useLucideContext } from './context';
|
||||
|
||||
interface IconComponentProps extends LucideProps {
|
||||
iconNode: IconNode;
|
||||
type IconComponentProps = LucideProps & {
|
||||
testID?: string;
|
||||
className?: string;
|
||||
}
|
||||
} & ({ icon: LucideIconData; iconNode?: never } | { icon?: never; iconNode: LucideIconNode[] });
|
||||
|
||||
const toNativeSvgAttrName = (attributeName: string) => {
|
||||
if (attributeName === 'class') {
|
||||
return 'className';
|
||||
}
|
||||
|
||||
if (attributeName.startsWith('data-') || attributeName.startsWith('aria-')) {
|
||||
return attributeName;
|
||||
}
|
||||
|
||||
return attributeName.replace(/-([a-z])/g, (_, character: string) => character.toUpperCase());
|
||||
};
|
||||
|
||||
const toNativeSvgAttributes = (attributes: Record<string, unknown>) => {
|
||||
return Object.entries(attributes).reduce<Record<string, unknown>>(
|
||||
(acc, [attributeName, value]) => {
|
||||
if (value === undefined) {
|
||||
return acc;
|
||||
}
|
||||
|
||||
acc[toNativeSvgAttrName(attributeName)] = value;
|
||||
return acc;
|
||||
},
|
||||
{},
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* Lucide icon component
|
||||
@@ -20,8 +46,8 @@ interface IconComponentProps extends LucideProps {
|
||||
* @param {number} props.strokeWidth - The stroke width of the icon
|
||||
* @param {boolean} props.absoluteStrokeWidth - Whether to use absolute stroke width
|
||||
* @param {string} props.className - The class name of the icon
|
||||
* @param {IconNode} props.children - The children of the icon
|
||||
* @param {IconNode} props.iconNode - The icon node of the icon
|
||||
* @param {LucideIconNode[]} props.children - The children of the icon
|
||||
* @param {LucideIconNode[]} props.iconNode - The icon node of the icon
|
||||
*
|
||||
* @returns {ForwardRefExoticComponent} LucideIcon
|
||||
*/
|
||||
@@ -30,10 +56,17 @@ const Icon = forwardRef<SVGSVGElement, IconComponentProps>(
|
||||
{
|
||||
color,
|
||||
size,
|
||||
width = size,
|
||||
height = size,
|
||||
strokeWidth,
|
||||
absoluteStrokeWidth,
|
||||
nonScalingStroke,
|
||||
children,
|
||||
iconNode,
|
||||
iconNode = [],
|
||||
icon = {
|
||||
node: iconNode,
|
||||
size: 24,
|
||||
},
|
||||
className,
|
||||
testID,
|
||||
...rest
|
||||
@@ -44,17 +77,28 @@ const Icon = forwardRef<SVGSVGElement, IconComponentProps>(
|
||||
size: contextSize = 24,
|
||||
strokeWidth: contextStrokeWidth = 2,
|
||||
absoluteStrokeWidth: contextAbsoluteStrokeWidth = false,
|
||||
nonScalingStroke: contextNonScalingStroke = false,
|
||||
color: contextColor = 'currentColor',
|
||||
className: contextClass = '',
|
||||
} = useLucideContext() ?? {};
|
||||
|
||||
const calculatedStrokeWidth =
|
||||
absoluteStrokeWidth ?? contextAbsoluteStrokeWidth
|
||||
? (Number(strokeWidth ?? contextStrokeWidth) * 24) / Number(size ?? contextSize)
|
||||
: strokeWidth ?? contextStrokeWidth;
|
||||
const hasAccessibleProp = Boolean(children) || hasA11yProp(rest);
|
||||
|
||||
const [, svgAttributes, builtIconNode = []] = buildLucideIconForReact(icon, {
|
||||
color: color ?? contextColor,
|
||||
width: width ?? size ?? contextSize,
|
||||
height: height ?? size ?? contextSize,
|
||||
strokeWidth: strokeWidth ?? contextStrokeWidth,
|
||||
absoluteStrokeWidth: absoluteStrokeWidth ?? contextAbsoluteStrokeWidth,
|
||||
nonScalingStroke: nonScalingStroke ?? contextNonScalingStroke,
|
||||
className: mergeClasses(contextClass, className),
|
||||
hasA11yProp: hasAccessibleProp,
|
||||
attributes: rest,
|
||||
});
|
||||
|
||||
const customAttrs = {
|
||||
stroke: color ?? contextColor ?? defaultAttributes.stroke,
|
||||
strokeWidth: calculatedStrokeWidth,
|
||||
stroke: svgAttributes['stroke'],
|
||||
strokeWidth: svgAttributes['strokeWidth'],
|
||||
...rest,
|
||||
};
|
||||
|
||||
@@ -62,21 +106,22 @@ const Icon = forwardRef<SVGSVGElement, IconComponentProps>(
|
||||
NativeSvg.Svg as unknown as string,
|
||||
{
|
||||
ref,
|
||||
...defaultAttributes,
|
||||
width: size ?? contextSize ?? defaultAttributes.width,
|
||||
height: size ?? contextSize ?? defaultAttributes.height,
|
||||
...toNativeSvgAttributes(svgAttributes),
|
||||
'data-testid': testID,
|
||||
className,
|
||||
...customAttrs,
|
||||
...rest,
|
||||
},
|
||||
[
|
||||
...iconNode.map(([tag, attrs]) => {
|
||||
...builtIconNode.map(([tag, attrs]) => {
|
||||
const upperCasedTag = (tag.charAt(0).toUpperCase() +
|
||||
tag.slice(1)) as keyof typeof NativeSvg;
|
||||
// duplicating the attributes here because generating the OTA update bundles don't inherit the SVG properties from parent (codepush, expo-updates)
|
||||
return createElement(
|
||||
NativeSvg[upperCasedTag] as FunctionComponent<LucideProps>,
|
||||
{ ...childDefaultAttributes, ...customAttrs, ...attrs } as LucideProps,
|
||||
toNativeSvgAttributes({
|
||||
...childDefaultAttributes,
|
||||
...customAttrs,
|
||||
...attrs,
|
||||
}) as LucideProps,
|
||||
);
|
||||
}),
|
||||
...((Array.isArray(children) ? children : [children]) || []),
|
||||
|
||||
@@ -4,12 +4,17 @@ const LucideContext = createContext<{
|
||||
size?: number;
|
||||
color?: string;
|
||||
strokeWidth?: number;
|
||||
/**
|
||||
* @deprecated Use `nonScalingStroke` instead.
|
||||
*/
|
||||
absoluteStrokeWidth?: boolean;
|
||||
nonScalingStroke?: boolean;
|
||||
}>({
|
||||
size: 24,
|
||||
color: 'currentColor',
|
||||
strokeWidth: 2,
|
||||
absoluteStrokeWidth: false,
|
||||
nonScalingStroke: false,
|
||||
});
|
||||
|
||||
interface LucideProviderProps {
|
||||
@@ -17,7 +22,11 @@ interface LucideProviderProps {
|
||||
size?: number;
|
||||
color?: string;
|
||||
strokeWidth?: number;
|
||||
/**
|
||||
* @deprecated Use `nonScalingStroke` instead.
|
||||
*/
|
||||
absoluteStrokeWidth?: boolean;
|
||||
nonScalingStroke?: boolean;
|
||||
}
|
||||
|
||||
export function LucideProvider({
|
||||
@@ -26,6 +35,7 @@ export function LucideProvider({
|
||||
color,
|
||||
strokeWidth,
|
||||
absoluteStrokeWidth,
|
||||
nonScalingStroke,
|
||||
}: LucideProviderProps) {
|
||||
const value = useMemo(
|
||||
() => ({
|
||||
@@ -33,8 +43,9 @@ export function LucideProvider({
|
||||
color,
|
||||
strokeWidth,
|
||||
absoluteStrokeWidth,
|
||||
nonScalingStroke,
|
||||
}),
|
||||
[size, color, strokeWidth, absoluteStrokeWidth],
|
||||
[size, color, strokeWidth, absoluteStrokeWidth, nonScalingStroke],
|
||||
);
|
||||
|
||||
return createElement(LucideContext.Provider, { value }, children);
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user