🚀 Big News: Socket Acquires Coana to Bring Reachability Analysis to Every Appsec Team.Learn more
Socket
Book a DemoInstallSign in
Socket

@neodx/svg

Package Overview
Dependencies
Maintainers
1
Versions
23
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@neodx/svg - npm Package Compare versions

Comparing version

to
0.6.0

_internal/build-sprites-53a600c2.mjs

2

esbuild.d.ts
import * as esbuild from 'esbuild';
import { S as SvgPluginParams } from './_internal/unplugin-b0f65603.js';
import { S as SvgPluginParams } from './_internal/unplugin-bae8a85b.js';

@@ -4,0 +4,0 @@ declare const _default: (options: SvgPluginParams) => esbuild.Plugin;

@@ -1,9 +0,9 @@

import { C as CreateSpriteBuilderParams, S as SpriteBuilder } from './_internal/create-sprite-builder-f7c30e64.js';
export { c as createSpriteBuilder } from './_internal/create-sprite-builder-f7c30e64.js';
import { C as CreateSpriteBuilderParams, S as SpriteBuilder } from './_internal/create-sprite-builder-e2c64c5e.js';
export { c as createSpriteBuilder } from './_internal/create-sprite-builder-e2c64c5e.js';
import * as chokidar from 'chokidar';
import { S as SvgSpritePluginHooks, a as SvgSpritePlugin } from './_internal/types-fe41d676.js';
export { C as Context, d as GeneratedSprite, G as GeneratedSprites, c as SpriteGroup, b as SpriteGroupsMap, e as SvgFile, f as SvgFileMeta, g as SvgNode } from './_internal/types-fe41d676.js';
export { i as plugins } from './_internal/index-5157eb75.js';
import { S as SvgSpritePluginHooks, a as SvgSpritePlugin } from './_internal/types-ce4301f9.js';
export { C as Context, d as GeneratedSprite, G as GeneratedSprites, c as SpriteGroup, b as SpriteGroupsMap, e as SvgFile, f as SvgFileMeta, g as SvgNode } from './_internal/types-ce4301f9.js';
export { i as plugins } from './_internal/index-76f02c2a.js';
interface GenerateParams extends CreateSpriteBuilderParams {
interface BuildSpritesParams extends CreateSpriteBuilderParams {
/**

@@ -20,6 +20,6 @@ * Globs to icons files

/**
* Scan files by input globs, parse them and generate sprites.
* Scan files by input globs, parse them, and generate sprites.
* Accepts prepared config and vfs instance.
*/
declare function buildSprites({ vfs, input, logger, keepTreeChanges, ...builderParams }: GenerateParams): Promise<void>;
declare function buildSprites({ vfs, input, logger, keepTreeChanges, ...builderParams }: BuildSpritesParams): Promise<void>;

@@ -35,2 +35,2 @@ interface CreateWatcherParams {

export { CreateSpriteBuilderParams, CreateWatcherParams, GenerateParams, SpriteBuilder, SvgSpritePlugin, SvgSpritePluginHooks, buildSprites, createPlugin, createWatcher };
export { type BuildSpritesParams, CreateSpriteBuilderParams, type CreateWatcherParams, SpriteBuilder, SvgSpritePlugin, SvgSpritePluginHooks, buildSprites, createPlugin, createWatcher };
{
"name": "@neodx/svg",
"packageManager": "yarn@3.2.0",
"version": "0.5.1",
"version": "0.6.0",
"description": "Supercharge your icons ⚡️",

@@ -49,30 +49,30 @@ "author": {

"files": [
"_internal/build-sprites-79c0b006.mjs",
"_internal/build-sprites-79c0b006.mjs.map",
"_internal/build-sprites-f7266982.cjs",
"_internal/build-sprites-f7266982.cjs.map",
"_internal/create-sprite-builder-250912b5.cjs",
"_internal/create-sprite-builder-250912b5.cjs.map",
"_internal/create-sprite-builder-8a4c69f6.mjs",
"_internal/create-sprite-builder-8a4c69f6.mjs.map",
"_internal/create-sprite-builder-f7c30e64.d.ts",
"_internal/build-sprites-53a600c2.mjs",
"_internal/build-sprites-53a600c2.mjs.map",
"_internal/build-sprites-5e33685e.cjs",
"_internal/build-sprites-5e33685e.cjs.map",
"_internal/create-sprite-builder-456ffd2f.cjs",
"_internal/create-sprite-builder-456ffd2f.cjs.map",
"_internal/create-sprite-builder-51201aa0.mjs",
"_internal/create-sprite-builder-51201aa0.mjs.map",
"_internal/create-sprite-builder-e2c64c5e.d.ts",
"_internal/create-watcher-cbead848.mjs",
"_internal/create-watcher-cbead848.mjs.map",
"_internal/create-watcher-e04060c3.cjs",
"_internal/create-watcher-e04060c3.cjs.map",
"_internal/index-198e8e0d.cjs",
"_internal/index-198e8e0d.cjs.map",
"_internal/index-5157eb75.d.ts",
"_internal/index-ccef0d17.mjs",
"_internal/index-ccef0d17.mjs.map",
"_internal/svgo-401e044a.cjs",
"_internal/svgo-401e044a.cjs.map",
"_internal/svgo-aa2fc7f4.mjs",
"_internal/svgo-aa2fc7f4.mjs.map",
"_internal/types-fe41d676.d.ts",
"_internal/unplugin-58642a2c.cjs",
"_internal/unplugin-58642a2c.cjs.map",
"_internal/unplugin-b0f65603.d.ts",
"_internal/unplugin-cb9d332a.mjs",
"_internal/unplugin-cb9d332a.mjs.map",
"_internal/create-watcher-f8681281.cjs",
"_internal/create-watcher-f8681281.cjs.map",
"_internal/index-55c40f60.mjs",
"_internal/index-55c40f60.mjs.map",
"_internal/index-76f02c2a.d.ts",
"_internal/index-88e6636e.cjs",
"_internal/index-88e6636e.cjs.map",
"_internal/svgo-0c02f7ce.cjs",
"_internal/svgo-0c02f7ce.cjs.map",
"_internal/svgo-de218e6a.mjs",
"_internal/svgo-de218e6a.mjs.map",
"_internal/types-ce4301f9.d.ts",
"_internal/unplugin-8e071ca2.mjs",
"_internal/unplugin-8e071ca2.mjs.map",
"_internal/unplugin-aa79f5b2.cjs",
"_internal/unplugin-aa79f5b2.cjs.map",
"_internal/unplugin-bae8a85b.d.ts",
"cli.cjs",

@@ -131,26 +131,34 @@ "cli.cjs.map",

"dependencies": {
"@neodx/fs": "^0.0.9",
"@neodx/log": "^0.2.1",
"@neodx/std": "^0.1.5",
"@neodx/vfs": "^0.1.9",
"chokidar": "^3.5.3",
"@neodx/fs": "0.0.10",
"@neodx/log": "0.3.0",
"@neodx/std": "0.2.0",
"@neodx/vfs": "0.1.10",
"chokidar": "3.5.3",
"colord": "2.9.3",
"commander": "11.0.0",
"pathe": "^1.1.1",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"svgo": "^3.0.2",
"svgson": "^5.3.1",
"unplugin": "^1.4.0",
"zod": "^3.21.4"
"pathe": "1.1.1",
"react": "18.2.0",
"react-dom": "18.2.0",
"svgo": "3.0.2",
"svgson": "5.3.1",
"unplugin": "1.5.0",
"zod": "3.22.4"
},
"devDependencies": {
"@neodx/autobuild": "*",
"@swc/helpers": "^0.5.1",
"@types/react": "^18.2.15",
"@types/react-dom": "^18.2.7",
"@types/svgo": "^3.0.0",
"clsx": "^2.0.0",
"prettier": "^2.8.8"
"@swc/helpers": "0.5.3",
"@types/react": "18.2.25",
"@types/react-dom": "18.2.11",
"@types/svgo": "3.0.0",
"clsx": "2.0.0",
"prettier": "2.8.8"
},
"peerDependencies": {
"prettier": "*"
},
"peerDependenciesMeta": {
"prettier": {
"optional": true
}
},
"exports": {

@@ -157,0 +165,0 @@ ".": {

@@ -1,2 +0,2 @@

export { G as GroupPluginOptions, L as LegacyTypescriptPluginOptions, S as SvgoPluginOptions, f as fixViewBox, g as groupSprites, l as legacyTypescript, s as setId, a as svgo } from '../_internal/index-5157eb75.js';
export { A as AnyColorInput, h as ColorPropertyReplacementInput, i as ColorReplacementInputConfig, R as ResetColorsPluginParams, r as resetColors } from '../_internal/types-fe41d676.js';
export { G as GroupPluginOptions, L as LegacyTypescriptPluginOptions, f as fixViewBox, g as groupSprites, l as legacyTypescript, s as setId } from '../_internal/index-76f02c2a.js';
export { A as AnyColorInput, i as ColorPropertyReplacementInput, j as ColorReplacementInputConfig, R as ResetColorsPluginParams, h as SvgoPluginParams, r as resetColors, s as svgo } from '../_internal/types-ce4301f9.js';
# @neodx/svg
<div align="left">
<a href="https://www.npmjs.com/package/@neodx/svg">
<img src="https://img.shields.io/npm/v/@neodx/svg.svg" alt="npm" />
</a>
<img src="https://img.shields.io/npm/l/@neodx/svg.svg" alt="license"/>
</div>
Supercharge your icons ⚡️
## Motivation
> We're working on the new documentation, please, visit [neodx.pages.dev](https://neodx.pages.dev/svg) to see the latest version.
Sprites are the most effective way to work with your SVG icons,
but for some reason developers (vision from a React world) prefer
mostly bloated and ineffective, "compile" SVG to react component with inlined SVG content.
Of course, we can use some external tools like https://svgsprit.es/ or some npm libraries,
but that's not serious (if you know any alternatives, let me know, and I'll add links), developers need DX.
In a ridiculous, but incredibly popular way, we don't have other solutions with the same DX.
Just think about it a little, you need to "compile" SVG, to embed your secondary static content in JSX
and get a lot of unwanted issues: additional source code, extra build time, extra bundle size,
the user's browser will parse and evaluate your **static SVG** as JS code,
you can never cache it, WOOF, etc., etc.
And yes, developers keep using this insanity because even an incredibly inefficient solution with a good DX
is better than a super-efficient, but unusable setup with semi-manual generators.
That's why we're here! 🥳
- TypeScript support out of box - generated types and [information about your sprites](#-content-based-hashes-and-runtime-metadata-generation)
- [Built-in integrated plugins](#integrate-with-your-bundler) for all major bundlers: `vite`, `webpack`, `rollup`, `esbuild`, etc.
- Optional grouping by folders
- Optimization with svgo
- Optional [grouping by folders](https://neodx.pages.dev/svg/group-and-hash.html)
- Optimization with [svgo](https://neodx.pages.dev/svg/api/plugins/svgo.html)
- [Automatically reset colors](#-automatically-reset-colors)
- Powerful files selection

@@ -44,13 +31,8 @@ ## Installation and usage

### CLI (Not recommended)
We're highly recommended to start with our ["Getting started" guide](https://neodx.pages.dev/svg/).
Currently, we don't recommend using CLI mode because it's not flexible enough and requires extra setup
if you want to use it - see [CLI](#cli) section and [CLI Options API](#cli-options).
### Integrate with your bundler
```shell
yarn sprite --help
```
> For better understanding and to access the latest version, please visit [our documentation](https://neodx.pages.dev/svg/setup/).
### Integrate with your bundler
Our plugins are built upon [unplugin](https://github.com/unjs/unplugin)

@@ -68,8 +50,3 @@ and provide a consistent interface and working principle across all multiple bundlers and frameworks.

root: 'assets',
group: true,
output: 'public',
metadata: 'src/shared/ui/icon/sprite.gen.ts',
resetColors: {
replaceUnknown: 'currentColor'
}
output: 'public'
})

@@ -81,74 +58,9 @@ ]

It will search for all SVG files in `assets` folder, group them by folders, optimize them with `svgo`,
reset all colors to `currentColor`
and generate sprites in `public` folder with TS definitions in `src/shared/ui/icon/sprite.gen.ts`.
reset all colors to `currentColor` and generate sprites in `public` folder.
For more details, see our [Step-by-step guide](#step-by-step).
For more details, see our [Step-by-step guide](https://neodx.pages.dev/svg/).
> **Note**: If you receive the error `TS2307: Cannot find module '@neodx/svg/vite' or its corresponding type declarations`,
> it's a common issue that will be fixed in one of the next versions.
>
> To resolve this issue at present, change `moduleResolution` to `Bundler` in your `tsconfig.json`.
Another plugins:
<details>
<summary>Webpack</summary>
```typescript
import svg from '@neodx/svg/webpack';
export default {
plugins: [
svg({
root: 'assets',
output: 'public',
metadata: 'src/shared/ui/icon/sprite.gen.ts'
})
]
};
```
</details>
<details>
<summary>Rollup</summary>
```typescript
import svg from '@neodx/svg/rollup';
export default {
plugins: [
svg({
root: 'assets',
output: 'public',
metadata: 'src/shared/ui/icon/sprite.gen.ts'
})
]
};
```
</details>
<details>
<summary>ESBuild</summary>
```typescript
import svg from '@neodx/svg/esbuild';
export default {
plugins: [
svg({
root: 'assets',
output: 'public',
metadata: 'src/shared/ui/icon/sprite.gen.ts'
})
]
};
```
</details>
## Features
### 🆕 Automatically reset colors
### 🆕 [Automatically reset colors](https://neodx.pages.dev/svg/colors-reset.html)

@@ -171,3 +83,3 @@ Automate your icons and forget about colors management issues.

To solve these issues, we're introducing a `resetColors` option:
To solve these issues, we're providing a powerful color reset mechanism (`resetColors` option, enabled by default):

@@ -179,109 +91,6 @@ - Automatically detects all colors in all forms (thx [colord](https://github.com/omgovich/colord)) from SVG content

###### Features preview
> Check out [our documentation](https://neodx.pages.dev/svg/colors-reset.html) for more details.
<details>
<summary>Disable colors reset</summary>
### 🆕 [Content-based hashes and runtime metadata generation](https://neodx.pages.dev/svg/group-and-hash.html)
```typescript
svg({
// disable colors reset
resetColors: false
});
```
</details>
<details>
<summary>Filter colors and icons</summary>
```typescript
svg({
resetColors: {
// global files filter (default - all files)
exclude: ['path/to/icon.svg', /[a-z]*-colored\.svg$/],
include: ['path/to/other-icon.svg' /* ... */],
// keep specific colors untouched
keep: ['white', '#eee'],
// all colors except white and #eee will be replaced with currentColor
replaceUnknown: 'currentColor'
}
});
```
</details>
<details>
<summary>Replace specific colors</summary>
> Without `replaceUnknown` option, all unspecified colors will be kept as is.
```typescript
svg({
resetColors: {
// if you want to replace specific colors only with currentColor, you can simply pass it as a string or array
replace: ['white', '#eee'],
// when you need to replace colors with a concrete color, you can pass an object with `from` and `to` properties
replace: {
from: [legacyBrandColor, legacyBrandColor2],
to: brandColor
},
// you can also pass an array of objects
replace: [
{
from: [legacyBrandColor, legacyBrandColor2],
to: brandColor
},
{
from: ['white', '#eee'],
to: 'currentColor'
}
]
}
});
```
</details>
###### Complex example
- Replace white color in all flags with `currentColor`
- For all icons except flags, logos and colored icons:
- Keep brand colors untouched
- Replace known accent colors with `var(--icon-color)`
- Replace known secondary colors with `var(--icon-bg)`
- Replace all other colors with `currentColor`
```typescript
svg({
resetColors: [
{
include: /^flags/,
replace: {
from: 'white',
to: 'currentColor'
}
},
{
keep: myTheme.brandColors,
exclude: [/^flags/, /^logos/, /-colored\.svg$/],
replace: [
{
from: myTheme.accentIconColors,
to: 'var(--icon-color)'
},
{
from: myTheme.secondaryIconColors,
to: 'var(--icon-bg)'
}
],
// if you want to replace colors in specific properties only, you can pass an array of them
properties: ['fill', 'stroke'],
replaceUnknown: 'currentColor'
}
]
});
```
### 🆕 Content-based hashes and runtime metadata generation
> **Note:** If you used `definitions` or `experimentalRuntime` options before, you need to update your configuration, see [Migration guide](#move-from-definitions-and-experimentalruntime-options-to-metadata-api).

@@ -297,4 +106,3 @@

But this is not very good for caching,
because if you change any of the SVG files,
But this is not very good for caching, because if you change any of the SVG files,
the sprite filename won't be updated, which could result in an infinite cache.

@@ -314,82 +122,46 @@

svg({
root: 'assets',
output: 'public/sprites',
fileName: '{name}.{hash:8}.svg',
metadata: {
path: 'src/shared/ui/icon/sprite.gen.ts',
path: 'src/sprite.gen.ts',
runtime: {
size: true,
viewBox: true
// generate runtime metadata (path and other information) for each sprite
size: true, // will add `width` and `height` properties
viewBox: true // will add `viewBox` property
}
}
// ...
})
// ...
]
// ...
});
```
Your output will be:
In the result, you will get the following sprites in your output:
```diff
public/
+ sprite-foo.12abc678.svg
+ sprite-bar.87654def.svg
/
├── assets
│ ├── common
│ │ ├── left.svg
│ │ └── right.svg
│ └── actions
│ └── close.svg
├── public
+ └── sprites
+ ├── common.12ghS6Uj.svg
+ └── actions.1A34ks78.svg
└── src
+ └── sprite.gen.ts
```
With the following metadata in `src/shared/ui/icon/sprite.gen.ts`:
To learn how to use it,
check out [our "Writing an Icon component" guide](https://neodx.pages.dev/svg/group-and-hash.html) or detailed basic tutorials:
```typescript
export interface SpritesMap {
'sprite-foo': 'first' | 'second';
'sprite-bar': ' /* ... */ ';
}
export const SPRITES_META = {
'sprite-foo': {
filePath: 'sprite-foo.12abc678.svg',
items: {
first: {
// all items will have `viewBox`, `width` and `height` properties
viewBox: '0 0 48 48',
width: 48,
height: 48
},
second: {
/* ... */
}
}
},
'sprite-bar': {
filePath: 'sprite-bar.87654def.svg',
items: {
/* ... */
}
}
};
```
- [Group and hash sprites](https://neodx.pages.dev/svg/group-and-hash.html)
- [Generate metadata](https://neodx.pages.dev/svg/metadata.html)
And updates of `Icon` component will be like this:
## Step-by-step
> This example is based on implementation from [Building Icon component with TailwindCSS](#building-icon-component-with-tailwindcss-see-example) recipe and our [Vite application example (link to GH repo)](https://github.com/secundant/neodx/tree/main/examples/svg-vite)
It's a simplified tutorial, for detailed one check our ["Getting started" guide](https://neodx.pages.dev/svg/).
```diff
+ import { SPRITES_META, type SpritesMap } from './sprite.gen';
+ export function Icon({ name, /* ... */ }) {
const [spriteName, iconName] = name.split('/');
+ const { filePath, items } = SPRITES_META[spriteName];
+ const { viewBox } = items[iconName];
return (
<svg
+ viewBox={viewBox}
// ...
>
+ <use href={`/${filePath}#${iconName}`} />
</svg>
);
}
```
## Step-by-step
Our example stack details:

@@ -405,9 +177,11 @@

```diff
assets/
common/
add.svg
close.svg
other/
cut.svg
search.svg
/
├── assets
│ ├── common
│ │ ├── left.svg
| | ... other icons
│ │ └── right.svg
│ └── actions
│ ... other icons
│ └── close.svg
```

@@ -419,8 +193,6 @@

Firstly, we adopt configuration from [Integrate with your bundler](#integrate-with-your-bundler) section:
```typescript
import { defineConfig } from 'vite';
import svg from '@neodx/svg/vite';
import react from '@vitejs/plugin-react';
import { defineConfig } from 'vite';
import tsconfigPaths from 'vite-tsconfig-paths';

@@ -435,9 +207,4 @@

group: true,
output: 'public',
metadata: {
path: 'src/shared/ui/icon/sprite.gen.ts'
},
resetColors: {
replaceUnknown: 'currentColor'
}
output: 'public/sprites',
metadata: 'src/shared/ui/icon/sprite.gen.ts'
})

@@ -448,246 +215,33 @@ ]

<details>
<summary>If you decided to use CLI mode:</summary>
Let's run `sprite` with some additional options:
```bash
yarn sprite --group --root assets -o public/sprite -d src/shared/ui/icon/sprite.gen.ts --reset-unknown-colors
```
In details:
- The `--group` option group icons by folders (`common` and `other`)
- The `--root` option sets `assets` as a base path for icons (you can try to remove it and see the difference)
- The `-o` option sets `public/sprite` as a base path for generated sprites (it's default value, but let's keep it for now)
- The `-d` option generates TS definitions file with sprite meta information
</details>
Now let's run `vite` (or `vite build`) and see what we have:
```diff
...
shared/
ui/
icon/
+ sprite.gen.ts
public/
+ sprite/
+ common.svg
+ other.svg
/
├── assets
│ ├── common
│ │ ├── left.svg
│ │ └── right.svg
│ └── actions
│ └── close.svg
├── public
+ └── sprites
+ ├── common.svg
+ └── actions.svg
└── src
└── shared
└── ui
└── icon
+ └── sprite.gen.ts
```
For each folder in `assets`, a separate sprite is created, along with a TS definitions file containing metadata about all icons.
Now you could visit our ["Writing an Icon component" guide](https://neodx.pages.dev/svg/writing-icon-component.html) to learn how to use it.
### Look at generated TS definitions
## Guides
```ts
export interface SpritesMap {
common: 'close' | 'favourite';
format: 'align-left' | 'tag';
}
- [Getting started](https://neodx.pages.dev/svg)
- [Group and hash sprites](https://neodx.pages.dev/svg/group-and-hash.html)
- [Generate metadata](https://neodx.pages.dev/svg/metadata.html)
- [Writing an Icon component](https://neodx.pages.dev/svg/writing-icon-component.html)
- [Working with multicolored icons](https://neodx.pages.dev/svg/multicolored.html)
export const SPRITES_META: { [K in keyof SpritesMap]: SpritesMap[K][] } = {
common: ['close', 'favourite'],
format: ['align-left', 'tag']
};
```
As you can see, we have a map of all sprites and meta information about them.
Now we can use it in our code - for type checking, autocomplete, and other cool stuff.
### Create your Icon component
> It's a **simple** implementation, you can see a real one in the "Recipes" section
```tsx
// shared/ui/icon/icon.tsx
import { SpritesMap } from './sprite.gen';
export interface IconProps<Group extends keyof SpritesMap> {
name: SpritesMap[Group];
type?: Group;
}
export function Icon<Group extends keyof SpritesMap = 'common'>({ type, name }: IconProps<Group>) {
return (
<svg className="icon">
<use href={`/public/sprite/${type}.svg#${name}`}></use>
</svg>
);
}
```
### Enjoy 👏
```tsx
import { Icon, TextField } from '@/shared/ui';
export function SomeFeature() {
return (
<div className="space-y-4">
<TextField name="a" startNode={<Icon name="add" />} />
<TextField name="b" startNode={<Icon name="close" />} />
<TextField name="c" startNode={<Icon type="other" name="search" />} />
</div>
);
}
```
## CLI
> **Warning:**
> While the CLI mode is currently available,
> it's not the recommended method of use and might be removed in future major versions.
>
> Now we're providing built-it bundlers integration, please, use [our plugin](#integrate-with-your-bundler) instead.
To get started, you can try the CLI mode even without any configuration, just run `sprite` command:
```shell
yarn sprite
```
This command searches for all SVG files, excluding those in the `public/sprites` folder and generate sprites in `public/sprites`.
By default, it creates a single sprite containing all icons without any grouping or TS definitions. However, this can be customized. See [CLI options](#cli-options) for more information
## Recipes
### Building Icon component with TailwindCSS ([see example](./examples/react))
#### Add base `icon` class
```css
/* shared/ui/index.css */
@tailwind base;
@tailwind components;
@tailwind utilities;
@layer components {
/*
Our base class for all icons, includes:
- `fill-current` - fill icon with current text color, so we can use `color` to change it
- `w-[1em] h-[1em]` - set icon size to 1em, so we can use `font-size` to scale it
- `box-content` - it's up to you, I choose it to keep icon size fixed
*/
.icon {
@apply select-none fill-current w-[1em] h-[1em] inline-block text-inherit box-content;
}
}
```
#### Add `Icon` component
```tsx
// shared/ui/icon/icon.tsx
import clsx from 'clsx';
import { SVGProps } from 'react';
import { SpritesMap } from './sprite.gen';
// Merging all icons as `SPRITE_NAME/SPRITE_ICON_NAME`
export type IconName = {
[Key in keyof SpritesMap]: `${Key}/${SpritesMap[Key]}`;
}[keyof SpritesMap];
export interface IconProps extends Omit<SVGProps<SVGSVGElement>, 'name' | 'type'> {
name: IconName;
}
export function Icon({ name, className, viewBox, ...props }: IconProps) {
const [spriteName, iconName] = name.split('/');
return (
<svg
// We recommend to use specific component class for avoid collisions with other styles and simple override it
className={clsx('icon', className)}
viewBox={viewBox}
focusable="false"
aria-hidden
{...props}
>
{/* For example, "/common.svg#favourite". Change base path if you don't store sprites under the root. */}
<use href={`/${spriteName}.svg#${iconName}`} />
</svg>
);
}
```
#### Usage
```tsx
import { Icon } from '@/shared/ui';
export function SomeFeature() {
return (
<div className="space-y-4">
<Icon name="common/add" />
<Icon name="common/close" className="text-red-500" />
<Icon name="text/bold" className="text-lg" />
<Icon name="actions/delete" className="p-2 rounded-md bg-stone-300" />
</div>
);
}
```
### Multiple colors
Let's imagine that we have a really different icons with next requirements:
- We have some known list of the accent colors, and we want to specify them in our CSS
- All other colors should be inherited from the parent (for example, `currentColor`)
#### Configure `resetColors` option
```typescript
import svg from '@neodx/svg/vite';
svg({
// ...
resetColors: {
// 1. Define known accent colors
replace: {
from: ['#6C707E', '#A8ADBD', '#818594'],
to: 'var(--icon-accent-color)'
},
// 2. Replace all other colors with `currentColor`
replaceUnknown: 'currentColor'
}
});
```
#### Add CSS variables
```css
/* shared/ui/index.css */
@layer base {
:root {
/* make default accent color */
--icon-primary-color: #6c707e;
}
}
```
#### Usage
Dirty but works 🫢
Probably, you can find a better solution 🫠
```tsx
import { Icon } from '@/shared/ui';
export function SomeFeature() {
return (
<Icon
name="common/add"
className="text-red-800 [--icon-primary-color:theme(colors.green.800)]"
/>
);
}
```
## Migrations

@@ -714,90 +268,2 @@

## API
### Node.JS API
```typescript
import { buildSprites } from '@neodx/svg';
import { createVfs } from '@neodx/vfs';
await buildSprites({
vfs: createVfs(process.cwd()),
root: 'assets',
input: '**/*.svg',
output: 'public',
definition: 'src/shared/ui/icon/sprite.gen.ts'
// ... options (see below)
});
```
#### Options
```typescript
interface Options {
/**
* Root folder for inputs, useful for correct groups naming
* @default process.cwd()
*/
root?: string;
/**
* Path to generated sprite/sprites folder
* @default public
*/
output?: string;
/**
* Logger instance (or object with any compatible interface)
* @see `@neodx/log`
* @default built-in logger
*/
logger?: LoggerMethods<'info' | 'debug' | 'error'>;
/**
* Should we group icons?
* @default false
*/
group?: boolean;
/**
* Template of sprite file name
* @example {name}.svg
* @example sprite-{name}.svg
* @example {name}-{hash}.svg
* @example {name}-{hash:8}.svg
* @default {name}.svg
*/
fileName?: string;
/**
* Should we optimize icons?
*/
optimize?: boolean;
/**
* Configures metadata generation
* @example "src/sprites/meta.ts"
* @example { path: "meta.ts", runtime: false } // will generate only types
* @example { path: "meta.ts", types: 'TypeName', runtime: 'InfoName' } // will generate "interface TypeName" types and "const InfoName" runtime metadata
* @example { path: "meta.ts", runtime: { size: true, viewBox: true } } // will generate runtime metadata with size and viewBox
*/
metadata?: MetadataPluginParams;
/**
* Reset colors config
*/
resetColors?: ResetColorsPluginParams;
}
```
### CLI Options
| option | default | description |
| -------------------------- | ------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------- |
| `-i`, `--input` | `"**/*.svg"` | Glob paths to icons files (output path will be automatically excluded) |
| `-o`, `--output` | `"public/sprites"` | Base path to generated sprite/sprites folder |
| `-d`, `--definitions` | Not provided (**disabled**) | Path to generated TS file with sprite meta |
| `--root` | `"."` (same as the current dir) | Base path to your assets, useful for correct groups names<br/>**careful:** `--input` should be relative to `--root` |
| `--group` | `false` | Should we group icons by folders? |
| `--dry-run` | `false` | Print proposal of generated file paths without actually generating it |
| `--optimize` | `true` | Should we optimize SVG with [svgo](https://github.com/svg/svgo)? |
| `--reset-color-values` | `"#000,#000000"` | An array of colors to replace as `currentColor` |
| `--reset-unknown-colors` | `false` | Should we set `currentColor` for all colors not defined in `--reset-color-values`, or for all colors if this option isn't provided? |
| `--reset-color-properties` | `"fill,stroke"` | An array of SVG properties that will be replaced with `currentColor` if they're present |
> **Note:** `--reset-color-values` and `--reset-color-properties` are strings with comma-separated values, don't forget to wrap them with quotes:
>
> `sprite ... --reset-color-values "#000,#000000,#fff"`
- [API Reference](https://neodx.pages.dev/svg/api/)

@@ -1,2 +0,2 @@

import { S as SvgPluginParams } from './_internal/unplugin-b0f65603.js';
import { S as SvgPluginParams } from './_internal/unplugin-bae8a85b.js';

@@ -3,0 +3,0 @@ declare const _default: (options: SvgPluginParams) => WebpackPluginInstance;

@@ -1,2 +0,2 @@

import { S as SvgPluginParams } from './_internal/unplugin-b0f65603.js';
import { S as SvgPluginParams } from './_internal/unplugin-bae8a85b.js';

@@ -3,0 +3,0 @@ declare const _default: (options: SvgPluginParams) => RspackPluginInstance;

import * as vite from 'vite';
import { S as SvgPluginParams } from './_internal/unplugin-b0f65603.js';
import { S as SvgPluginParams } from './_internal/unplugin-bae8a85b.js';

@@ -4,0 +4,0 @@ declare const _default: (options: SvgPluginParams) => vite.Plugin | vite.Plugin[];

@@ -1,2 +0,2 @@

import { S as SvgPluginParams } from './_internal/unplugin-b0f65603.js';
import { S as SvgPluginParams } from './_internal/unplugin-bae8a85b.js';

@@ -3,0 +3,0 @@ declare const _default: (options: SvgPluginParams) => WebpackPluginInstance;

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet