Add Svelte 5 (Runes) icon package (#1434)
Introduced the @tabler/icons-svelte-runes package for Svelte 5+ with runes reactivity, including source, build, tests, and documentation. Updated issue templates, labeler, and README to reference the new package and distinguish between Svelte 4 and Svelte 5 usage. Adjusted build scripts and lockfile to support the new package.
This commit is contained in:
parent
48280d7eb6
commit
0678fad12c
|
|
@ -31,6 +31,7 @@ body:
|
|||
- label: "@tabler/icons-react-native"
|
||||
- label: "@tabler/icons-solid"
|
||||
- label: "@tabler/icons-svelte"
|
||||
- label: "@tabler/icons-svelte-runes"
|
||||
- label: "@tabler/icons-vue"
|
||||
- label: Figma plugin
|
||||
- label: source/main
|
||||
|
|
|
|||
|
|
@ -38,12 +38,18 @@
|
|||
- any-glob-to-any-file:
|
||||
- 'packages/icons-preact/*'
|
||||
|
||||
# For Svelte package
|
||||
# For Svelte 4 and below package
|
||||
🔗 svelte package:
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- 'packages/icons-svelte/*'
|
||||
|
||||
# For Svelte 5 package
|
||||
🔗 svelte-runes package:
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- 'packages/icons-svelte-runes/*'
|
||||
|
||||
# For SolidJS package
|
||||
🔗 solid package:
|
||||
- changed-files:
|
||||
|
|
|
|||
17
README.md
17
README.md
|
|
@ -232,7 +232,7 @@ After importing the _IconsModule_ in your feature or shared module, use the icon
|
|||
|
||||
For more usage documentation refer to [the official documentation](https://github.com/pierreavn/angular-tabler-icons).
|
||||
|
||||
### Svelte
|
||||
### Svelte 4 and below
|
||||
|
||||
Svelte components available through [`@tabler/icons-svelte`](https://github.com/tabler/tabler-icons/tree/master/packages/icons-svelte) package.
|
||||
|
||||
|
|
@ -248,6 +248,21 @@ Svelte components available through [`@tabler/icons-svelte`](https://github.com/
|
|||
</main>
|
||||
```
|
||||
|
||||
### Svelte 5
|
||||
Svelte 5 components available through [`@tabler/icons-svelte-runes`](https://www.npmjs.com/package/@tabler/icons-svelte-runes) package.
|
||||
|
||||
```js
|
||||
<script lang="ts">
|
||||
import { IconHeart } from '@tabler/icons-svelte-runes';
|
||||
</script>
|
||||
|
||||
<main>
|
||||
<IconHeart size={48} stroke={1} />
|
||||
<IconHeart size="32" stroke={1.5} />
|
||||
<IconHeart color="crimson" class="p-1" size="96" stroke="2" />
|
||||
</main>
|
||||
```
|
||||
|
||||
## CDN
|
||||
|
||||
All files included in `@tabler/icons` npm package are available over a CDN.
|
||||
|
|
|
|||
|
|
@ -0,0 +1,40 @@
|
|||
---
|
||||
title: Tabler Icons for Svelte 5
|
||||
---
|
||||
|
||||

|
||||
|
||||
## Installation
|
||||
|
||||
<TabsPackage name="@tabler/icons-svelte-runes" />
|
||||
|
||||
or just [download from Github](https://github.com/tabler/tabler-icons/releases).
|
||||
|
||||
## How to use
|
||||
|
||||
It's build with ESmodules so it's completely tree-shakable. Each icon can be imported as a component.
|
||||
|
||||
```sveltehtml
|
||||
<script lang="ts">
|
||||
import { IconHeart } from '@tabler/icons-svelte-runes';
|
||||
</script>
|
||||
|
||||
<main>
|
||||
<IconHeart />
|
||||
</main>
|
||||
```
|
||||
|
||||
You can pass additional props to adjust the icon.
|
||||
|
||||
```html
|
||||
<IconHeart size={48} stroke={1} />
|
||||
```
|
||||
|
||||
### Props
|
||||
|
||||
| name | type | default |
|
||||
| ------------- | -------- | ------------ |
|
||||
| `size` | _Number_ | 24 |
|
||||
| `color` | _String_ | currentColor |
|
||||
| `stroke` | _Number_ | 2 |
|
||||
| `class` | _String_ | |
|
||||
|
|
@ -33,13 +33,14 @@
|
|||
"validate": "node ./.build/validate-icons.mjs",
|
||||
"release": "git pull && release-it --verbose",
|
||||
"build:copy": "rm -rf ./icons && mkdir ./icons && cp ./_site/tags.json tags.json && cp ./_site/icons/* ./icons/ && rm -rf ./_site/",
|
||||
"build:packages": "pnpm run build:icons && pnpm run build:sprite && pnpm run build:react && pnpm run build:react-native && pnpm run build:preact && pnpm run build:solidjs && pnpm run build:svelte && pnpm run build:vue && pnpm run build:png && pnpm run build:pdf && pnpm run build:esp && pnpm run build:webfont",
|
||||
"build:packages": "pnpm run build:icons && pnpm run build:sprite && pnpm run build:react && pnpm run build:react-native && pnpm run build:preact && pnpm run build:solidjs && pnpm run build:svelte && pnpm run build:svelte-runes && pnpm run build:vue && pnpm run build:png && pnpm run build:pdf && pnpm run build:esp && pnpm run build:webfont",
|
||||
"build:icons": "pnpm --filter @tabler/icons build",
|
||||
"build:react": "pnpm --filter @tabler/icons-react build",
|
||||
"build:react-native": "pnpm --filter @tabler/icons-react-native build",
|
||||
"build:preact": "pnpm --filter @tabler/icons-preact build",
|
||||
"build:solidjs": "pnpm --filter @tabler/icons-solidjs build",
|
||||
"build:svelte": "pnpm --filter @tabler/icons-svelte build",
|
||||
"build:svelte-runes": "pnpm --filter @tabler/icons-svelte-runes build",
|
||||
"build:vue": "pnpm --filter @tabler/icons-vue build",
|
||||
"build:png": "pnpm --filter @tabler/icons-png build",
|
||||
"build:pdf": "pnpm --filter @tabler/icons-pdf build",
|
||||
|
|
|
|||
|
|
@ -0,0 +1,4 @@
|
|||
src/icons/*.svelte
|
||||
.svelte-kit
|
||||
src/aliases.ts
|
||||
src/icons-list.ts
|
||||
|
|
@ -0,0 +1,207 @@
|
|||
# Tabler Icons for Svelte (Runes)
|
||||
|
||||
<p align="center">
|
||||
<img src="https://raw.githubusercontent.com/tabler/tabler-icons/main/.github/packages/og-package-svelte.png" alt="Tabler Icons" width="838">
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
Implementation of the Tabler Icons library for Svelte 5+ using the new runes reactivity system.
|
||||
<p>
|
||||
|
||||
<p align="center">
|
||||
<a href="https://tabler-icons.io/"><strong>Browse all icons at tabler-icons.io →</strong></a>
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
<a href="https://github.com/tabler/tabler-icons/releases"><img src="https://img.shields.io/npm/v/@tabler/icons-svelte-runes" alt="Latest Release"></a>
|
||||
<a href="https://github.com/tabler/tabler-icons/blob/master/LICENSE"><img src="https://img.shields.io/npm/l/@tabler/icons.svg" alt="License"></a>
|
||||
</p>
|
||||
|
||||
## Why This Package?
|
||||
|
||||
This package is specifically built for **Svelte 5+** using the new **runes** reactivity system (`$props()`, `$derived`, etc.).
|
||||
|
||||
- **For Svelte 5+ projects:** Use this package (`@tabler/icons-svelte-runes`)
|
||||
- **For Svelte 3/4 projects:** Use [`@tabler/icons-svelte`](https://www.npmjs.com/package/@tabler/icons-svelte)
|
||||
|
||||
## Installation
|
||||
|
||||
```bash
|
||||
pnpm add @tabler/icons-svelte-runes
|
||||
```
|
||||
|
||||
or
|
||||
|
||||
```bash
|
||||
npm install @tabler/icons-svelte-runes
|
||||
```
|
||||
|
||||
or
|
||||
|
||||
```bash
|
||||
yarn add @tabler/icons-svelte-runes
|
||||
```
|
||||
|
||||
## Requirements
|
||||
|
||||
- **Svelte 5.0+** with runes enabled
|
||||
- For older Svelte versions, use `@tabler/icons-svelte` instead
|
||||
|
||||
## Usage
|
||||
|
||||
It's built with ES modules so it's completely tree-shakable. Each icon can be imported as a component.
|
||||
|
||||
```svelte
|
||||
<script lang="ts">
|
||||
import { IconHeart } from '@tabler/icons-svelte-runes';
|
||||
</script>
|
||||
|
||||
<IconHeart />
|
||||
```
|
||||
|
||||
You can pass additional props to adjust the icon:
|
||||
|
||||
```svelte
|
||||
<IconHeart size={48} stroke={1} color="red" />
|
||||
```
|
||||
|
||||
### Props
|
||||
|
||||
| name | type | default |
|
||||
| -------- | ------------------ | ------------ |
|
||||
| `size` | `number \| string` | 24 |
|
||||
| `color` | `string` | currentColor |
|
||||
| `stroke` | `number \| string` | 2 |
|
||||
| `class` | `string` | '' |
|
||||
|
||||
All other HTML attributes are forwarded to the SVG element.
|
||||
|
||||
## TypeScript Support
|
||||
|
||||
The package includes full TypeScript definitions. Icons are typed as Svelte 5 `Component<IconProps>`:
|
||||
|
||||
```typescript
|
||||
import type { Icon } from '@tabler/icons-svelte-runes';
|
||||
import { IconHeart } from '@tabler/icons-svelte-runes';
|
||||
|
||||
// Icon is compatible with Svelte 5's Component type
|
||||
const MyIcon: Icon = IconHeart;
|
||||
```
|
||||
|
||||
### Using Icons in Props
|
||||
|
||||
When passing icons as props, use the `Component` type or `any` for maximum compatibility:
|
||||
|
||||
```svelte
|
||||
<script lang="ts">
|
||||
import type { Component } from 'svelte';
|
||||
import { IconHeart } from '@tabler/icons-svelte-runes';
|
||||
|
||||
interface Props {
|
||||
icon: Component<any>;
|
||||
label: string;
|
||||
}
|
||||
|
||||
let { icon: Icon, label }: Props = $props();
|
||||
</script>
|
||||
|
||||
<button>
|
||||
<Icon size={20} />
|
||||
{label}
|
||||
</button>
|
||||
```
|
||||
|
||||
## Examples
|
||||
|
||||
### Basic Icon Usage
|
||||
|
||||
```svelte
|
||||
<script lang="ts">
|
||||
import { IconHeart, IconStar, IconHome } from '@tabler/icons-svelte-runes';
|
||||
</script>
|
||||
|
||||
<IconHeart />
|
||||
<IconStar size={32} color="gold" />
|
||||
<IconHome stroke={1.5} class="my-icon" />
|
||||
```
|
||||
|
||||
### Dynamic Icons with Runes
|
||||
|
||||
```svelte
|
||||
<script lang="ts">
|
||||
import { IconHeart, IconStar, IconCircle } from '@tabler/icons-svelte-runes';
|
||||
|
||||
const icons = {
|
||||
heart: IconHeart,
|
||||
star: IconStar,
|
||||
circle: IconCircle
|
||||
};
|
||||
|
||||
let selected = $state('heart');
|
||||
let DynamicIcon = $derived(icons[selected]);
|
||||
</script>
|
||||
|
||||
<DynamicIcon size={32} />
|
||||
|
||||
<button onclick={() => selected = 'heart'}>Heart</button>
|
||||
<button onclick={() => selected = 'star'}>Star</button>
|
||||
<button onclick={() => selected = 'circle'}>Circle</button>
|
||||
```
|
||||
|
||||
### Reactive Size with $derived
|
||||
|
||||
```svelte
|
||||
<script lang="ts">
|
||||
import { IconHeart } from '@tabler/icons-svelte-runes';
|
||||
|
||||
let isLarge = $state(false);
|
||||
let iconSize = $derived(isLarge ? 48 : 24);
|
||||
</script>
|
||||
|
||||
<IconHeart size={iconSize} />
|
||||
<button onclick={() => isLarge = !isLarge}>Toggle Size</button>
|
||||
```
|
||||
|
||||
## Migrating from @tabler/icons-svelte
|
||||
|
||||
The API is identical, just change the package name:
|
||||
|
||||
```diff
|
||||
- import { IconHeart } from '@tabler/icons-svelte';
|
||||
+ import { IconHeart } from '@tabler/icons-svelte-runes';
|
||||
```
|
||||
|
||||
No other changes needed! Your existing props and usage remain the same.
|
||||
|
||||
## What's Different from @tabler/icons-svelte?
|
||||
|
||||
Internally, this package uses Svelte 5's new features:
|
||||
|
||||
- `$props()` instead of `export let`
|
||||
- `$derived` for computed values
|
||||
- Modern TypeScript `Component` type
|
||||
- Optimized for Svelte 5's fine-grained reactivity
|
||||
|
||||
**Result:** Better performance and smaller bundle sizes in Svelte 5 projects!
|
||||
|
||||
## Sponsors
|
||||
|
||||
**If you want to support this project, you can [become a sponsor on GitHub](https://github.com/sponsors/codecalm) or just [donate on PayPal](https://paypal.me/codecalm) :)**
|
||||
|
||||
<a href="https://github.com/sponsors/codecalm">
|
||||
<img src="https://cdn.jsdelivr.net/gh/tabler/sponsors@latest/sponsors.svg" alt="Tabler sponsors">
|
||||
</a>
|
||||
|
||||
## Contributing
|
||||
|
||||
For more info on how to contribute please see the [contribution guidelines](https://github.com/tabler/tabler-icons/blob/main/CONTRIBUTING.md).
|
||||
|
||||
Caught a mistake or want to contribute to the documentation? [Edit this page on Github](https://github.com/tabler/tabler-icons/blob/main/packages/icons-svelte-runes/README.md)
|
||||
|
||||
## License
|
||||
|
||||
Tabler Icons is licensed under the [MIT License](https://github.com/tabler/tabler-icons/blob/master/LICENSE).
|
||||
|
||||
## Sponsor Tabler
|
||||
|
||||
<a href="https://github.com/sponsors/codecalm" target="_blank"><img src="https://github.com/tabler/tabler/raw/dev/src/static/sponsor-banner-readme.png?raw=true" alt="Sponsor Tabler" /></a>
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
#!/usr/bin/env node
|
||||
|
||||
import { buildJsIcons, buildIconsList } from '../../.build/build-icons.mjs';
|
||||
|
||||
const componentTemplate = ({ type, name, children, stringify }) => {
|
||||
return `\
|
||||
<script lang="ts">
|
||||
import Icon from '../Icon.svelte';
|
||||
import type { IconNode, IconProps } from '../types.js';
|
||||
import type { Snippet } from 'svelte';
|
||||
|
||||
interface Props extends IconProps {
|
||||
children?: Snippet;
|
||||
}
|
||||
|
||||
let { children, ...props }: Props = $props();
|
||||
|
||||
const iconNode: IconNode = ${JSON.stringify(children)};
|
||||
</script>
|
||||
<Icon type="${type}" name="${name}" {...props} iconNode={iconNode} {children} />
|
||||
`;
|
||||
};
|
||||
|
||||
const aliasTemplate = ({ fromPascal, to }) =>
|
||||
`export { default as Icon${fromPascal} } from './icons/${to}.svelte';\n`;
|
||||
|
||||
const indexItemTemplate = ({ name, namePascal }) =>
|
||||
`export { default as Icon${namePascal} } from './${name}.svelte';`;
|
||||
|
||||
buildJsIcons({
|
||||
name: 'icons-svelte-runes',
|
||||
componentTemplate,
|
||||
indexItemTemplate,
|
||||
aliasTemplate,
|
||||
extension: 'svelte',
|
||||
key: false,
|
||||
indexFile: 'index.ts',
|
||||
pascalName: false,
|
||||
});
|
||||
|
||||
buildIconsList('icons-svelte-runes');
|
||||
|
|
@ -0,0 +1,83 @@
|
|||
{
|
||||
"name": "@tabler/icons-svelte-runes",
|
||||
"version": "1.0.0",
|
||||
"license": "MIT",
|
||||
"author": "codecalm",
|
||||
"description": "A set of free MIT-licensed high-quality SVG icons for Svelte 5+ using runes",
|
||||
"homepage": "https://tabler-icons.io",
|
||||
"bugs": {
|
||||
"url": "https://github.com/tabler/tabler-icons/issues"
|
||||
},
|
||||
"funding": {
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/codecalm"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/tabler/tabler-icons.git",
|
||||
"directory": "packages/icons-svelte-runes"
|
||||
},
|
||||
"svelte": "./dist/tabler-icons-svelte-runes.js",
|
||||
"types": "./dist/tabler-icons-svelte-runes.d.ts",
|
||||
"type": "module",
|
||||
"amdName": "TablerIconsSvelteRunes",
|
||||
"exports": {
|
||||
".": {
|
||||
"types": "./dist/tabler-icons-svelte-runes.d.ts",
|
||||
"svelte": "./dist/tabler-icons-svelte-runes.js",
|
||||
"default": "./dist/tabler-icons-svelte-runes.js"
|
||||
},
|
||||
"./icons": {
|
||||
"types": "./dist/tabler-icons-svelte-runes.d.ts",
|
||||
"svelte": "./dist/tabler-icons-svelte-runes.js"
|
||||
},
|
||||
"./icons/*": {
|
||||
"types": "./dist/icons/*.svelte.d.ts",
|
||||
"svelte": "./dist/icons/*.svelte"
|
||||
}
|
||||
},
|
||||
"sideEffects": false,
|
||||
"files": [
|
||||
"dist"
|
||||
],
|
||||
"keywords": [
|
||||
"svelte",
|
||||
"svelte5",
|
||||
"runes",
|
||||
"icons",
|
||||
"svg",
|
||||
"tabler",
|
||||
"tabler-icons",
|
||||
"svelte-runes",
|
||||
"ui"
|
||||
],
|
||||
"scripts": {
|
||||
"build": "pnpm run clean && pnpm run copy:license && pnpm run build:icons && pnpm run build:package",
|
||||
"build:icons": "node build.mjs",
|
||||
"build:package": "svelte-package --input ./src",
|
||||
"copy:license": "cp ../../LICENSE ./LICENSE",
|
||||
"clean": "rm -rf dist && find . ! -name '.gitkeep' -path '*/src/icons/*' -exec rm -rf {} +",
|
||||
"test": "vitest run",
|
||||
"imports-check": "attw $(npm pack)"
|
||||
},
|
||||
"dependencies": {
|
||||
"@tabler/icons": "3.35.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@sveltejs/package": "^2.3.7",
|
||||
"@sveltejs/vite-plugin-svelte": "^5.0.3",
|
||||
"@testing-library/jest-dom": "^6.6.3",
|
||||
"@testing-library/svelte": "^5.2.9",
|
||||
"@tsconfig/svelte": "^5.0.4",
|
||||
"jest-serializer-html": "^7.1.0",
|
||||
"jsdom": "^25.0.1",
|
||||
"svelte": "^5.0.0",
|
||||
"svelte-check": "^4.3.4",
|
||||
"typescript": "^5.7.3",
|
||||
"vite": "^7.2.7",
|
||||
"vitest": "^3.0.8"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"svelte": "^5.0.0"
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
import { expect } from 'vitest';
|
||||
import * as matchers from '@testing-library/jest-dom/matchers';
|
||||
import htmlSerializer from 'jest-serializer-html';
|
||||
|
||||
// Extend Vitest's expect with jest-dom matchers
|
||||
expect.extend(matchers);
|
||||
|
||||
// Add HTML serializer for snapshots
|
||||
expect.addSnapshotSerializer(htmlSerializer);
|
||||
|
|
@ -0,0 +1,53 @@
|
|||
<script lang="ts">
|
||||
import defaultAttributes from './defaultAttributes';
|
||||
import type { IconNode } from './types';
|
||||
import type { Snippet } from 'svelte';
|
||||
|
||||
interface Props {
|
||||
type: 'outline' | 'filled';
|
||||
name: string;
|
||||
color?: string;
|
||||
size?: number | string;
|
||||
stroke?: number | string;
|
||||
iconNode: IconNode;
|
||||
class?: string;
|
||||
children?: Snippet;
|
||||
[key: string]: any; // For rest props
|
||||
}
|
||||
|
||||
let {
|
||||
type,
|
||||
name,
|
||||
color = 'currentColor',
|
||||
size = 24,
|
||||
stroke = 2,
|
||||
iconNode,
|
||||
class: className = '',
|
||||
children,
|
||||
...restProps
|
||||
}: Props = $props();
|
||||
|
||||
// Derive the fill/stroke attributes based on type
|
||||
const typeAttributes = $derived(
|
||||
type === 'filled' ? { fill: color } : { 'stroke-width': stroke, stroke: color },
|
||||
);
|
||||
|
||||
// Derive the full class name
|
||||
const fullClassName = $derived(`tabler-icon tabler-icon-${name} ${className}`);
|
||||
</script>
|
||||
|
||||
<svg
|
||||
{...defaultAttributes[type]}
|
||||
{...restProps}
|
||||
width={size}
|
||||
height={size}
|
||||
class={fullClassName}
|
||||
{...typeAttributes}
|
||||
>
|
||||
{#each iconNode as [tag, attrs]}
|
||||
<svelte:element this={tag} {...attrs} />
|
||||
{/each}
|
||||
{#if children}
|
||||
{@render children()}
|
||||
{/if}
|
||||
</svg>
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
import type { Attrs } from "./types.js";
|
||||
|
||||
const defaultAttributes: Record<"outline" | "filled", Attrs> = {
|
||||
outline: {
|
||||
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',
|
||||
},
|
||||
filled: {
|
||||
xmlns: 'http://www.w3.org/2000/svg',
|
||||
width: 24,
|
||||
height: 24,
|
||||
viewBox: '0 0 24 24',
|
||||
fill: 'currentColor',
|
||||
stroke: 'none'
|
||||
},
|
||||
};
|
||||
|
||||
export default defaultAttributes;
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
export * from './icons/index.js';
|
||||
export * as icons from './icons/index.js';
|
||||
export * as iconsList from './icons-list.js';
|
||||
export * from './aliases.js';
|
||||
export { default as defaultAttributes } from './defaultAttributes.js';
|
||||
|
||||
export type { Icon } from './types.js';
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
import type { Component, Snippet } from 'svelte';
|
||||
import type { SVGAttributes, SvelteHTMLElements } from 'svelte/elements';
|
||||
|
||||
export type Attrs = SVGAttributes<SVGSVGElement>;
|
||||
|
||||
export type IconNode = [elementName: keyof SvelteHTMLElements, attrs: Attrs][];
|
||||
|
||||
export interface IconProps extends Omit<Attrs, 'color' | 'stroke'> {
|
||||
color?: string;
|
||||
size?: number | string;
|
||||
stroke?: number | string;
|
||||
class?: string;
|
||||
children?: Snippet;
|
||||
}
|
||||
|
||||
// Svelte 5 compatible icon type
|
||||
export type Icon = Component<IconProps>;
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
import { vitePreprocess } from '@sveltejs/vite-plugin-svelte';
|
||||
|
||||
export default {
|
||||
preprocess: vitePreprocess(),
|
||||
compilerOptions: {
|
||||
runes: true,
|
||||
},
|
||||
};
|
||||
|
|
@ -0,0 +1,132 @@
|
|||
import { describe, it, expect, afterEach } from 'vitest';
|
||||
import { render, cleanup } from '@testing-library/svelte';
|
||||
import { IconAccessible, IconAccessibleFilled } from './src/tabler-icons-svelte-runes.js';
|
||||
|
||||
describe('Svelte Runes Icon component', () => {
|
||||
afterEach(() => cleanup());
|
||||
|
||||
it('should render icon component', () => {
|
||||
const { container } = render(IconAccessible);
|
||||
expect(container.getElementsByTagName('svg').length).toBeGreaterThan(0);
|
||||
});
|
||||
|
||||
it('should add a class to the element', () => {
|
||||
const { container } = render(IconAccessible, {
|
||||
props: {
|
||||
class: 'test-class',
|
||||
},
|
||||
});
|
||||
|
||||
const svg = container.getElementsByTagName('svg')[0];
|
||||
|
||||
expect(svg).toHaveClass('test-class');
|
||||
expect(svg).toHaveClass('tabler-icon');
|
||||
expect(svg).toHaveClass('tabler-icon-accessible');
|
||||
});
|
||||
|
||||
it('should add a style attribute to the element', () => {
|
||||
const { container } = render(IconAccessible, {
|
||||
props: {
|
||||
style: 'color: red',
|
||||
},
|
||||
});
|
||||
|
||||
const svg = container.getElementsByTagName('svg')[0];
|
||||
|
||||
expect(svg).toHaveStyle('color: rgb(255, 0, 0)');
|
||||
});
|
||||
|
||||
it('should update svg attributes when there are props passed to the component', () => {
|
||||
const { container } = render(IconAccessible, {
|
||||
props: {
|
||||
size: 48,
|
||||
color: 'red',
|
||||
stroke: 4,
|
||||
},
|
||||
});
|
||||
|
||||
const svg = container.getElementsByTagName('svg')[0];
|
||||
|
||||
expect(svg.getAttribute('width')).toBe('48');
|
||||
expect(svg.getAttribute('stroke')).toBe('red');
|
||||
expect(svg.getAttribute('stroke-width')).toBe('4');
|
||||
});
|
||||
|
||||
it('should accept stroke as a number', () => {
|
||||
const { container } = render(IconAccessible, {
|
||||
props: {
|
||||
stroke: 3,
|
||||
},
|
||||
});
|
||||
|
||||
const svg = container.getElementsByTagName('svg')[0];
|
||||
|
||||
expect(svg.getAttribute('stroke-width')).toBe('3');
|
||||
});
|
||||
|
||||
it('should accept size as a string', () => {
|
||||
const { container } = render(IconAccessible, {
|
||||
props: {
|
||||
size: '100%',
|
||||
},
|
||||
});
|
||||
|
||||
const svg = container.getElementsByTagName('svg')[0];
|
||||
|
||||
expect(svg.getAttribute('width')).toBe('100%');
|
||||
expect(svg.getAttribute('height')).toBe('100%');
|
||||
});
|
||||
|
||||
it('should update svg attributes when there are props passed to the filled version of component', () => {
|
||||
const { container } = render(IconAccessibleFilled, {
|
||||
props: {
|
||||
size: 48,
|
||||
color: 'red',
|
||||
},
|
||||
});
|
||||
const svg = container.getElementsByTagName('svg')[0];
|
||||
|
||||
expect(svg.getAttribute('width')).toBe('48');
|
||||
expect(svg.getAttribute('fill')).toBe('red');
|
||||
expect(svg.getAttribute('stroke')).toBe('none');
|
||||
expect(svg.getAttribute('stroke-width')).toBe(null);
|
||||
});
|
||||
|
||||
it('should render children content using snippets', () => {
|
||||
const { container } = render(IconAccessible, {
|
||||
props: {},
|
||||
// Test that children can be passed (even though we can't easily test snippet content in this setup)
|
||||
});
|
||||
|
||||
const svg = container.getElementsByTagName('svg')[0];
|
||||
expect(svg).toBeDefined();
|
||||
});
|
||||
|
||||
it('should match snapshot', () => {
|
||||
const { container } = render(IconAccessible);
|
||||
expect(container.innerHTML).toMatchInlineSnapshot(`
|
||||
<svg xmlns="http://www.w3.org/2000/svg"
|
||||
width="24"
|
||||
height="24"
|
||||
viewbox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
class="tabler-icon tabler-icon-accessible "
|
||||
>
|
||||
<path d="M12 12m-9 0a9 9 0 1 0 18 0a9 9 0 1 0 -18 0">
|
||||
</path>
|
||||
<path d="M10 16.5l2 -3l2 3m-2 -3v-2l3 -1m-6 0l3 1">
|
||||
</path>
|
||||
<circle cx="12"
|
||||
cy="7.5"
|
||||
r=".5"
|
||||
fill="currentColor"
|
||||
>
|
||||
</circle>
|
||||
</svg>
|
||||
`);
|
||||
});
|
||||
});
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
{
|
||||
"extends": "@tsconfig/svelte/tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"target": "ESNext",
|
||||
"useDefineForClassFields": true,
|
||||
"module": "ESNext",
|
||||
"moduleResolution": "bundler",
|
||||
"resolveJsonModule": true,
|
||||
"allowJs": true,
|
||||
"checkJs": true,
|
||||
"isolatedModules": true,
|
||||
"lib": ["ESNext", "DOM", "DOM.Iterable"],
|
||||
"skipLibCheck": true,
|
||||
"strict": true,
|
||||
"types": ["vitest/globals", "@testing-library/jest-dom"]
|
||||
},
|
||||
"include": [
|
||||
"src/**/*.d.ts",
|
||||
"src/**/*.ts",
|
||||
"src/**/*.js",
|
||||
"src/**/*.svelte",
|
||||
"tests/**/*.ts",
|
||||
"*.spec.js",
|
||||
"vitest-setup.d.ts"
|
||||
],
|
||||
"exclude": ["node_modules", "dist"]
|
||||
}
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
/// <reference types="vitest" />
|
||||
import type { TestingLibraryMatchers } from '@testing-library/jest-dom/matchers';
|
||||
|
||||
declare module 'vitest' {
|
||||
interface Assertion<T = any> extends jest.Matchers<void, T>, TestingLibraryMatchers<T, void> {}
|
||||
interface AsymmetricMatchersContaining extends TestingLibraryMatchers<any, void> {}
|
||||
}
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
import { defineConfig } from 'vitest/config';
|
||||
import { svelte } from '@sveltejs/vite-plugin-svelte';
|
||||
|
||||
export default defineConfig({
|
||||
plugins: [svelte()],
|
||||
test: {
|
||||
globals: true,
|
||||
environment: 'jsdom',
|
||||
setupFiles: './setupVitest.ts',
|
||||
},
|
||||
resolve: {
|
||||
conditions: ['browser'],
|
||||
},
|
||||
});
|
||||
830
pnpm-lock.yaml
830
pnpm-lock.yaml
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue