mirror of
https://github.com/lucide-icons/lucide.git
synced 2025-12-15 21:17:41 +01:00
feat(@lucide/svelte): Lucide svelte 5 package (#2753)
* Lucide svelte (#1) * Update peerDependencies to support Svelte 5 * Bump svelte version * Bump @testing-library/svelte version * Remove alias in vitest.config.ts that causes tests to fail due to deprecated svelte/internal API * Convert to svelte 5 syntax * Bump vite & @sveltejs/vite-plugin-svelte version * Fix error during render when children prop is missing & fix components being mounted on the server during tests * Update test snapshots to reflect the differences in the html generated by svelte 5 * Convert class attribute to new array syntax with built-in clsx * Convert export template to svelte 5 syntax * Move svelte 5 to separate directory * Update snapshots * Update docs * fix(icon): change variable declaration from let to const in Icon.svelte * Lucide svelte (#1) (#2727) * Update peerDependencies to support Svelte 5 * Bump svelte version * Bump @testing-library/svelte version * Remove alias in vitest.config.ts that causes tests to fail due to deprecated svelte/internal API * Convert to svelte 5 syntax * Bump vite & @sveltejs/vite-plugin-svelte version * Fix error during render when children prop is missing & fix components being mounted on the server during tests * Update test snapshots to reflect the differences in the html generated by svelte 5 * Convert class attribute to new array syntax with built-in clsx * Convert export template to svelte 5 syntax * Revert changes in lucide-svelte library * Update package lock * Update test files * Formatting * Update clean command * Fix build * Update packages * update deps * Fix export script * Format code * Revert version number change in package json * Update workflows --------- Co-authored-by: Aurélien Richard <56389380+aurelienrichard@users.noreply.github.com>
This commit is contained in:
41
.github/workflows/lucide-svelte-5.yml
vendored
Normal file
41
.github/workflows/lucide-svelte-5.yml
vendored
Normal file
@@ -0,0 +1,41 @@
|
||||
name: Lucide Svelte 5 checks
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- packages/svelte/**
|
||||
- packages/shared/**
|
||||
- tools/build-icons/**
|
||||
- tools/rollup-plugins/**
|
||||
- pnpm-lock.yaml
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: pnpm/action-setup@v4
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
cache: 'pnpm'
|
||||
|
||||
- name: Install dependencies
|
||||
run: pnpm install --frozen-lockfile
|
||||
|
||||
- name: Build
|
||||
run: pnpm --filter @lucide/svelte build
|
||||
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: pnpm/action-setup@v4
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
cache: 'pnpm'
|
||||
|
||||
- name: Install dependencies
|
||||
run: pnpm install --frozen-lockfile
|
||||
|
||||
- name: Test
|
||||
run: pnpm --filter @lucide/svelte test
|
||||
1
.github/workflows/release.yml
vendored
1
.github/workflows/release.yml
vendored
@@ -52,6 +52,7 @@ jobs:
|
||||
'lucide-preact',
|
||||
'lucide-solid',
|
||||
'lucide-svelte',
|
||||
'@lucide/svelte',
|
||||
]
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
@@ -7,22 +7,22 @@ Implementation of the lucide icon library for svelte applications.
|
||||
::: code-group
|
||||
|
||||
```sh [pnpm]
|
||||
pnpm add lucide-svelte
|
||||
pnpm add @lucide/svelte
|
||||
```
|
||||
|
||||
```sh [yarn]
|
||||
yarn add lucide-svelte
|
||||
yarn add @lucide/svelte
|
||||
```
|
||||
|
||||
```sh [npm]
|
||||
npm install lucide-svelte
|
||||
npm install @lucide/svelte
|
||||
```
|
||||
|
||||
```sh [bun]
|
||||
bun add lucide-svelte
|
||||
bun add @lucide/svelte
|
||||
```
|
||||
|
||||
:::
|
||||
> `@lucide/svelte` is only for Svelte 5, for Svelte 4 use the `lucide-svelte` package.
|
||||
|
||||
## How to use
|
||||
|
||||
@@ -36,7 +36,7 @@ Default usage:
|
||||
|
||||
```svelte
|
||||
<script>
|
||||
import { Skull } from 'lucide-svelte';
|
||||
import { Skull } from '@lucide/svelte';
|
||||
</script>
|
||||
|
||||
<Skull />
|
||||
@@ -46,17 +46,17 @@ Additional props can be passed to adjust the icon:
|
||||
|
||||
```svelte
|
||||
<script>
|
||||
import { Camera } from 'lucide-svelte';
|
||||
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:
|
||||
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';
|
||||
import CircleAlert from '@lucide/svelte/icons/circle-alert';
|
||||
</script>
|
||||
|
||||
<CircleAlert color="#ff3e98" />
|
||||
@@ -77,7 +77,7 @@ To customize the appearance of an icon, you can pass custom properties as props
|
||||
|
||||
```svelte
|
||||
<script>
|
||||
import { Phone } from 'lucide-svelte';
|
||||
import { Phone } from '@lucide/svelte';
|
||||
</script>
|
||||
|
||||
<Phone fill="#333" />
|
||||
@@ -91,101 +91,138 @@ The package includes type definitions for all icons. This is useful if you want
|
||||
|
||||
### TypeScript Example
|
||||
|
||||
#### Svelte 4
|
||||
::: code-group
|
||||
|
||||
```svelte
|
||||
```svelte [Svelte 5]
|
||||
<script lang="ts">
|
||||
import { Home, Library, Cog, type Icon } from 'lucide-svelte';
|
||||
import type { ComponentType } from 'svelte';
|
||||
import { Home, Library, Cog, type Icon as IconType } from '@lucide/svelte';
|
||||
|
||||
type MenuItem = {
|
||||
name: string;
|
||||
href: string;
|
||||
icon: ComponentType<Icon>;
|
||||
};
|
||||
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
|
||||
}
|
||||
];
|
||||
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}
|
||||
<a href={item.href}>
|
||||
<svelte:component this={item.icon} />
|
||||
<span>{item.name}</span>
|
||||
</a>
|
||||
{@const Icon = item.icon}
|
||||
<a href={item.href}>
|
||||
<Icon />
|
||||
<span>{item.name}</span>
|
||||
</a>
|
||||
{/each}
|
||||
```
|
||||
|
||||
|
||||
#### Svelte 5
|
||||
Some changes are required since Svelte 5 [deprecates](https://svelte.dev/docs/svelte/v5-migration-guide#Components-are-no-longer-classes-Component-typing-changes) the `ComponentType` typescript type.
|
||||
|
||||
```svelte
|
||||
```svelte [Svelte 4]
|
||||
<script lang="ts">
|
||||
import { Home, Library, Cog, type Icon as IconType } from 'lucide-svelte';
|
||||
import { Home, Library, Cog, type Icon } from '@lucide/svelte';
|
||||
import type { ComponentType } from 'svelte';
|
||||
|
||||
type MenuItem = {
|
||||
name: string;
|
||||
href: string;
|
||||
icon: typeof IconType;
|
||||
};
|
||||
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
|
||||
}
|
||||
];
|
||||
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>
|
||||
<a href={item.href}>
|
||||
<svelte:component this={item.icon} />
|
||||
<span>{item.name}</span>
|
||||
</a>
|
||||
{/each}
|
||||
```
|
||||
:::
|
||||
|
||||
### JSDoc Example
|
||||
|
||||
#### Svelte 4
|
||||
::: code-group
|
||||
|
||||
```svelte
|
||||
```svelte [Svelte 5]
|
||||
<script>
|
||||
import { Home, Library, Cog } from 'lucide-svelte';
|
||||
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
|
||||
* @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[]} */
|
||||
@@ -216,49 +253,7 @@ Some changes are required since Svelte 5 [deprecates](https://svelte.dev/docs/sv
|
||||
{/each}
|
||||
```
|
||||
|
||||
|
||||
#### Svelte 5
|
||||
|
||||
```svelte
|
||||
<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}
|
||||
|
||||
```
|
||||
:::
|
||||
|
||||
For more details about typing the `svelte:component` directive, see the [Svelte documentation](https://svelte.dev/docs/typescript#types-componenttype).
|
||||
|
||||
@@ -275,7 +270,7 @@ This creates a single icon based on the iconNode passed and renders a Lucide ico
|
||||
|
||||
```svelte
|
||||
<script>
|
||||
import { Icon } from 'lucide-svelte';
|
||||
import { Icon } from '@lucide/svelte';
|
||||
import { burger, sausage } from '@lucide/lab';
|
||||
</script>
|
||||
|
||||
@@ -293,29 +288,29 @@ The example below imports all ES Modules, so exercise caution when using it. Imp
|
||||
|
||||
### Icon Component Example
|
||||
|
||||
#### Svelte 4
|
||||
::: code-group
|
||||
|
||||
```svelte
|
||||
```svelte [Svelte 5]
|
||||
<script>
|
||||
import * as icons from 'lucide-svelte';
|
||||
import * as icons from '@lucide/svelte';
|
||||
let { name } = $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} />
|
||||
```
|
||||
|
||||
#### Svelte 5
|
||||
|
||||
```svelte
|
||||
<script>
|
||||
import * as icons from 'lucide-svelte';
|
||||
let { name } = $props();
|
||||
|
||||
const Icon = icons[name];
|
||||
</script>
|
||||
|
||||
<Icon {...props} />
|
||||
```
|
||||
:::
|
||||
|
||||
#### Using the Icon Component
|
||||
|
||||
|
||||
@@ -12,4 +12,4 @@
|
||||
<path d="M20 13c0 5-3.5 7.5-7.66 8.95a1 1 0 0 1-.67-.01C7.5 20.5 4 18 4 13V6a1 1 0 0 1 1-1c2 0 4.5-1.2 6.24-2.72a1.17 1.17 0 0 1 1.52 0C14.51 3.81 17 5 19 5a1 1 0 0 1 1 1z" />
|
||||
<path d="M6.376 18.91a6 6 0 0 1 11.249.003" />
|
||||
<circle cx="12" cy="11" r="4" />
|
||||
</svg>
|
||||
</svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 469 B After Width: | Height: | Size: 470 B |
@@ -1,36 +1,34 @@
|
||||
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
|
||||
|
||||
exports[`Using Icon Component > should render icon and match snapshot 1`] = `
|
||||
<div>
|
||||
<svg
|
||||
class="lucide-icon lucide"
|
||||
fill="none"
|
||||
height="48"
|
||||
stroke="red"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="1"
|
||||
viewBox="0 0 24 24"
|
||||
width="48"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<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
|
||||
d="M6 8h12"
|
||||
/>
|
||||
|
||||
<path
|
||||
d="M18.3 17.7a2.5 2.5 0 0 1-3.16 3.83 2.53 2.53 0 0 1-1.14-2V12"
|
||||
/>
|
||||
|
||||
<path
|
||||
d="M6.6 15.6A2 2 0 1 0 10 17v-5"
|
||||
/>
|
||||
|
||||
|
||||
</svg>
|
||||
</div>
|
||||
<svg
|
||||
class="lucide-icon lucide"
|
||||
fill="none"
|
||||
height="48"
|
||||
stroke="red"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="1"
|
||||
viewBox="0 0 24 24"
|
||||
width="48"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<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
|
||||
d="M6 8h12"
|
||||
/>
|
||||
|
||||
<path
|
||||
d="M18.3 17.7a2.5 2.5 0 0 1-3.16 3.83 2.53 2.53 0 0 1-1.14-2V12"
|
||||
/>
|
||||
|
||||
<path
|
||||
d="M6.6 15.6A2 2 0 1 0 10 17v-5"
|
||||
/>
|
||||
|
||||
|
||||
</svg>
|
||||
`;
|
||||
|
||||
@@ -42,176 +42,168 @@ exports[`Using lucide icon components > should add a class to the element 1`] =
|
||||
`;
|
||||
|
||||
exports[`Using lucide icon components > should adjust the size, stroke color and stroke width 1`] = `
|
||||
<body>
|
||||
<div>
|
||||
<svg
|
||||
class="lucide-icon lucide lucide-smile"
|
||||
fill="none"
|
||||
height="48"
|
||||
stroke="red"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="4"
|
||||
viewBox="0 0 24 24"
|
||||
width="48"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<circle
|
||||
cx="12"
|
||||
cy="12"
|
||||
r="10"
|
||||
/>
|
||||
|
||||
<path
|
||||
d="M8 14s1.5 2 4 2 4-2 4-2"
|
||||
/>
|
||||
|
||||
<line
|
||||
x1="9"
|
||||
x2="9.01"
|
||||
y1="9"
|
||||
y2="9"
|
||||
/>
|
||||
|
||||
<line
|
||||
x1="15"
|
||||
x2="15.01"
|
||||
y1="9"
|
||||
y2="9"
|
||||
/>
|
||||
|
||||
|
||||
</svg>
|
||||
</div>
|
||||
</body>
|
||||
`;
|
||||
|
||||
exports[`Using lucide icon components > should not scale the strokeWidth when absoluteStrokeWidth is set 1`] = `
|
||||
<div>
|
||||
<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"
|
||||
data-testid="smile-icon"
|
||||
class="lucide-icon lucide lucide-smile"
|
||||
<svg
|
||||
class="lucide-icon lucide lucide-smile"
|
||||
fill="none"
|
||||
height="48"
|
||||
stroke="red"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="4"
|
||||
viewBox="0 0 24 24"
|
||||
width="48"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<circle cx="12"
|
||||
cy="12"
|
||||
r="10"
|
||||
>
|
||||
</circle>
|
||||
<path d="M8 14s1.5 2 4 2 4-2 4-2">
|
||||
</path>
|
||||
<line x1="9"
|
||||
x2="9.01"
|
||||
y1="9"
|
||||
y2="9"
|
||||
>
|
||||
</line>
|
||||
<line x1="15"
|
||||
x2="15.01"
|
||||
y1="9"
|
||||
y2="9"
|
||||
>
|
||||
</line>
|
||||
<circle
|
||||
cx="12"
|
||||
cy="12"
|
||||
r="10"
|
||||
/>
|
||||
|
||||
<path
|
||||
d="M8 14s1.5 2 4 2 4-2 4-2"
|
||||
/>
|
||||
|
||||
<line
|
||||
x1="9"
|
||||
x2="9.01"
|
||||
y1="9"
|
||||
y2="9"
|
||||
/>
|
||||
|
||||
<line
|
||||
x1="15"
|
||||
x2="15.01"
|
||||
y1="9"
|
||||
y2="9"
|
||||
/>
|
||||
|
||||
|
||||
</svg>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`Using lucide icon components > should render an component 1`] = `
|
||||
<body>
|
||||
<div>
|
||||
<svg
|
||||
class="lucide-icon lucide lucide-smile"
|
||||
fill="none"
|
||||
height="24"
|
||||
stroke="currentColor"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
viewBox="0 0 24 24"
|
||||
width="24"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<circle
|
||||
cx="12"
|
||||
cy="12"
|
||||
r="10"
|
||||
/>
|
||||
|
||||
<path
|
||||
d="M8 14s1.5 2 4 2 4-2 4-2"
|
||||
/>
|
||||
|
||||
<line
|
||||
x1="9"
|
||||
exports[`Using lucide icon components > should not 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"
|
||||
data-testid="smile-icon"
|
||||
class="lucide-icon lucide lucide-smile"
|
||||
>
|
||||
<circle cx="12"
|
||||
cy="12"
|
||||
r="10"
|
||||
>
|
||||
</circle>
|
||||
<path d="M8 14s1.5 2 4 2 4-2 4-2">
|
||||
</path>
|
||||
<line x1="9"
|
||||
x2="9.01"
|
||||
y1="9"
|
||||
y2="9"
|
||||
/>
|
||||
|
||||
<line
|
||||
x1="15"
|
||||
>
|
||||
</line>
|
||||
<line x1="15"
|
||||
x2="15.01"
|
||||
y1="9"
|
||||
y2="9"
|
||||
/>
|
||||
|
||||
|
||||
</svg>
|
||||
</div>
|
||||
</body>
|
||||
>
|
||||
</line>
|
||||
</svg>
|
||||
`;
|
||||
|
||||
exports[`Using lucide icon components > should render an component 1`] = `
|
||||
<div>
|
||||
<svg
|
||||
class="lucide-icon lucide lucide-smile"
|
||||
fill="none"
|
||||
height="24"
|
||||
stroke="currentColor"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
viewBox="0 0 24 24"
|
||||
width="24"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<circle
|
||||
cx="12"
|
||||
cy="12"
|
||||
r="10"
|
||||
/>
|
||||
|
||||
<path
|
||||
d="M8 14s1.5 2 4 2 4-2 4-2"
|
||||
/>
|
||||
|
||||
<line
|
||||
x1="9"
|
||||
x2="9.01"
|
||||
y1="9"
|
||||
y2="9"
|
||||
/>
|
||||
|
||||
<line
|
||||
x1="15"
|
||||
x2="15.01"
|
||||
y1="9"
|
||||
y2="9"
|
||||
/>
|
||||
|
||||
|
||||
</svg>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`Using lucide icon components > should render an icon slot 1`] = `
|
||||
<body>
|
||||
<div>
|
||||
<svg
|
||||
class="lucide-icon lucide lucide-smile"
|
||||
fill="none"
|
||||
height="24"
|
||||
stroke="currentColor"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
viewBox="0 0 24 24"
|
||||
width="24"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<circle
|
||||
cx="12"
|
||||
cy="12"
|
||||
r="10"
|
||||
/>
|
||||
|
||||
<path
|
||||
d="M8 14s1.5 2 4 2 4-2 4-2"
|
||||
/>
|
||||
|
||||
<line
|
||||
x1="9"
|
||||
x2="9.01"
|
||||
y1="9"
|
||||
y2="9"
|
||||
/>
|
||||
|
||||
<line
|
||||
x1="15"
|
||||
x2="15.01"
|
||||
y1="9"
|
||||
y2="9"
|
||||
/>
|
||||
|
||||
|
||||
<text>
|
||||
Test
|
||||
</text>
|
||||
</svg>
|
||||
</div>
|
||||
</body>
|
||||
<div>
|
||||
<svg
|
||||
class="lucide-icon lucide lucide-smile"
|
||||
fill="none"
|
||||
height="24"
|
||||
stroke="currentColor"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
viewBox="0 0 24 24"
|
||||
width="24"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<circle
|
||||
cx="12"
|
||||
cy="12"
|
||||
r="10"
|
||||
/>
|
||||
|
||||
<path
|
||||
d="M8 14s1.5 2 4 2 4-2 4-2"
|
||||
/>
|
||||
|
||||
<line
|
||||
x1="9"
|
||||
x2="9.01"
|
||||
y1="9"
|
||||
y2="9"
|
||||
/>
|
||||
|
||||
<line
|
||||
x1="15"
|
||||
x2="15.01"
|
||||
y1="9"
|
||||
y2="9"
|
||||
/>
|
||||
|
||||
|
||||
<text>
|
||||
Test
|
||||
</text>
|
||||
</svg>
|
||||
</div>
|
||||
`;
|
||||
|
||||
2
packages/svelte/.gitignore
vendored
Normal file
2
packages/svelte/.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
src/icons/*.svelte
|
||||
.svelte-kit
|
||||
73
packages/svelte/README.md
Normal file
73
packages/svelte/README.md
Normal file
@@ -0,0 +1,73 @@
|
||||
<p align="center">
|
||||
<a href="https://github.com/lucide-icons/lucide">
|
||||
<img src="https://lucide.dev/package-logos/lucide-svelte.svg" alt="Lucide icon library for Svelte 5 applications." width="540">
|
||||
</a>
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
Lucide icon library for Svelte 5 applications.
|
||||
</p>
|
||||
|
||||
<div align="center">
|
||||
|
||||
[](https://www.npmjs.com/package/lucide-svelte)
|
||||

|
||||
[](https://lucide.dev/license)
|
||||
</div>
|
||||
|
||||
<p align="center">
|
||||
<a href="https://lucide.dev/guide/">About</a>
|
||||
·
|
||||
<a href="https://lucide.dev/icons/">Icons</a>
|
||||
·
|
||||
<a href="https://lucide.dev/guide/packages/lucide-svelte">Documentation</a>
|
||||
·
|
||||
<a href="https://lucide.dev/license">License</a>
|
||||
</p>
|
||||
|
||||
# Lucide Svelte
|
||||
|
||||
Implementation of the lucide icon library for svelte applications.
|
||||
|
||||
## Installation
|
||||
|
||||
```sh
|
||||
pnpm add @lucide/svelte
|
||||
```
|
||||
|
||||
```sh
|
||||
npm install @lucide/svelte
|
||||
```
|
||||
|
||||
```sh
|
||||
yarn add @lucide/svelte
|
||||
```
|
||||
|
||||
```sh
|
||||
bun add @lucide/svelte
|
||||
```
|
||||
|
||||
## Documentation
|
||||
|
||||
For full documentation, visit [lucide.dev](https://lucide.dev/guide/packages/lucide-svelte)
|
||||
|
||||
## Community
|
||||
|
||||
Join the [Discord server](https://discord.gg/EH6nSts) to chat with the maintainers and other users.
|
||||
|
||||
## License
|
||||
|
||||
Lucide is licensed under the ISC license. See [LICENSE](https://lucide.dev/license).
|
||||
|
||||
## Sponsors
|
||||
|
||||
<a href="https://vercel.com?utm_source=lucide&utm_campaign=oss">
|
||||
<img src="https://lucide.dev/vercel.svg" alt="Powered by Vercel" width="200" />
|
||||
</a>
|
||||
|
||||
<a href="https://www.digitalocean.com/?refcode=b0877a2caebd&utm_campaign=Referral_Invite&utm_medium=Referral_Program&utm_source=badge"><img src="https://lucide.dev/digitalocean.svg" width="200" alt="DigitalOcean Referral Badge" /></a>
|
||||
|
||||
### Awesome backers 🍺
|
||||
|
||||
<a href="https://www.scipress.io?utm_source=lucide"><img src="https://lucide.dev/sponsors/scipress.svg" width="180" alt="Scipress sponsor badge" /></a>
|
||||
<a href="https://github.com/pdfme/pdfme"><img src="https://lucide.dev/sponsors/pdfme.svg" width="180" alt="pdfme sponsor badge" /></a>
|
||||
79
packages/svelte/package.json
Normal file
79
packages/svelte/package.json
Normal file
@@ -0,0 +1,79 @@
|
||||
{
|
||||
"name": "@lucide/svelte",
|
||||
"description": "A Lucide icon library package for Svelte applications",
|
||||
"version": "0.1.0",
|
||||
"license": "ISC",
|
||||
"homepage": "https://lucide.dev",
|
||||
"bugs": "https://github.com/lucide-icons/lucide/issues",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/lucide-icons/lucide.git",
|
||||
"directory": "packages/svelte"
|
||||
},
|
||||
"keywords": [
|
||||
"Lucide",
|
||||
"Svelte",
|
||||
"Feather",
|
||||
"Icons",
|
||||
"Icon",
|
||||
"SVG",
|
||||
"Feather Icons",
|
||||
"Fontawesome",
|
||||
"Font Awesome"
|
||||
],
|
||||
"author": "Eric Fennis",
|
||||
"type": "module",
|
||||
"main": "dist/lucide-svelte.js",
|
||||
"exports": {
|
||||
".": {
|
||||
"types": "./dist/lucide-svelte.d.ts",
|
||||
"svelte": "./dist/lucide-svelte.js",
|
||||
"default": "./dist/lucide-svelte.js"
|
||||
},
|
||||
"./icons": {
|
||||
"types": "./dist/lucide-svelte.d.ts",
|
||||
"svelte": "./dist/lucide-svelte.js"
|
||||
},
|
||||
"./icons/*": {
|
||||
"types": "./dist/icons/*.svelte.d.ts",
|
||||
"svelte": "./dist/icons/*.js",
|
||||
"default": "./dist/icons/*.js"
|
||||
}
|
||||
},
|
||||
"typings": "dist/lucide-svelte.d.ts",
|
||||
"sideEffects": false,
|
||||
"files": [
|
||||
"dist"
|
||||
],
|
||||
"scripts": {
|
||||
"build": "pnpm clean && pnpm copy:license && pnpm build:icons && pnpm build:package && pnpm build:license",
|
||||
"copy:license": "cp ../../LICENSE ./LICENSE",
|
||||
"clean": "rm -rf dist stats ./src/icons/*.{ts,svelte} ./src/aliases/{aliases,prefixed,suffixed}.ts",
|
||||
"build:icons": "build-icons --output=./src --templateSrc=./scripts/exportTemplate.mjs --exportFileName=index.ts --iconFileExtension=.svelte --importImportFileExtension=.svelte --separateIconFileExport --separateIconFileExportExtension=.ts --withAliases --aliasesFileExtension=.ts --separateAliasesFile --separateAliasesFileExtension=.ts --aliasImportFileExtension=.js --pretty=false",
|
||||
"build:package": "svelte-package --input ./src",
|
||||
"build:license": "node ./scripts/appendBlockComments.mjs",
|
||||
"test": "pnpm copy:license && pnpm build:icons && vitest run",
|
||||
"test:watch": "vitest watch",
|
||||
"version": "pnpm version --git-tag-version=false"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@lucide/build-icons": "workspace:*",
|
||||
"@lucide/helpers": "workspace:*",
|
||||
"@sveltejs/package": "^2.3.10",
|
||||
"@sveltejs/vite-plugin-svelte": "^5.0.3",
|
||||
"@testing-library/jest-dom": "^6.1.4",
|
||||
"@testing-library/svelte": "^5.2.7",
|
||||
"@tsconfig/svelte": "^5.0.4",
|
||||
"jest-serializer-html": "^7.1.0",
|
||||
"jsdom": "^20.0.3",
|
||||
"svelte": "^5.20.5",
|
||||
"svelte-check": "^4.1.4",
|
||||
"svelte-preprocess": "^6.0.3",
|
||||
"typescript": "^5.1.6",
|
||||
"vite": "6.0.7",
|
||||
"vitest": "^1.1.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"svelte": "^5"
|
||||
}
|
||||
}
|
||||
64
packages/svelte/scripts/appendBlockComments.mjs
Normal file
64
packages/svelte/scripts/appendBlockComments.mjs
Normal file
@@ -0,0 +1,64 @@
|
||||
import { lstatSync } from 'fs';
|
||||
import { readdir, readFile, writeFile } from 'fs/promises';
|
||||
import path from 'path';
|
||||
import { getCurrentDirPath } from '@lucide/helpers';
|
||||
import { getJSBanner } from './license.mjs';
|
||||
|
||||
const currentDir = getCurrentDirPath(import.meta.url);
|
||||
const targetDirectory = path.join(currentDir, '../dist');
|
||||
|
||||
const files = await readdir(targetDirectory, {
|
||||
recursive: true,
|
||||
encoding: 'utf-8',
|
||||
});
|
||||
|
||||
// eslint-disable-next-line no-restricted-syntax
|
||||
for (const file of files) {
|
||||
const filepath = path.join(targetDirectory, file);
|
||||
const filestat = lstatSync(filepath);
|
||||
|
||||
// eslint-disable-next-line no-continue
|
||||
if (filestat.isFile() === false || filestat.isDirectory()) continue;
|
||||
|
||||
// eslint-disable-next-line no-await-in-loop
|
||||
const contents = await readFile(filepath, { encoding: 'utf-8' });
|
||||
let newContents = contents;
|
||||
const ext = path.extname(filepath);
|
||||
let license;
|
||||
|
||||
if (/\.(js|mjs|cjs|ts)/.test(ext)) {
|
||||
license = getJSBanner();
|
||||
}
|
||||
|
||||
if (license) {
|
||||
newContents = license + contents;
|
||||
}
|
||||
|
||||
// Places icon block comment at the top of the Svelte component class
|
||||
if (/icons\/(.*?)\.svelte\.d\.ts/.test(filepath)) {
|
||||
const svelteFilepath = filepath.replace('.d.ts', '');
|
||||
// eslint-disable-next-line no-await-in-loop
|
||||
const svelteFileContents = await readFile(svelteFilepath, { encoding: 'utf-8' });
|
||||
|
||||
const blockCommentRegex = /\/\*\*\n\s\*\s(@component\s@name)[\s\S]*?\*\//;
|
||||
const blockCommentMatch = blockCommentRegex.exec(svelteFileContents);
|
||||
|
||||
if (blockCommentMatch !== null) {
|
||||
const blockComment = blockCommentMatch[0];
|
||||
|
||||
const exportClassRegex = /export default class (\w+) extends SvelteComponentTyped<(.*?)> {/;
|
||||
|
||||
if (exportClassRegex.test(newContents)) {
|
||||
newContents = newContents.replace(
|
||||
exportClassRegex,
|
||||
`${blockComment}\nexport default class $1 extends SvelteComponentTyped<$2> {`,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (newContents !== contents) {
|
||||
// eslint-disable-next-line no-await-in-loop
|
||||
await writeFile(filepath, newContents, { encoding: 'utf-8' });
|
||||
}
|
||||
}
|
||||
43
packages/svelte/scripts/exportTemplate.mjs
Normal file
43
packages/svelte/scripts/exportTemplate.mjs
Normal file
@@ -0,0 +1,43 @@
|
||||
/* eslint-disable import/no-extraneous-dependencies */
|
||||
import base64SVG from '@lucide/build-icons/utils/base64SVG.mjs';
|
||||
import { getJSBanner } from './license.mjs';
|
||||
|
||||
export default async ({
|
||||
iconName,
|
||||
children,
|
||||
componentName,
|
||||
getSvg,
|
||||
deprecated,
|
||||
deprecationReason,
|
||||
}) => {
|
||||
const svgContents = await getSvg();
|
||||
const svgBase64 = base64SVG(svgContents);
|
||||
|
||||
return `\
|
||||
<script lang="ts">
|
||||
${getJSBanner()}
|
||||
import Icon from '../Icon.svelte';
|
||||
import type { IconNode, IconProps } from '../types.js';
|
||||
|
||||
let props: IconProps = $props();
|
||||
|
||||
const iconNode: IconNode = ${JSON.stringify(children)};
|
||||
|
||||
/**
|
||||
* @component @name ${componentName}
|
||||
* @description Lucide SVG icon component, renders SVG Element with children.
|
||||
*
|
||||
* @preview  - https://lucide.dev/icons/${iconName}
|
||||
* @see https://lucide.dev/guide/packages/lucide-svelte - Documentation
|
||||
*
|
||||
* @param {Object} props - Lucide icons props and any valid SVG attribute
|
||||
* @returns {FunctionalComponent} Svelte component
|
||||
* ${deprecated ? `@deprecated ${deprecationReason}` : ''}
|
||||
*/
|
||||
</script>
|
||||
|
||||
<Icon name="${iconName}" {...props} iconNode={iconNode}>
|
||||
{@render props.children?.()}
|
||||
</Icon>
|
||||
`;
|
||||
};
|
||||
13
packages/svelte/scripts/license.mjs
Normal file
13
packages/svelte/scripts/license.mjs
Normal file
@@ -0,0 +1,13 @@
|
||||
import fs from 'fs';
|
||||
import pkg from '../package.json' with { type: 'json' };
|
||||
|
||||
const license = fs.readFileSync('LICENSE', 'utf-8');
|
||||
|
||||
export function getJSBanner() {
|
||||
return `/**
|
||||
* @license ${pkg.name} v${pkg.version} - ${pkg.license}
|
||||
*
|
||||
* ${license.split('\n').join('\n * ')}
|
||||
*/
|
||||
`;
|
||||
}
|
||||
33
packages/svelte/src/Icon.svelte
Normal file
33
packages/svelte/src/Icon.svelte
Normal file
@@ -0,0 +1,33 @@
|
||||
<script lang="ts">
|
||||
import defaultAttributes from './defaultAttributes';
|
||||
import type { IconProps } from './types';
|
||||
|
||||
const {
|
||||
name,
|
||||
color = 'currentColor',
|
||||
size = 24,
|
||||
strokeWidth = 2,
|
||||
absoluteStrokeWidth = false,
|
||||
iconNode = [],
|
||||
children,
|
||||
...props
|
||||
}: IconProps = $props();
|
||||
</script>
|
||||
|
||||
<svg
|
||||
{...defaultAttributes}
|
||||
{...props}
|
||||
width={size}
|
||||
height={size}
|
||||
stroke={color}
|
||||
stroke-width={absoluteStrokeWidth ? (Number(strokeWidth) * 24) / Number(size) : strokeWidth}
|
||||
class={['lucide-icon lucide', name && `lucide-${name}`, props.class]}
|
||||
>
|
||||
{#each iconNode as [tag, attrs]}
|
||||
<svelte:element
|
||||
this={tag}
|
||||
{...attrs}
|
||||
/>
|
||||
{/each}
|
||||
{@render children?.()}
|
||||
</svg>
|
||||
3
packages/svelte/src/aliases/index.ts
Normal file
3
packages/svelte/src/aliases/index.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
export * from './aliases';
|
||||
export * from './prefixed';
|
||||
export * from './suffixed';
|
||||
15
packages/svelte/src/defaultAttributes.ts
Normal file
15
packages/svelte/src/defaultAttributes.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
import type { Attrs } from './types.js';
|
||||
|
||||
const defaultAttributes: Attrs = {
|
||||
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;
|
||||
1
packages/svelte/src/icons/.gitkeep
Normal file
1
packages/svelte/src/icons/.gitkeep
Normal file
@@ -0,0 +1 @@
|
||||
Folder for generated icons
|
||||
6
packages/svelte/src/lucide-svelte.ts
Normal file
6
packages/svelte/src/lucide-svelte.ts
Normal file
@@ -0,0 +1,6 @@
|
||||
export * from './icons/index';
|
||||
export * as icons from './icons/index';
|
||||
export * from './aliases';
|
||||
export { default as defaultAttributes } from './defaultAttributes';
|
||||
export * from './types';
|
||||
export { default as Icon } from './Icon.svelte';
|
||||
24
packages/svelte/src/types.ts
Normal file
24
packages/svelte/src/types.ts
Normal file
@@ -0,0 +1,24 @@
|
||||
import type { SVGAttributes, SvelteHTMLElements } from 'svelte/elements';
|
||||
import type { Snippet } from 'svelte';
|
||||
|
||||
export type Attrs = SVGAttributes<SVGSVGElement>;
|
||||
|
||||
export type IconNode = [elementName: keyof SvelteHTMLElements, attrs: Attrs][];
|
||||
|
||||
export interface IconProps extends Attrs {
|
||||
name?: string;
|
||||
color?: string;
|
||||
size?: number | string;
|
||||
strokeWidth?: number | string;
|
||||
absoluteStrokeWidth?: boolean;
|
||||
iconNode?: IconNode;
|
||||
children?: Snippet;
|
||||
}
|
||||
|
||||
export type IconEvents = {
|
||||
[evt: string]: CustomEvent<any>;
|
||||
};
|
||||
|
||||
export type IconSlots = {
|
||||
default: {};
|
||||
};
|
||||
8
packages/svelte/svelte.config.js
Normal file
8
packages/svelte/svelte.config.js
Normal file
@@ -0,0 +1,8 @@
|
||||
// eslint-disable-next-line import/no-extraneous-dependencies
|
||||
import sveltePreprocess from 'svelte-preprocess';
|
||||
|
||||
export default {
|
||||
preprocess: sveltePreprocess({
|
||||
typescript: true,
|
||||
}),
|
||||
};
|
||||
33
packages/svelte/tests/Icon.spec.ts
Normal file
33
packages/svelte/tests/Icon.spec.ts
Normal file
@@ -0,0 +1,33 @@
|
||||
import { describe, it, expect } from 'vitest';
|
||||
import { render } from '@testing-library/svelte';
|
||||
import { Icon } from '../src/lucide-svelte';
|
||||
|
||||
import { airVent } from './testIconNodes';
|
||||
|
||||
describe('Using Icon Component', () => {
|
||||
it('should render icon based on a iconNode', async () => {
|
||||
const { container } = render(Icon, {
|
||||
props: {
|
||||
iconNode: airVent,
|
||||
size: 48,
|
||||
color: 'red',
|
||||
absoluteStrokeWidth: true,
|
||||
},
|
||||
});
|
||||
|
||||
expect(container.firstChild).toBeDefined();
|
||||
});
|
||||
|
||||
it('should render icon and match snapshot', async () => {
|
||||
const { container } = render(Icon, {
|
||||
props: {
|
||||
iconNode: airVent,
|
||||
size: 48,
|
||||
color: 'red',
|
||||
absoluteStrokeWidth: true,
|
||||
},
|
||||
});
|
||||
|
||||
expect(container.firstChild).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
7
packages/svelte/tests/TestSlots.svelte
Normal file
7
packages/svelte/tests/TestSlots.svelte
Normal file
@@ -0,0 +1,7 @@
|
||||
<script lang="ts">
|
||||
import Smile from '../src/icons/smile.svelte'
|
||||
</script>
|
||||
|
||||
<Smile>
|
||||
<text>Test</text>
|
||||
</Smile>
|
||||
47
packages/svelte/tests/__snapshots__/Icon.spec.ts.snap
Normal file
47
packages/svelte/tests/__snapshots__/Icon.spec.ts.snap
Normal file
@@ -0,0 +1,47 @@
|
||||
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
|
||||
|
||||
exports[`Using Icon Component > should render icon and match snapshot 1`] = `
|
||||
<svg
|
||||
class="lucide-icon lucide"
|
||||
fill="none"
|
||||
height="48"
|
||||
stroke="red"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="1"
|
||||
viewBox="0 0 24 24"
|
||||
width="48"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<!---->
|
||||
<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>
|
||||
|
||||
<!---->
|
||||
<path
|
||||
d="M6 8h12"
|
||||
>
|
||||
|
||||
</path>
|
||||
|
||||
<!---->
|
||||
<path
|
||||
d="M18.3 17.7a2.5 2.5 0 0 1-3.16 3.83 2.53 2.53 0 0 1-1.14-2V12"
|
||||
>
|
||||
|
||||
</path>
|
||||
|
||||
<!---->
|
||||
<path
|
||||
d="M6.6 15.6A2 2 0 1 0 10 17v-5"
|
||||
>
|
||||
|
||||
</path>
|
||||
|
||||
<!---->
|
||||
<!---->
|
||||
</svg>
|
||||
`;
|
||||
272
packages/svelte/tests/__snapshots__/lucide-svelte.spec.ts.snap
Normal file
272
packages/svelte/tests/__snapshots__/lucide-svelte.spec.ts.snap
Normal file
@@ -0,0 +1,272 @@
|
||||
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
|
||||
|
||||
exports[`Using lucide icon components > should add a class to the element 1`] = `
|
||||
<svg
|
||||
class="lucide-icon lucide lucide-smile my-icon"
|
||||
fill="none"
|
||||
height="24"
|
||||
stroke="currentColor"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
viewBox="0 0 24 24"
|
||||
width="24"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<!---->
|
||||
<circle
|
||||
cx="12"
|
||||
cy="12"
|
||||
r="10"
|
||||
>
|
||||
|
||||
</circle>
|
||||
|
||||
<!---->
|
||||
<path
|
||||
d="M8 14s1.5 2 4 2 4-2 4-2"
|
||||
>
|
||||
|
||||
</path>
|
||||
|
||||
<!---->
|
||||
<line
|
||||
x1="9"
|
||||
x2="9.01"
|
||||
y1="9"
|
||||
y2="9"
|
||||
>
|
||||
|
||||
</line>
|
||||
|
||||
<!---->
|
||||
<line
|
||||
x1="15"
|
||||
x2="15.01"
|
||||
y1="9"
|
||||
y2="9"
|
||||
>
|
||||
|
||||
</line>
|
||||
|
||||
<!---->
|
||||
<!---->
|
||||
|
||||
<!---->
|
||||
</svg>
|
||||
`;
|
||||
|
||||
exports[`Using lucide icon components > should adjust the size, stroke color and stroke width 1`] = `
|
||||
<div>
|
||||
<svg
|
||||
class="lucide-icon lucide lucide-smile"
|
||||
fill="none"
|
||||
height="48"
|
||||
stroke="red"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="4"
|
||||
viewBox="0 0 24 24"
|
||||
width="48"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<!---->
|
||||
<circle
|
||||
cx="12"
|
||||
cy="12"
|
||||
r="10"
|
||||
>
|
||||
|
||||
</circle>
|
||||
|
||||
<!---->
|
||||
<path
|
||||
d="M8 14s1.5 2 4 2 4-2 4-2"
|
||||
>
|
||||
|
||||
</path>
|
||||
|
||||
<!---->
|
||||
<line
|
||||
x1="9"
|
||||
x2="9.01"
|
||||
y1="9"
|
||||
y2="9"
|
||||
>
|
||||
|
||||
</line>
|
||||
|
||||
<!---->
|
||||
<line
|
||||
x1="15"
|
||||
x2="15.01"
|
||||
y1="9"
|
||||
y2="9"
|
||||
>
|
||||
|
||||
</line>
|
||||
|
||||
<!---->
|
||||
<!---->
|
||||
|
||||
<!---->
|
||||
</svg>
|
||||
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`Using lucide icon components > should not 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"
|
||||
data-testid="smile-icon"
|
||||
class="lucide-icon lucide lucide-smile"
|
||||
>
|
||||
<circle cx="12"
|
||||
cy="12"
|
||||
r="10"
|
||||
>
|
||||
</circle>
|
||||
<path d="M8 14s1.5 2 4 2 4-2 4-2">
|
||||
</path>
|
||||
<line x1="9"
|
||||
x2="9.01"
|
||||
y1="9"
|
||||
y2="9"
|
||||
>
|
||||
</line>
|
||||
<line x1="15"
|
||||
x2="15.01"
|
||||
y1="9"
|
||||
y2="9"
|
||||
>
|
||||
</line>
|
||||
</svg>
|
||||
`;
|
||||
|
||||
exports[`Using lucide icon components > should render an component 1`] = `
|
||||
<div>
|
||||
<svg
|
||||
class="lucide-icon lucide lucide-smile"
|
||||
fill="none"
|
||||
height="24"
|
||||
stroke="currentColor"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
viewBox="0 0 24 24"
|
||||
width="24"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<!---->
|
||||
<circle
|
||||
cx="12"
|
||||
cy="12"
|
||||
r="10"
|
||||
>
|
||||
|
||||
</circle>
|
||||
|
||||
<!---->
|
||||
<path
|
||||
d="M8 14s1.5 2 4 2 4-2 4-2"
|
||||
>
|
||||
|
||||
</path>
|
||||
|
||||
<!---->
|
||||
<line
|
||||
x1="9"
|
||||
x2="9.01"
|
||||
y1="9"
|
||||
y2="9"
|
||||
>
|
||||
|
||||
</line>
|
||||
|
||||
<!---->
|
||||
<line
|
||||
x1="15"
|
||||
x2="15.01"
|
||||
y1="9"
|
||||
y2="9"
|
||||
>
|
||||
|
||||
</line>
|
||||
|
||||
<!---->
|
||||
<!---->
|
||||
|
||||
<!---->
|
||||
</svg>
|
||||
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`Using lucide icon components > should render an icon slot 1`] = `
|
||||
<div>
|
||||
<svg
|
||||
class="lucide-icon lucide lucide-smile"
|
||||
fill="none"
|
||||
height="24"
|
||||
stroke="currentColor"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
viewBox="0 0 24 24"
|
||||
width="24"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<!---->
|
||||
<circle
|
||||
cx="12"
|
||||
cy="12"
|
||||
r="10"
|
||||
>
|
||||
|
||||
</circle>
|
||||
|
||||
<!---->
|
||||
<path
|
||||
d="M8 14s1.5 2 4 2 4-2 4-2"
|
||||
>
|
||||
|
||||
</path>
|
||||
|
||||
<!---->
|
||||
<line
|
||||
x1="9"
|
||||
x2="9.01"
|
||||
y1="9"
|
||||
y2="9"
|
||||
>
|
||||
|
||||
</line>
|
||||
|
||||
<!---->
|
||||
<line
|
||||
x1="15"
|
||||
x2="15.01"
|
||||
y1="9"
|
||||
y2="9"
|
||||
>
|
||||
|
||||
</line>
|
||||
|
||||
<!---->
|
||||
<!---->
|
||||
<text>
|
||||
Test
|
||||
</text>
|
||||
|
||||
<!---->
|
||||
</svg>
|
||||
|
||||
</div>
|
||||
`;
|
||||
92
packages/svelte/tests/lucide-svelte.spec.ts
Normal file
92
packages/svelte/tests/lucide-svelte.spec.ts
Normal file
@@ -0,0 +1,92 @@
|
||||
import { describe, it, expect, afterEach } from 'vitest';
|
||||
import { render, cleanup } from '@testing-library/svelte';
|
||||
import { Smile, Pen, Edit2 } from '../src/lucide-svelte';
|
||||
import TestSlots from './TestSlots.svelte';
|
||||
|
||||
describe('Using lucide icon components', () => {
|
||||
afterEach(() => cleanup());
|
||||
it('should render an component', () => {
|
||||
const { container } = render(Smile);
|
||||
expect(container).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should adjust the size, stroke color and stroke width', () => {
|
||||
const { container } = render(Smile, {
|
||||
props: {
|
||||
size: 48,
|
||||
color: 'red',
|
||||
strokeWidth: 4,
|
||||
},
|
||||
});
|
||||
|
||||
expect(container).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should add a class to the element', () => {
|
||||
const testClass = 'my-icon';
|
||||
render(Smile, {
|
||||
props: {
|
||||
class: testClass,
|
||||
},
|
||||
});
|
||||
|
||||
const [icon] = document.getElementsByClassName(testClass);
|
||||
|
||||
expect(icon).toBeInTheDocument();
|
||||
expect(icon).toMatchSnapshot();
|
||||
expect(icon).toHaveClass(testClass);
|
||||
expect(icon).toHaveClass('lucide');
|
||||
expect(icon).toHaveClass('lucide-smile');
|
||||
});
|
||||
|
||||
it('should add a style attribute to the element', () => {
|
||||
render(Smile, {
|
||||
props: {
|
||||
style: 'position: absolute;',
|
||||
},
|
||||
});
|
||||
const [icon] = document.getElementsByClassName('lucide');
|
||||
|
||||
expect(icon.getAttribute('style')).toContain('position: absolute');
|
||||
});
|
||||
|
||||
it('should render an icon slot', () => {
|
||||
const { container, getByText } = render(TestSlots);
|
||||
|
||||
const textElement = getByText('Test');
|
||||
expect(textElement).toBeInTheDocument();
|
||||
expect(container).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should render the alias icon', () => {
|
||||
const { container } = render(Pen);
|
||||
|
||||
const PenIconRenderedHTML = container.innerHTML;
|
||||
|
||||
cleanup();
|
||||
|
||||
const { container: Edit2Container } = render(Edit2);
|
||||
|
||||
expect(PenIconRenderedHTML).toBe(Edit2Container.innerHTML);
|
||||
});
|
||||
|
||||
it('should not scale the strokeWidth when absoluteStrokeWidth is set', () => {
|
||||
const testId = 'smile-icon';
|
||||
const { container, getByTestId } = render(Smile, {
|
||||
'data-testid': testId,
|
||||
color: 'red',
|
||||
size: 48,
|
||||
absoluteStrokeWidth: true,
|
||||
});
|
||||
|
||||
const { attributes } = getByTestId(testId) as unknown as {
|
||||
attributes: Record<string, { value: string }>;
|
||||
};
|
||||
expect(attributes.stroke.value).toBe('red');
|
||||
expect(attributes.width.value).toBe('48');
|
||||
expect(attributes.height.value).toBe('48');
|
||||
expect(attributes['stroke-width'].value).toBe('1');
|
||||
|
||||
expect(container.innerHTML).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
5
packages/svelte/tests/setupVitest.ts
Normal file
5
packages/svelte/tests/setupVitest.ts
Normal file
@@ -0,0 +1,5 @@
|
||||
import { expect } from 'vitest';
|
||||
import '@testing-library/jest-dom/vitest';
|
||||
import htmlSerializer from 'jest-serializer-html';
|
||||
|
||||
expect.addSnapshotSerializer(htmlSerializer);
|
||||
21
packages/svelte/tests/testIconNodes.ts
Normal file
21
packages/svelte/tests/testIconNodes.ts
Normal file
@@ -0,0 +1,21 @@
|
||||
import type { IconNode } from '../src/lucide-svelte';
|
||||
|
||||
export const airVent: IconNode = [
|
||||
[
|
||||
'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', { d: 'M6 8h12' }],
|
||||
['path', { d: 'M18.3 17.7a2.5 2.5 0 0 1-3.16 3.83 2.53 2.53 0 0 1-1.14-2V12' }],
|
||||
['path', { d: 'M6.6 15.6A2 2 0 1 0 10 17v-5' }],
|
||||
];
|
||||
|
||||
export const coffee: IconNode = [
|
||||
['path', { d: 'M17 8h1a4 4 0 1 1 0 8h-1' }],
|
||||
['path', { d: 'M3 8h14v9a4 4 0 0 1-4 4H7a4 4 0 0 1-4-4Z' }],
|
||||
['line', { x1: '6', x2: '6', y1: '2', y2: '4' }],
|
||||
['line', { x1: '10', x2: '10', y1: '2', y2: '4' }],
|
||||
['line', { x1: '14', x2: '14', y1: '2', y2: '4' }],
|
||||
];
|
||||
14
packages/svelte/tsconfig.json
Normal file
14
packages/svelte/tsconfig.json
Normal file
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"extends": "@tsconfig/svelte/tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"target": "ESNext",
|
||||
"useDefineForClassFields": true,
|
||||
"module": "ESNext",
|
||||
"resolveJsonModule": true,
|
||||
"allowJs": true,
|
||||
"checkJs": true,
|
||||
"isolatedModules": true,
|
||||
"types": ["@testing-library/jest-dom"],
|
||||
},
|
||||
"include": ["src/**/*.d.ts", "src/**/*.ts", "src/**/*.js", "src/**/*.svelte", "tests/**/*.ts"],
|
||||
}
|
||||
19
packages/svelte/vitest.config.ts
Normal file
19
packages/svelte/vitest.config.ts
Normal file
@@ -0,0 +1,19 @@
|
||||
import { svelte } from '@sveltejs/vite-plugin-svelte';
|
||||
import { defineConfig } from 'vitest/config';
|
||||
|
||||
// @ts-expect-error - type mismatch
|
||||
export default defineConfig(({ mode }) => ({
|
||||
plugins: [
|
||||
svelte({
|
||||
compilerOptions: { hmr: false },
|
||||
}),
|
||||
],
|
||||
resolve: {
|
||||
conditions: mode === 'test' ? ['browser'] : [],
|
||||
},
|
||||
test: {
|
||||
globals: true,
|
||||
environment: 'jsdom',
|
||||
setupFiles: './tests/setupVitest.ts',
|
||||
},
|
||||
}));
|
||||
2581
pnpm-lock.yaml
generated
2581
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
@@ -18,7 +18,7 @@ function pascalToKebabNextJSFlavour(str) {
|
||||
const currentDir = getCurrentDirPath(import.meta.url);
|
||||
const ICONS_DIR = path.resolve(currentDir, '../icons');
|
||||
|
||||
const svgFiles = readSvgDirectory(ICONS_DIR);
|
||||
const svgFiles = await readSvgDirectory(ICONS_DIR);
|
||||
|
||||
const iconNames = svgFiles.map((icon) => icon.split('.')[0]).reverse();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user