mirror of
https://github.com/gromlab-ru/svg-sprites.git
synced 2026-07-22 04:40:17 +03:00
sync
This commit is contained in:
29
docs/en/README.md
Normal file
29
docs/en/README.md
Normal file
@@ -0,0 +1,29 @@
|
||||
# Documentation
|
||||
|
||||
Choose one exact mode guide for setup. The guides are standalone documents and
|
||||
can also be used unchanged by AI skills.
|
||||
|
||||
## Quick Start Guides
|
||||
|
||||
| Project | Exact mode | Guide |
|
||||
|---|---|---|
|
||||
| Static HTML or custom publishing | `standalone` | [Bare standalone](guides/standalone.md) |
|
||||
| Vanilla + Vite | `standalone@vite` | [Standalone + Vite](guides/standalone-vite.md) |
|
||||
| Vanilla + Webpack 5 | `standalone@webpack` | [Standalone + Webpack](guides/standalone-webpack.md) |
|
||||
| React + Vite | `react@vite` | [React + Vite](guides/react-vite.md) |
|
||||
| React + Webpack 5 | `react@webpack` | [React + Webpack](guides/react-webpack.md) |
|
||||
| Next.js App Router + Turbopack | `next@app/turbopack` | [App Router + Turbopack](guides/next-app-turbopack.md) |
|
||||
| Next.js App Router + Webpack | `next@app/webpack` | [App Router + Webpack](guides/next-app-webpack.md) |
|
||||
| Next.js Pages Router + Turbopack | `next@pages/turbopack` | [Pages Router + Turbopack](guides/next-pages-turbopack.md) |
|
||||
| Next.js Pages Router + Webpack | `next@pages/webpack` | [Pages Router + Webpack](guides/next-pages-webpack.md) |
|
||||
|
||||
Every guide follows the same order:
|
||||
|
||||
1. Generate the sprite through `npx` without adding the package to the project.
|
||||
2. Optionally install and connect the debug Viewer.
|
||||
3. Optionally type the config through the package or a local copy-paste type.
|
||||
|
||||
## Reference
|
||||
|
||||
- [Technical reference](reference/technical.md)
|
||||
- [Programmatic API](reference/programmatic-api.md)
|
||||
11
docs/en/guides/README.md
Normal file
11
docs/en/guides/README.md
Normal file
@@ -0,0 +1,11 @@
|
||||
# Quick Start Guides
|
||||
|
||||
- `standalone`: [bare standalone](standalone.md)
|
||||
- `standalone@vite`: [standalone with Vite](standalone-vite.md)
|
||||
- `standalone@webpack`: [standalone with Webpack](standalone-webpack.md)
|
||||
- `react@vite`: [React with Vite](react-vite.md)
|
||||
- `react@webpack`: [React with Webpack](react-webpack.md)
|
||||
- `next@app/turbopack`: [App Router with Turbopack](next-app-turbopack.md)
|
||||
- `next@app/webpack`: [App Router with Webpack](next-app-webpack.md)
|
||||
- `next@pages/turbopack`: [Pages Router with Turbopack](next-pages-turbopack.md)
|
||||
- `next@pages/webpack`: [Pages Router with Webpack](next-pages-webpack.md)
|
||||
153
docs/en/guides/next-app-turbopack.md
Normal file
153
docs/en/guides/next-app-turbopack.md
Normal file
@@ -0,0 +1,153 @@
|
||||
# Next.js App Router Turbopack SVG Sprite Quick Start
|
||||
|
||||
This guide targets the exact mode key `next@app/turbopack`: a generated typed React icon for the Next.js App Router and Turbopack.
|
||||
|
||||
## 1. Generate the sprite
|
||||
|
||||
No package installation and no `package.json` dependency are needed. `npx` downloads the CLI temporarily, and generated runtime does not import `@gromlab/svg-sprites`.
|
||||
|
||||
Keep the config and source icons together:
|
||||
|
||||
```text
|
||||
src/ui/icons/
|
||||
├── icons/
|
||||
│ ├── check.svg
|
||||
│ └── folder.svg
|
||||
└── svg-sprite.config.ts
|
||||
```
|
||||
|
||||
Use a plain default object export with no package import:
|
||||
|
||||
```ts
|
||||
// src/ui/icons/svg-sprite.config.ts
|
||||
export default {
|
||||
mode: 'next@app/turbopack',
|
||||
name: 'icons',
|
||||
}
|
||||
```
|
||||
|
||||
When `input` is omitted, SVG files are read from `./icons` relative to the config. A `.js` config with a default export and a `.json` config are also supported. Generate directly with:
|
||||
|
||||
```bash
|
||||
npx --yes --package=@gromlab/svg-sprites@latest svg-sprites src/ui/icons/svg-sprite.config.ts
|
||||
```
|
||||
|
||||
Generate once per invocation and keep the exact Turbopack flags on both commands:
|
||||
|
||||
```json
|
||||
{
|
||||
"scripts": {
|
||||
"sprites": "npx --yes --package=@gromlab/svg-sprites@latest svg-sprites src/ui/icons/svg-sprite.config.ts",
|
||||
"dev": "npm run sprites && next dev --turbopack",
|
||||
"build": "npm run sprites && next build --turbopack"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Do not add `predev` or `prebuild` hooks to these scripts; that would run generation twice. In CI, replace `latest` with an exact package version.
|
||||
|
||||
Generation creates a local `.gitignore`; commit that file once, but do not commit `.svg-sprite/`. Generated declarations are self-contained and do not require the package.
|
||||
|
||||
### Production usage
|
||||
|
||||
The generated icon has no `'use client'` directive and is Server Component-compatible. Import it directly in an App Router page or layout:
|
||||
|
||||
```tsx
|
||||
// src/app/page.tsx
|
||||
import {
|
||||
IconsIcon,
|
||||
iconsIconNames,
|
||||
} from '../ui/icons/.svg-sprite/index.js'
|
||||
|
||||
export default function Page() {
|
||||
return (
|
||||
<main>
|
||||
<IconsIcon icon="folder" width={24} height={24} aria-label="Files" />
|
||||
<p>{iconsIconNames.length} icons available</p>
|
||||
</main>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
Turbopack resolves the generated `new URL('../sprite.svg', import.meta.url)` and CSS Module, emitting a separate SVG asset. Keep the mode and the `--turbopack` dev/build flags aligned.
|
||||
|
||||
## 2. Debug and preview
|
||||
|
||||
This section is optional. Only users who need the Viewer or icon previews should install:
|
||||
|
||||
```bash
|
||||
npm install --save-dev @gromlab/svg-sprites
|
||||
```
|
||||
|
||||
Viewer is interactive, so place the React bridge in a separate Client Component:
|
||||
|
||||
```tsx
|
||||
// src/app/icon-debug/IconsViewer.tsx
|
||||
'use client'
|
||||
|
||||
import { SpriteViewer } from '@gromlab/svg-sprites/react'
|
||||
|
||||
const sources = [
|
||||
() => import('../../ui/icons/.svg-sprite/svg-sprite.manifest.js'),
|
||||
]
|
||||
|
||||
export function IconsViewer() {
|
||||
return <SpriteViewer sources={sources} title="Project icons" />
|
||||
}
|
||||
```
|
||||
|
||||
Render it from the route's Server Component:
|
||||
|
||||
```tsx
|
||||
// src/app/icon-debug/page.tsx
|
||||
import { IconsViewer } from './IconsViewer'
|
||||
|
||||
export default function IconDebugPage() {
|
||||
return <IconsViewer />
|
||||
}
|
||||
```
|
||||
|
||||
Keep the route internal or development-only. Viewer is not part of the production icon runtime.
|
||||
|
||||
## 3. Type the config
|
||||
|
||||
Choose one of these two paths.
|
||||
|
||||
### With a local package installation
|
||||
|
||||
After installing the package locally, use the helper:
|
||||
|
||||
```ts
|
||||
import { defineSpriteConfig } from '@gromlab/svg-sprites'
|
||||
|
||||
export default defineSpriteConfig({
|
||||
mode: 'next@app/turbopack',
|
||||
name: 'icons',
|
||||
})
|
||||
```
|
||||
|
||||
You can alternatively import `type SpriteConfig` and apply `satisfies SpriteConfig`.
|
||||
|
||||
### Without the package
|
||||
|
||||
Copy a mode-specific type directly into the config:
|
||||
|
||||
```ts
|
||||
type LocalSpriteConfig = {
|
||||
mode: 'next@app/turbopack'
|
||||
name?: string
|
||||
description?: string
|
||||
input?: string | string[]
|
||||
transform?: {
|
||||
removeSize?: boolean
|
||||
replaceColors?: boolean
|
||||
addTransition?: boolean
|
||||
}
|
||||
generatedNotice?: boolean
|
||||
}
|
||||
|
||||
export default {
|
||||
mode: 'next@app/turbopack',
|
||||
name: 'icons',
|
||||
} satisfies LocalSpriteConfig
|
||||
```
|
||||
153
docs/en/guides/next-app-webpack.md
Normal file
153
docs/en/guides/next-app-webpack.md
Normal file
@@ -0,0 +1,153 @@
|
||||
# Next.js App Router Webpack SVG Sprite Quick Start
|
||||
|
||||
This guide targets the exact mode key `next@app/webpack`: a generated typed React icon for the Next.js App Router and Webpack 5.
|
||||
|
||||
## 1. Generate the sprite
|
||||
|
||||
No package installation and no `package.json` dependency are needed. `npx` downloads the CLI temporarily, and generated runtime does not import `@gromlab/svg-sprites`.
|
||||
|
||||
Keep the config adjacent to its source icons:
|
||||
|
||||
```text
|
||||
src/ui/icons/
|
||||
├── icons/
|
||||
│ ├── check.svg
|
||||
│ └── folder.svg
|
||||
└── svg-sprite.config.ts
|
||||
```
|
||||
|
||||
Use a plain default object export with no package import:
|
||||
|
||||
```ts
|
||||
// src/ui/icons/svg-sprite.config.ts
|
||||
export default {
|
||||
mode: 'next@app/webpack',
|
||||
name: 'icons',
|
||||
}
|
||||
```
|
||||
|
||||
When `input` is omitted, SVG files are read from `./icons` relative to the config. A `.js` config with a default export and a `.json` config are also supported. Generate directly with:
|
||||
|
||||
```bash
|
||||
npx --yes --package=@gromlab/svg-sprites@latest svg-sprites src/ui/icons/svg-sprite.config.ts
|
||||
```
|
||||
|
||||
Generate once per invocation and keep the exact Webpack flags on both commands:
|
||||
|
||||
```json
|
||||
{
|
||||
"scripts": {
|
||||
"sprites": "npx --yes --package=@gromlab/svg-sprites@latest svg-sprites src/ui/icons/svg-sprite.config.ts",
|
||||
"dev": "npm run sprites && next dev --webpack",
|
||||
"build": "npm run sprites && next build --webpack"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Do not add `predev` or `prebuild` hooks to these scripts; that would run generation twice. In CI, replace `latest` with an exact package version.
|
||||
|
||||
Generation creates a local `.gitignore`; commit that file once, but do not commit `.svg-sprite/`. Generated declarations are self-contained and do not require the package.
|
||||
|
||||
### Production usage
|
||||
|
||||
The generated icon has no `'use client'` directive and is Server Component-compatible. Import it directly in an App Router page or layout:
|
||||
|
||||
```tsx
|
||||
// src/app/page.tsx
|
||||
import {
|
||||
IconsIcon,
|
||||
iconsIconNames,
|
||||
} from '../ui/icons/.svg-sprite/index.js'
|
||||
|
||||
export default function Page() {
|
||||
return (
|
||||
<main>
|
||||
<IconsIcon icon="folder" width={24} height={24} aria-label="Files" />
|
||||
<p>{iconsIconNames.length} icons available</p>
|
||||
</main>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
Webpack resolves the generated `new URL('../sprite.svg', import.meta.url)` and CSS Module, emitting a separate SVG asset. Keep the mode and the `--webpack` dev/build flags aligned. If custom Next.js webpack rules process SVG through SVGR, exclude `.svg-sprite/sprite.svg` from those rules.
|
||||
|
||||
## 2. Debug and preview
|
||||
|
||||
This section is optional. Only users who need the Viewer or icon previews should install:
|
||||
|
||||
```bash
|
||||
npm install --save-dev @gromlab/svg-sprites
|
||||
```
|
||||
|
||||
Viewer is interactive, so place the React bridge in a separate Client Component:
|
||||
|
||||
```tsx
|
||||
// src/app/icon-debug/IconsViewer.tsx
|
||||
'use client'
|
||||
|
||||
import { SpriteViewer } from '@gromlab/svg-sprites/react'
|
||||
|
||||
const sources = [
|
||||
() => import('../../ui/icons/.svg-sprite/svg-sprite.manifest.js'),
|
||||
]
|
||||
|
||||
export function IconsViewer() {
|
||||
return <SpriteViewer sources={sources} title="Project icons" />
|
||||
}
|
||||
```
|
||||
|
||||
Render it from the route's Server Component:
|
||||
|
||||
```tsx
|
||||
// src/app/icon-debug/page.tsx
|
||||
import { IconsViewer } from './IconsViewer'
|
||||
|
||||
export default function IconDebugPage() {
|
||||
return <IconsViewer />
|
||||
}
|
||||
```
|
||||
|
||||
Keep the route internal or development-only. Viewer is not part of the production icon runtime.
|
||||
|
||||
## 3. Type the config
|
||||
|
||||
Choose one of these two paths.
|
||||
|
||||
### With a local package installation
|
||||
|
||||
After installing the package locally, use the helper:
|
||||
|
||||
```ts
|
||||
import { defineSpriteConfig } from '@gromlab/svg-sprites'
|
||||
|
||||
export default defineSpriteConfig({
|
||||
mode: 'next@app/webpack',
|
||||
name: 'icons',
|
||||
})
|
||||
```
|
||||
|
||||
You can alternatively import `type SpriteConfig` and apply `satisfies SpriteConfig`.
|
||||
|
||||
### Without the package
|
||||
|
||||
Copy a mode-specific type directly into the config:
|
||||
|
||||
```ts
|
||||
type LocalSpriteConfig = {
|
||||
mode: 'next@app/webpack'
|
||||
name?: string
|
||||
description?: string
|
||||
input?: string | string[]
|
||||
transform?: {
|
||||
removeSize?: boolean
|
||||
replaceColors?: boolean
|
||||
addTransition?: boolean
|
||||
}
|
||||
generatedNotice?: boolean
|
||||
}
|
||||
|
||||
export default {
|
||||
mode: 'next@app/webpack',
|
||||
name: 'icons',
|
||||
} satisfies LocalSpriteConfig
|
||||
```
|
||||
140
docs/en/guides/next-pages-turbopack.md
Normal file
140
docs/en/guides/next-pages-turbopack.md
Normal file
@@ -0,0 +1,140 @@
|
||||
# Next.js Pages Router Turbopack SVG Sprite Quick Start
|
||||
|
||||
This guide targets the exact mode key `next@pages/turbopack`: a generated typed React icon for the Next.js Pages Router and Turbopack.
|
||||
|
||||
## 1. Generate the sprite
|
||||
|
||||
No package installation and no `package.json` dependency are needed. `npx` downloads the CLI temporarily, and generated runtime does not import `@gromlab/svg-sprites`.
|
||||
|
||||
Keep the config and source icons together:
|
||||
|
||||
```text
|
||||
src/ui/icons/
|
||||
├── icons/
|
||||
│ ├── check.svg
|
||||
│ └── folder.svg
|
||||
└── svg-sprite.config.ts
|
||||
```
|
||||
|
||||
Use a plain default object export with no package import:
|
||||
|
||||
```ts
|
||||
// src/ui/icons/svg-sprite.config.ts
|
||||
export default {
|
||||
mode: 'next@pages/turbopack',
|
||||
name: 'icons',
|
||||
}
|
||||
```
|
||||
|
||||
When `input` is omitted, SVG files are read from `./icons` relative to the config. A `.js` config with a default export and a `.json` config are also supported. Generate directly with:
|
||||
|
||||
```bash
|
||||
npx --yes --package=@gromlab/svg-sprites@latest svg-sprites src/ui/icons/svg-sprite.config.ts
|
||||
```
|
||||
|
||||
Generate once per invocation and keep the exact Turbopack flags on both commands:
|
||||
|
||||
```json
|
||||
{
|
||||
"scripts": {
|
||||
"sprites": "npx --yes --package=@gromlab/svg-sprites@latest svg-sprites src/ui/icons/svg-sprite.config.ts",
|
||||
"dev": "npm run sprites && next dev --turbopack",
|
||||
"build": "npm run sprites && next build --turbopack"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Do not add `predev` or `prebuild` hooks to these scripts; that would run generation twice. In CI, replace `latest` with an exact package version.
|
||||
|
||||
Generation creates a local `.gitignore`; commit that file once, but do not commit `.svg-sprite/`. Generated declarations are self-contained and do not require the package.
|
||||
|
||||
### Production usage
|
||||
|
||||
Import the generated component and icon-name list into a Pages Router page:
|
||||
|
||||
```tsx
|
||||
// src/pages/index.tsx
|
||||
import {
|
||||
IconsIcon,
|
||||
iconsIconNames,
|
||||
} from '../ui/icons/.svg-sprite/index.js'
|
||||
|
||||
export default function HomePage() {
|
||||
return (
|
||||
<main>
|
||||
<IconsIcon icon="folder" width={24} height={24} aria-label="Files" />
|
||||
<p>{iconsIconNames.length} icons available</p>
|
||||
</main>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
The component works with SSR, SSG, and client-side navigation. Turbopack resolves the generated SVG URL and CSS Module and emits a separate asset. Keep the mode and the `--turbopack` dev/build flags aligned.
|
||||
|
||||
## 2. Debug and preview
|
||||
|
||||
This section is optional. Only users who need the Viewer or icon previews should install:
|
||||
|
||||
```bash
|
||||
npm install --save-dev @gromlab/svg-sprites
|
||||
```
|
||||
|
||||
Pages Router does not require an App Router Client Component boundary. Use the React bridge directly in a page with a static loader array:
|
||||
|
||||
```tsx
|
||||
// src/pages/icon-debug.tsx
|
||||
import { SpriteViewer } from '@gromlab/svg-sprites/react'
|
||||
|
||||
const sources = [
|
||||
() => import('../ui/icons/.svg-sprite/svg-sprite.manifest.js'),
|
||||
]
|
||||
|
||||
export default function IconDebugPage() {
|
||||
return <SpriteViewer sources={sources} title="Project icons" />
|
||||
}
|
||||
```
|
||||
|
||||
Keep the page internal or development-only. Viewer is not part of the production icon runtime.
|
||||
|
||||
## 3. Type the config
|
||||
|
||||
Choose one of these two paths.
|
||||
|
||||
### With a local package installation
|
||||
|
||||
After installing the package locally, use the helper:
|
||||
|
||||
```ts
|
||||
import { defineSpriteConfig } from '@gromlab/svg-sprites'
|
||||
|
||||
export default defineSpriteConfig({
|
||||
mode: 'next@pages/turbopack',
|
||||
name: 'icons',
|
||||
})
|
||||
```
|
||||
|
||||
You can alternatively import `type SpriteConfig` and apply `satisfies SpriteConfig`.
|
||||
|
||||
### Without the package
|
||||
|
||||
Copy a mode-specific type directly into the config:
|
||||
|
||||
```ts
|
||||
type LocalSpriteConfig = {
|
||||
mode: 'next@pages/turbopack'
|
||||
name?: string
|
||||
description?: string
|
||||
input?: string | string[]
|
||||
transform?: {
|
||||
removeSize?: boolean
|
||||
replaceColors?: boolean
|
||||
addTransition?: boolean
|
||||
}
|
||||
generatedNotice?: boolean
|
||||
}
|
||||
|
||||
export default {
|
||||
mode: 'next@pages/turbopack',
|
||||
name: 'icons',
|
||||
} satisfies LocalSpriteConfig
|
||||
```
|
||||
140
docs/en/guides/next-pages-webpack.md
Normal file
140
docs/en/guides/next-pages-webpack.md
Normal file
@@ -0,0 +1,140 @@
|
||||
# Next.js Pages Router Webpack SVG Sprite Quick Start
|
||||
|
||||
This guide targets the exact mode key `next@pages/webpack`: a generated typed React icon for the Next.js Pages Router and Webpack 5.
|
||||
|
||||
## 1. Generate the sprite
|
||||
|
||||
No package installation and no `package.json` dependency are needed. `npx` downloads the CLI temporarily, and generated runtime does not import `@gromlab/svg-sprites`.
|
||||
|
||||
Keep the config adjacent to its source icons:
|
||||
|
||||
```text
|
||||
src/ui/icons/
|
||||
├── icons/
|
||||
│ ├── check.svg
|
||||
│ └── folder.svg
|
||||
└── svg-sprite.config.ts
|
||||
```
|
||||
|
||||
Use a plain default object export with no package import:
|
||||
|
||||
```ts
|
||||
// src/ui/icons/svg-sprite.config.ts
|
||||
export default {
|
||||
mode: 'next@pages/webpack',
|
||||
name: 'icons',
|
||||
}
|
||||
```
|
||||
|
||||
When `input` is omitted, SVG files are read from `./icons` relative to the config. A `.js` config with a default export and a `.json` config are also supported. Generate directly with:
|
||||
|
||||
```bash
|
||||
npx --yes --package=@gromlab/svg-sprites@latest svg-sprites src/ui/icons/svg-sprite.config.ts
|
||||
```
|
||||
|
||||
Generate once per invocation and keep the exact Webpack flags on both commands:
|
||||
|
||||
```json
|
||||
{
|
||||
"scripts": {
|
||||
"sprites": "npx --yes --package=@gromlab/svg-sprites@latest svg-sprites src/ui/icons/svg-sprite.config.ts",
|
||||
"dev": "npm run sprites && next dev --webpack",
|
||||
"build": "npm run sprites && next build --webpack"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Do not add `predev` or `prebuild` hooks to these scripts; that would run generation twice. In CI, replace `latest` with an exact package version.
|
||||
|
||||
Generation creates a local `.gitignore`; commit that file once, but do not commit `.svg-sprite/`. Generated declarations are self-contained and do not require the package.
|
||||
|
||||
### Production usage
|
||||
|
||||
Import the generated component and icon-name list into a Pages Router page:
|
||||
|
||||
```tsx
|
||||
// src/pages/index.tsx
|
||||
import {
|
||||
IconsIcon,
|
||||
iconsIconNames,
|
||||
} from '../ui/icons/.svg-sprite/index.js'
|
||||
|
||||
export default function HomePage() {
|
||||
return (
|
||||
<main>
|
||||
<IconsIcon icon="folder" width={24} height={24} aria-label="Files" />
|
||||
<p>{iconsIconNames.length} icons available</p>
|
||||
</main>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
The component works with SSR, SSG, and client-side navigation. Webpack resolves the generated SVG URL and CSS Module and emits a separate asset. Keep the mode and the `--webpack` dev/build flags aligned. If custom Next.js webpack rules process SVG through SVGR, exclude `.svg-sprite/sprite.svg` from those rules.
|
||||
|
||||
## 2. Debug and preview
|
||||
|
||||
This section is optional. Only users who need the Viewer or icon previews should install:
|
||||
|
||||
```bash
|
||||
npm install --save-dev @gromlab/svg-sprites
|
||||
```
|
||||
|
||||
Pages Router does not require an App Router Client Component boundary. Use the React bridge directly in a page with a static loader array:
|
||||
|
||||
```tsx
|
||||
// src/pages/icon-debug.tsx
|
||||
import { SpriteViewer } from '@gromlab/svg-sprites/react'
|
||||
|
||||
const sources = [
|
||||
() => import('../ui/icons/.svg-sprite/svg-sprite.manifest.js'),
|
||||
]
|
||||
|
||||
export default function IconDebugPage() {
|
||||
return <SpriteViewer sources={sources} title="Project icons" />
|
||||
}
|
||||
```
|
||||
|
||||
Keep the page internal or development-only. Viewer is not part of the production icon runtime.
|
||||
|
||||
## 3. Type the config
|
||||
|
||||
Choose one of these two paths.
|
||||
|
||||
### With a local package installation
|
||||
|
||||
After installing the package locally, use the helper:
|
||||
|
||||
```ts
|
||||
import { defineSpriteConfig } from '@gromlab/svg-sprites'
|
||||
|
||||
export default defineSpriteConfig({
|
||||
mode: 'next@pages/webpack',
|
||||
name: 'icons',
|
||||
})
|
||||
```
|
||||
|
||||
You can alternatively import `type SpriteConfig` and apply `satisfies SpriteConfig`.
|
||||
|
||||
### Without the package
|
||||
|
||||
Copy a mode-specific type directly into the config:
|
||||
|
||||
```ts
|
||||
type LocalSpriteConfig = {
|
||||
mode: 'next@pages/webpack'
|
||||
name?: string
|
||||
description?: string
|
||||
input?: string | string[]
|
||||
transform?: {
|
||||
removeSize?: boolean
|
||||
replaceColors?: boolean
|
||||
addTransition?: boolean
|
||||
}
|
||||
generatedNotice?: boolean
|
||||
}
|
||||
|
||||
export default {
|
||||
mode: 'next@pages/webpack',
|
||||
name: 'icons',
|
||||
} satisfies LocalSpriteConfig
|
||||
```
|
||||
148
docs/en/guides/react-vite.md
Normal file
148
docs/en/guides/react-vite.md
Normal file
@@ -0,0 +1,148 @@
|
||||
# React Vite SVG Sprite Quick Start
|
||||
|
||||
This guide targets the exact mode key `react@vite`: a generated typed React component with a Vite-managed SVG asset.
|
||||
|
||||
## 1. Generate the sprite
|
||||
|
||||
No package installation and no `package.json` dependency are needed. `npx` downloads the CLI temporarily, and generated runtime does not import `@gromlab/svg-sprites`.
|
||||
|
||||
Keep the config and source icons together:
|
||||
|
||||
```text
|
||||
src/ui/icons/
|
||||
├── icons/
|
||||
│ ├── check.svg
|
||||
│ └── folder.svg
|
||||
└── svg-sprite.config.ts
|
||||
```
|
||||
|
||||
Use a plain default object export with no package import:
|
||||
|
||||
```ts
|
||||
// src/ui/icons/svg-sprite.config.ts
|
||||
export default {
|
||||
mode: 'react@vite',
|
||||
name: 'icons',
|
||||
}
|
||||
```
|
||||
|
||||
When `input` is omitted, SVG files are read from `./icons` relative to the config. A `.js` config with a default export and a `.json` config are also supported. Generate directly with:
|
||||
|
||||
```bash
|
||||
npx --yes --package=@gromlab/svg-sprites@latest svg-sprites src/ui/icons/svg-sprite.config.ts
|
||||
```
|
||||
|
||||
Use the exact Vite dev/build commands and generate once per invocation:
|
||||
|
||||
```json
|
||||
{
|
||||
"scripts": {
|
||||
"sprites": "npx --yes --package=@gromlab/svg-sprites@latest svg-sprites src/ui/icons/svg-sprite.config.ts",
|
||||
"dev": "npm run sprites && vite",
|
||||
"build": "npm run sprites && tsc --noEmit && vite build"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Do not add `predev` or `prebuild` hooks to these scripts; that would run generation twice. In CI, replace `latest` with an exact package version.
|
||||
|
||||
Generation creates a local `.gitignore`; commit that file once, but do not commit `.svg-sprite/`. Generated declarations are self-contained and do not require the package.
|
||||
|
||||
### Production usage
|
||||
|
||||
Import the generated component and icon-name list directly:
|
||||
|
||||
```tsx
|
||||
// src/App.tsx
|
||||
import {
|
||||
IconsIcon,
|
||||
iconsIconNames,
|
||||
} from './ui/icons/.svg-sprite/index.js'
|
||||
|
||||
export function App() {
|
||||
return (
|
||||
<main>
|
||||
<IconsIcon icon="check" width={24} height={24} aria-label="Complete" />
|
||||
<small>{iconsIconNames.length} icons available</small>
|
||||
</main>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
`icon` is a generated union of SVG file names. Vite automatically handles the generated CSS Module and the `sprite.svg?no-inline` import, emitting the sprite as a separate asset. If your own TypeScript source imports Vite query assets, include Vite's ambient types:
|
||||
|
||||
```json
|
||||
{
|
||||
"compilerOptions": {
|
||||
"types": ["vite/client"]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 2. Debug and preview
|
||||
|
||||
This section is optional. Only users who need the Viewer or icon previews should install:
|
||||
|
||||
```bash
|
||||
npm install --save-dev @gromlab/svg-sprites
|
||||
```
|
||||
|
||||
Use the React `SpriteViewer` bridge with a static loader array. Keep every `import()` path a string literal:
|
||||
|
||||
```tsx
|
||||
// src/IconsDebugPage.tsx
|
||||
import { SpriteViewer } from '@gromlab/svg-sprites/react'
|
||||
|
||||
const sources = [
|
||||
() => import('./ui/icons/.svg-sprite/svg-sprite.manifest.js'),
|
||||
]
|
||||
|
||||
export function IconsDebugPage() {
|
||||
return <SpriteViewer sources={sources} title="Project icons" />
|
||||
}
|
||||
```
|
||||
|
||||
Keep this component on a debug route or in an internal tool. Viewer is not part of the production icon runtime.
|
||||
|
||||
## 3. Type the config
|
||||
|
||||
Choose one of these two paths.
|
||||
|
||||
### With a local package installation
|
||||
|
||||
After installing the package locally, use the helper:
|
||||
|
||||
```ts
|
||||
import { defineSpriteConfig } from '@gromlab/svg-sprites'
|
||||
|
||||
export default defineSpriteConfig({
|
||||
mode: 'react@vite',
|
||||
name: 'icons',
|
||||
})
|
||||
```
|
||||
|
||||
You can alternatively import `type SpriteConfig` and apply `satisfies SpriteConfig`.
|
||||
|
||||
### Without the package
|
||||
|
||||
Copy a mode-specific type directly into the config:
|
||||
|
||||
```ts
|
||||
type LocalSpriteConfig = {
|
||||
mode: 'react@vite'
|
||||
name?: string
|
||||
description?: string
|
||||
input?: string | string[]
|
||||
transform?: {
|
||||
removeSize?: boolean
|
||||
replaceColors?: boolean
|
||||
addTransition?: boolean
|
||||
}
|
||||
generatedNotice?: boolean
|
||||
}
|
||||
|
||||
export default {
|
||||
mode: 'react@vite',
|
||||
name: 'icons',
|
||||
} satisfies LocalSpriteConfig
|
||||
```
|
||||
156
docs/en/guides/react-webpack.md
Normal file
156
docs/en/guides/react-webpack.md
Normal file
@@ -0,0 +1,156 @@
|
||||
# React Webpack SVG Sprite Quick Start
|
||||
|
||||
This guide targets the exact mode key `react@webpack`: a generated typed React component using Webpack 5 Asset Modules and CSS Modules.
|
||||
|
||||
## 1. Generate the sprite
|
||||
|
||||
No package installation and no `package.json` dependency are needed. `npx` downloads the CLI temporarily, and generated runtime does not import `@gromlab/svg-sprites`.
|
||||
|
||||
Keep the config adjacent to its source icons:
|
||||
|
||||
```text
|
||||
src/ui/icons/
|
||||
├── icons/
|
||||
│ ├── check.svg
|
||||
│ └── folder.svg
|
||||
└── svg-sprite.config.ts
|
||||
```
|
||||
|
||||
Use a plain default object export with no package import:
|
||||
|
||||
```ts
|
||||
// src/ui/icons/svg-sprite.config.ts
|
||||
export default {
|
||||
mode: 'react@webpack',
|
||||
name: 'icons',
|
||||
}
|
||||
```
|
||||
|
||||
When `input` is omitted, SVG files are read from `./icons` relative to the config. A `.js` config with a default export and a `.json` config are also supported. Generate directly with:
|
||||
|
||||
```bash
|
||||
npx --yes --package=@gromlab/svg-sprites@latest svg-sprites src/ui/icons/svg-sprite.config.ts
|
||||
```
|
||||
|
||||
Use the exact Webpack 5 flags and generate once per invocation:
|
||||
|
||||
```json
|
||||
{
|
||||
"scripts": {
|
||||
"sprites": "npx --yes --package=@gromlab/svg-sprites@latest svg-sprites src/ui/icons/svg-sprite.config.ts",
|
||||
"dev": "npm run sprites && webpack serve --mode development",
|
||||
"build": "npm run sprites && webpack --mode production"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Do not add `predev` or `prebuild` hooks to these scripts; that would run generation twice. In CI, replace `latest` with an exact package version.
|
||||
|
||||
Generation creates a local `.gitignore`; commit that file once, but do not commit `.svg-sprite/`. Generated declarations are self-contained and do not require the package.
|
||||
|
||||
### Production usage
|
||||
|
||||
Import the generated component and icon-name list directly:
|
||||
|
||||
```tsx
|
||||
// src/App.tsx
|
||||
import {
|
||||
IconsIcon,
|
||||
iconsIconNames,
|
||||
} from './ui/icons/.svg-sprite/index.js'
|
||||
|
||||
export function App() {
|
||||
return (
|
||||
<main>
|
||||
<IconsIcon icon="folder" width={24} height={24} aria-label="Files" />
|
||||
<small>{iconsIconNames.length} icons available</small>
|
||||
</main>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
The generated component uses `new URL('../sprite.svg', import.meta.url)`, which Webpack 5 processes through Asset Modules and emits as a separate SVG asset. Exclude `.svg-sprite/sprite.svg` from SVG component or SVGR rules so they do not intercept that URL dependency.
|
||||
|
||||
The generated component also imports `react-component.module.css`. Configure `.module.css` through `css-loader` with modules enabled, plus `style-loader` or `MiniCssExtractPlugin`:
|
||||
|
||||
```js
|
||||
// webpack.config.js (relevant rule)
|
||||
export default {
|
||||
module: {
|
||||
rules: [
|
||||
{
|
||||
test: /\.module\.css$/i,
|
||||
use: ['style-loader', { loader: 'css-loader', options: { modules: true } }],
|
||||
},
|
||||
],
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
## 2. Debug and preview
|
||||
|
||||
This section is optional. Only users who need the Viewer or icon previews should install:
|
||||
|
||||
```bash
|
||||
npm install --save-dev @gromlab/svg-sprites
|
||||
```
|
||||
|
||||
Use the React `SpriteViewer` bridge with a static loader array. Keep every `import()` path a string literal so Webpack can create the chunk:
|
||||
|
||||
```tsx
|
||||
// src/IconsDebugPage.tsx
|
||||
import { SpriteViewer } from '@gromlab/svg-sprites/react'
|
||||
|
||||
const sources = [
|
||||
() => import('./ui/icons/.svg-sprite/svg-sprite.manifest.js'),
|
||||
]
|
||||
|
||||
export function IconsDebugPage() {
|
||||
return <SpriteViewer sources={sources} title="Project icons" />
|
||||
}
|
||||
```
|
||||
|
||||
Keep this component on a debug route or in an internal tool. Viewer is not part of the production icon runtime.
|
||||
|
||||
## 3. Type the config
|
||||
|
||||
Choose one of these two paths.
|
||||
|
||||
### With a local package installation
|
||||
|
||||
After installing the package locally, use the helper:
|
||||
|
||||
```ts
|
||||
import { defineSpriteConfig } from '@gromlab/svg-sprites'
|
||||
|
||||
export default defineSpriteConfig({
|
||||
mode: 'react@webpack',
|
||||
name: 'icons',
|
||||
})
|
||||
```
|
||||
|
||||
You can alternatively import `type SpriteConfig` and apply `satisfies SpriteConfig`.
|
||||
|
||||
### Without the package
|
||||
|
||||
Copy a mode-specific type directly into the config:
|
||||
|
||||
```ts
|
||||
type LocalSpriteConfig = {
|
||||
mode: 'react@webpack'
|
||||
name?: string
|
||||
description?: string
|
||||
input?: string | string[]
|
||||
transform?: {
|
||||
removeSize?: boolean
|
||||
replaceColors?: boolean
|
||||
addTransition?: boolean
|
||||
}
|
||||
generatedNotice?: boolean
|
||||
}
|
||||
|
||||
export default {
|
||||
mode: 'react@webpack',
|
||||
name: 'icons',
|
||||
} satisfies LocalSpriteConfig
|
||||
```
|
||||
156
docs/en/guides/standalone-vite.md
Normal file
156
docs/en/guides/standalone-vite.md
Normal file
@@ -0,0 +1,156 @@
|
||||
# Standalone Vite SVG Sprite Quick Start
|
||||
|
||||
This guide targets the exact mode key `standalone@vite`: a native generated Web Component with Vite-managed SVG assets.
|
||||
|
||||
## 1. Generate the sprite
|
||||
|
||||
No package installation and no `package.json` dependency are needed. `npx` downloads the CLI temporarily, and generated runtime does not import `@gromlab/svg-sprites`.
|
||||
|
||||
Keep the config and source icons together:
|
||||
|
||||
```text
|
||||
src/ui/icons/
|
||||
├── icons/
|
||||
│ ├── check.svg
|
||||
│ └── folder.svg
|
||||
└── svg-sprite.config.ts
|
||||
```
|
||||
|
||||
Use a plain default object export with no package import:
|
||||
|
||||
```ts
|
||||
// src/ui/icons/svg-sprite.config.ts
|
||||
export default {
|
||||
mode: 'standalone@vite',
|
||||
name: 'icons',
|
||||
}
|
||||
```
|
||||
|
||||
When `input` is omitted, SVG files are read from `./icons` relative to the config. A `.js` config with a default export and a `.json` config are also supported. Generate once directly with:
|
||||
|
||||
```bash
|
||||
npx --yes --package=@gromlab/svg-sprites@latest svg-sprites src/ui/icons/svg-sprite.config.ts
|
||||
```
|
||||
|
||||
Use the exact Vite dev/build commands and generate once per invocation:
|
||||
|
||||
```json
|
||||
{
|
||||
"scripts": {
|
||||
"sprites": "npx --yes --package=@gromlab/svg-sprites@latest svg-sprites src/ui/icons/svg-sprite.config.ts",
|
||||
"dev": "npm run sprites && vite",
|
||||
"build": "npm run sprites && vite build"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Do not add `predev` or `prebuild` hooks to these scripts; that would run generation twice. In CI, replace `latest` with an exact package version.
|
||||
|
||||
Generation creates a local `.gitignore`; commit that file once, but do not commit `.svg-sprite/`. The generated JavaScript and declarations live together, and the declarations are self-contained: they do not require `@gromlab/svg-sprites`.
|
||||
|
||||
### Production usage
|
||||
|
||||
Register the generated element once, then use `<icons-icon>`:
|
||||
|
||||
```ts
|
||||
// src/main.ts
|
||||
import {
|
||||
defineIconsIconElement,
|
||||
iconsIconNames,
|
||||
} from './ui/icons/.svg-sprite/index.js'
|
||||
|
||||
defineIconsIconElement()
|
||||
console.log('Available icons:', iconsIconNames)
|
||||
```
|
||||
|
||||
```html
|
||||
<icons-icon icon="check" role="img" aria-label="Complete"></icons-icon>
|
||||
```
|
||||
|
||||
The host is `1em` by `1em`, so `font-size` controls its default size. Transformed colors use `currentColor` and custom properties such as `--icon-color-1`:
|
||||
|
||||
```css
|
||||
icons-icon {
|
||||
font-size: 24px;
|
||||
color: #2563eb;
|
||||
--icon-color-2: #dbeafe;
|
||||
}
|
||||
```
|
||||
|
||||
Vite handles the generated `sprite.svg?no-inline` import automatically and emits a separate asset. If your own TypeScript source imports Vite query assets, include Vite's ambient types:
|
||||
|
||||
```json
|
||||
{
|
||||
"compilerOptions": {
|
||||
"types": ["vite/client"]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 2. Debug and preview
|
||||
|
||||
This section is optional. Only users who need the Viewer or icon previews should install:
|
||||
|
||||
```bash
|
||||
npm install --save-dev @gromlab/svg-sprites
|
||||
```
|
||||
|
||||
Register the Viewer element, import its type, and assign the generated JavaScript manifest to `sources`:
|
||||
|
||||
```ts
|
||||
import '@gromlab/svg-sprites/viewer/element'
|
||||
import type { SpriteViewerElement } from '@gromlab/svg-sprites/viewer'
|
||||
import spriteManifest from './ui/icons/.svg-sprite/svg-sprite.manifest.js'
|
||||
|
||||
document.querySelector<HTMLDivElement>('#debug')!.innerHTML = `
|
||||
<gromlab-sprite-viewer viewer-title="Project icons"></gromlab-sprite-viewer>
|
||||
`
|
||||
|
||||
const viewer = document.querySelector<SpriteViewerElement>('gromlab-sprite-viewer')!
|
||||
viewer.sources = [spriteManifest]
|
||||
```
|
||||
|
||||
Keep this code on a debug route or in an internal tool. Viewer is not part of the production icon runtime.
|
||||
|
||||
## 3. Type the config
|
||||
|
||||
Choose one of these two paths.
|
||||
|
||||
### With a local package installation
|
||||
|
||||
After installing the package locally, use the helper:
|
||||
|
||||
```ts
|
||||
import { defineSpriteConfig } from '@gromlab/svg-sprites'
|
||||
|
||||
export default defineSpriteConfig({
|
||||
mode: 'standalone@vite',
|
||||
name: 'icons',
|
||||
})
|
||||
```
|
||||
|
||||
You can alternatively import `type SpriteConfig` and apply `satisfies SpriteConfig`.
|
||||
|
||||
### Without the package
|
||||
|
||||
Copy a mode-specific type directly into the config:
|
||||
|
||||
```ts
|
||||
type LocalSpriteConfig = {
|
||||
mode: 'standalone@vite'
|
||||
name?: string
|
||||
description?: string
|
||||
input?: string | string[]
|
||||
transform?: {
|
||||
removeSize?: boolean
|
||||
replaceColors?: boolean
|
||||
addTransition?: boolean
|
||||
}
|
||||
generatedNotice?: boolean
|
||||
}
|
||||
|
||||
export default {
|
||||
mode: 'standalone@vite',
|
||||
name: 'icons',
|
||||
} satisfies LocalSpriteConfig
|
||||
```
|
||||
143
docs/en/guides/standalone-webpack.md
Normal file
143
docs/en/guides/standalone-webpack.md
Normal file
@@ -0,0 +1,143 @@
|
||||
# Standalone Webpack SVG Sprite Quick Start
|
||||
|
||||
This guide targets the exact mode key `standalone@webpack`: a native generated Web Component using Webpack 5 Asset Modules.
|
||||
|
||||
## 1. Generate the sprite
|
||||
|
||||
No package installation and no `package.json` dependency are needed. `npx` downloads the CLI temporarily, and generated runtime does not import `@gromlab/svg-sprites`.
|
||||
|
||||
Keep the config adjacent to its source icons:
|
||||
|
||||
```text
|
||||
src/ui/icons/
|
||||
├── icons/
|
||||
│ ├── check.svg
|
||||
│ └── folder.svg
|
||||
└── svg-sprite.config.ts
|
||||
```
|
||||
|
||||
Use a plain default object export with no package import:
|
||||
|
||||
```ts
|
||||
// src/ui/icons/svg-sprite.config.ts
|
||||
export default {
|
||||
mode: 'standalone@webpack',
|
||||
name: 'icons',
|
||||
}
|
||||
```
|
||||
|
||||
When `input` is omitted, SVG files are read from `./icons` relative to the config. A `.js` config with a default export and a `.json` config are also supported. Generate directly with:
|
||||
|
||||
```bash
|
||||
npx --yes --package=@gromlab/svg-sprites@latest svg-sprites src/ui/icons/svg-sprite.config.ts
|
||||
```
|
||||
|
||||
Use the exact Webpack 5 flags and generate once per invocation:
|
||||
|
||||
```json
|
||||
{
|
||||
"scripts": {
|
||||
"sprites": "npx --yes --package=@gromlab/svg-sprites@latest svg-sprites src/ui/icons/svg-sprite.config.ts",
|
||||
"dev": "npm run sprites && webpack serve --mode development",
|
||||
"build": "npm run sprites && webpack --mode production"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Do not add `predev` or `prebuild` hooks to these scripts; that would run generation twice. In CI, replace `latest` with an exact package version.
|
||||
|
||||
Generation creates a local `.gitignore`; commit that file once, but do not commit `.svg-sprite/`. Generated declarations are self-contained and do not require the package.
|
||||
|
||||
### Production usage
|
||||
|
||||
Register the generated element once, then use `<icons-icon>`:
|
||||
|
||||
```ts
|
||||
// src/main.ts
|
||||
import {
|
||||
defineIconsIconElement,
|
||||
iconsIconNames,
|
||||
} from './ui/icons/.svg-sprite/index.js'
|
||||
|
||||
defineIconsIconElement()
|
||||
console.log('Available icons:', iconsIconNames)
|
||||
```
|
||||
|
||||
```html
|
||||
<icons-icon
|
||||
icon="check"
|
||||
role="img"
|
||||
aria-label="Complete"
|
||||
style="font-size:24px;color:#16a34a;--icon-color-1:#16a34a"
|
||||
></icons-icon>
|
||||
```
|
||||
|
||||
The generated facade uses `new URL('./sprite.svg', import.meta.url)`, which Webpack 5 processes through Asset Modules and emits as a separate asset. If the project has SVG-to-component or SVGR rules, exclude `.svg-sprite/sprite.svg` from them so they do not intercept this URL dependency. Check `output.publicPath` if the emitted URL is wrong.
|
||||
|
||||
## 2. Debug and preview
|
||||
|
||||
This section is optional. Only users who need the Viewer or icon previews should install:
|
||||
|
||||
```bash
|
||||
npm install --save-dev @gromlab/svg-sprites
|
||||
```
|
||||
|
||||
Register the Viewer element, import its type, and assign the generated JavaScript manifest to `sources`:
|
||||
|
||||
```ts
|
||||
import '@gromlab/svg-sprites/viewer/element'
|
||||
import type { SpriteViewerElement } from '@gromlab/svg-sprites/viewer'
|
||||
import spriteManifest from './ui/icons/.svg-sprite/svg-sprite.manifest.js'
|
||||
|
||||
document.querySelector<HTMLDivElement>('#debug')!.innerHTML = `
|
||||
<gromlab-sprite-viewer viewer-title="Project icons"></gromlab-sprite-viewer>
|
||||
`
|
||||
|
||||
const viewer = document.querySelector<SpriteViewerElement>('gromlab-sprite-viewer')!
|
||||
viewer.sources = [spriteManifest]
|
||||
```
|
||||
|
||||
Keep this code on a debug route or in an internal tool. Viewer is not part of the production icon runtime.
|
||||
|
||||
## 3. Type the config
|
||||
|
||||
Choose one of these two paths.
|
||||
|
||||
### With a local package installation
|
||||
|
||||
After installing the package locally, use the helper:
|
||||
|
||||
```ts
|
||||
import { defineSpriteConfig } from '@gromlab/svg-sprites'
|
||||
|
||||
export default defineSpriteConfig({
|
||||
mode: 'standalone@webpack',
|
||||
name: 'icons',
|
||||
})
|
||||
```
|
||||
|
||||
You can alternatively import `type SpriteConfig` and apply `satisfies SpriteConfig`.
|
||||
|
||||
### Without the package
|
||||
|
||||
Copy a mode-specific type directly into the config:
|
||||
|
||||
```ts
|
||||
type LocalSpriteConfig = {
|
||||
mode: 'standalone@webpack'
|
||||
name?: string
|
||||
description?: string
|
||||
input?: string | string[]
|
||||
transform?: {
|
||||
removeSize?: boolean
|
||||
replaceColors?: boolean
|
||||
addTransition?: boolean
|
||||
}
|
||||
generatedNotice?: boolean
|
||||
}
|
||||
|
||||
export default {
|
||||
mode: 'standalone@webpack',
|
||||
name: 'icons',
|
||||
} satisfies LocalSpriteConfig
|
||||
```
|
||||
171
docs/en/guides/standalone.md
Normal file
171
docs/en/guides/standalone.md
Normal file
@@ -0,0 +1,171 @@
|
||||
# Standalone SVG Sprite Quick Start
|
||||
|
||||
This guide targets the exact mode key `standalone`: static HTML or a custom asset pipeline with no generated JavaScript facade.
|
||||
|
||||
## 1. Generate the sprite
|
||||
|
||||
No package installation and no `package.json` dependency are needed. `npx` downloads the CLI temporarily, and generated runtime does not import `@gromlab/svg-sprites`; bare `standalone` does not generate a JavaScript runtime at all.
|
||||
|
||||
Keep the config next to its source icons:
|
||||
|
||||
```text
|
||||
src/ui/icons/
|
||||
├── icons/
|
||||
│ ├── check.svg
|
||||
│ └── folder.svg
|
||||
└── svg-sprite.config.json
|
||||
```
|
||||
|
||||
Create a JSON config:
|
||||
|
||||
```json
|
||||
{
|
||||
"mode": "standalone",
|
||||
"name": "icons"
|
||||
}
|
||||
```
|
||||
|
||||
When `input` is omitted, the generator reads `./icons` next to the config.
|
||||
|
||||
To include SVG files from nested directories, set one glob pattern:
|
||||
|
||||
```json
|
||||
{
|
||||
"mode": "standalone",
|
||||
"name": "icons",
|
||||
"input": "../assets/icons/**/*.svg"
|
||||
}
|
||||
```
|
||||
|
||||
An array can mix folders, individual SVG files, and glob patterns:
|
||||
|
||||
```json
|
||||
{
|
||||
"mode": "standalone",
|
||||
"name": "icons",
|
||||
"input": [
|
||||
"../assets/icons",
|
||||
"../features/profile/user.svg",
|
||||
"../features/admin/*.svg"
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
All relative paths start at the config directory. Pass the config path explicitly:
|
||||
|
||||
```bash
|
||||
npx --yes --package=@gromlab/svg-sprites@latest svg-sprites src/ui/icons/svg-sprite.config.json
|
||||
```
|
||||
|
||||
For repeatable local commands, the same temporary CLI can be used from a script:
|
||||
|
||||
```json
|
||||
{
|
||||
"scripts": {
|
||||
"sprites": "npx --yes --package=@gromlab/svg-sprites@latest svg-sprites src/ui/icons/svg-sprite.config.json"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Run that script once from your existing dev/build pipeline. If you use a `predev` or `prebuild` hook instead, do not also call `npm run sprites` inside the corresponding script. Bare `standalone` has no bundler-specific dev or build flag. In CI, replace `latest` with an exact package version.
|
||||
|
||||
Bare `standalone` does not create or modify `.gitignore`; the application decides whether `.svg-sprite/` is committed or ignored. It emits no declarations, facade, or component. Generated declarations in typed modes are self-contained and do not require the package.
|
||||
|
||||
### Production usage
|
||||
|
||||
The application owns the public URL, versioning, and cache policy. Copy both generated assets into the deploy output:
|
||||
|
||||
```bash
|
||||
cp src/ui/icons/.svg-sprite/sprite.svg public/assets/icons.svg
|
||||
cp src/ui/icons/.svg-sprite/svg-sprite.manifest.json public/assets/icons.manifest.json
|
||||
```
|
||||
|
||||
Use the published URL manually:
|
||||
|
||||
```html
|
||||
<svg width="24" height="24" role="img" aria-label="Complete">
|
||||
<use href="/assets/icons.svg#check"></use>
|
||||
</svg>
|
||||
```
|
||||
|
||||
Safe icon names normally match their fragment IDs. Names containing spaces or other SVG-ID-unsafe characters receive a generated ID; read that icon's `id` from `icons.manifest.json` instead of constructing the fragment yourself.
|
||||
|
||||
## 2. Debug and preview
|
||||
|
||||
This section is optional. Only install the package locally if you need the debug Viewer or an icon preview:
|
||||
|
||||
```bash
|
||||
npm install --save-dev @gromlab/svg-sprites
|
||||
```
|
||||
|
||||
Without a bundler, self-host the browser bundle by copying it from `node_modules` into the deploy output:
|
||||
|
||||
```bash
|
||||
cp node_modules/@gromlab/svg-sprites/dist/viewer-element.js public/debug/viewer-element.js
|
||||
```
|
||||
|
||||
Then provide both public asset URLs through HTML attributes:
|
||||
|
||||
```html
|
||||
<script type="module" src="/debug/viewer-element.js"></script>
|
||||
|
||||
<gromlab-sprite-viewer
|
||||
viewer-title="Project icons"
|
||||
manifest-url="/assets/icons.manifest.json"
|
||||
sprite-url="/assets/icons.svg"
|
||||
></gromlab-sprite-viewer>
|
||||
```
|
||||
|
||||
For a quick preview, a pinned CDN file can replace the self-hosted script:
|
||||
|
||||
```html
|
||||
<script
|
||||
type="module"
|
||||
src="https://unpkg.com/@gromlab/svg-sprites@1.1.5/dist/viewer-element.js"
|
||||
></script>
|
||||
```
|
||||
|
||||
Self-host the file for controlled environments and pin the CDN version if you use the alternative. Viewer is optional tooling, not part of the production icon runtime.
|
||||
|
||||
## 3. Type the config
|
||||
|
||||
This guide uses a JSON config, which works without TypeScript types. If config autocomplete is needed, replace `svg-sprite.config.json` with `svg-sprite.config.ts` and choose one of these approaches.
|
||||
|
||||
### With a local package installation
|
||||
|
||||
After installing the package locally, use the helper:
|
||||
|
||||
```ts
|
||||
import { defineSpriteConfig } from '@gromlab/svg-sprites'
|
||||
|
||||
export default defineSpriteConfig({
|
||||
mode: 'standalone',
|
||||
name: 'icons',
|
||||
})
|
||||
```
|
||||
|
||||
You can alternatively import `type SpriteConfig` and apply `satisfies SpriteConfig`.
|
||||
|
||||
### Without the package
|
||||
|
||||
Keep a narrow local type directly in the config:
|
||||
|
||||
```ts
|
||||
type LocalSpriteConfig = {
|
||||
mode: 'standalone'
|
||||
name?: string
|
||||
description?: string
|
||||
input?: string | string[]
|
||||
transform?: {
|
||||
removeSize?: boolean
|
||||
replaceColors?: boolean
|
||||
addTransition?: boolean
|
||||
}
|
||||
generatedNotice?: boolean
|
||||
}
|
||||
|
||||
export default {
|
||||
mode: 'standalone',
|
||||
name: 'icons',
|
||||
} satisfies LocalSpriteConfig
|
||||
```
|
||||
@@ -1,113 +1,4 @@
|
||||
# Next.js App Router
|
||||
# Next.js App Router Guides Moved
|
||||
|
||||
[← Back to home](../../README.md)
|
||||
|
||||
Two explicit modes are supported:
|
||||
|
||||
| Bundler | Mode key |
|
||||
|---|---|
|
||||
| Turbopack | `next@app/turbopack` |
|
||||
| Webpack 5 | `next@app/webpack` |
|
||||
|
||||
## 1. Install the package
|
||||
|
||||
```bash
|
||||
npm install --save-dev @gromlab/svg-sprites
|
||||
```
|
||||
|
||||
## 2. Create a sprite module
|
||||
|
||||
```text
|
||||
src/ui/file-manager/svg-sprite/
|
||||
├── icons/
|
||||
│ ├── check.svg
|
||||
│ └── folder.svg
|
||||
├── index.ts
|
||||
└── svg-sprite.config.ts
|
||||
```
|
||||
|
||||
```ts
|
||||
// src/ui/file-manager/svg-sprite/svg-sprite.config.ts
|
||||
import { defineSpriteConfig } from '@gromlab/svg-sprites'
|
||||
|
||||
export default defineSpriteConfig({
|
||||
mode: 'next@app/turbopack',
|
||||
name: 'file-manager',
|
||||
description: 'File manager icons',
|
||||
})
|
||||
```
|
||||
|
||||
The root barrel is application-owned:
|
||||
|
||||
```ts
|
||||
// src/ui/file-manager/svg-sprite/index.ts
|
||||
export * from './.svg-sprite'
|
||||
```
|
||||
|
||||
## 3. Add generation
|
||||
|
||||
For Turbopack:
|
||||
|
||||
```json
|
||||
{
|
||||
"scripts": {
|
||||
"sprite:file-manager": "svg-sprites src/ui/file-manager/svg-sprite/svg-sprite.config.ts",
|
||||
"predev": "npm run sprite:file-manager",
|
||||
"prebuild": "npm run sprite:file-manager"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
For Webpack, replace the mode key with `next@app/webpack`.
|
||||
|
||||
Run the first generation before importing the generated module:
|
||||
|
||||
```bash
|
||||
npm run sprite:file-manager
|
||||
```
|
||||
|
||||
## 4. Use it in a Server Component
|
||||
|
||||
The generated component does not contain `'use client'`, so it can be imported directly into `page.tsx` or `layout.tsx`:
|
||||
|
||||
```tsx
|
||||
import { FileManagerIcon } from '@/ui/file-manager/svg-sprite'
|
||||
|
||||
export default function Page() {
|
||||
return (
|
||||
<main>
|
||||
<FileManagerIcon icon="folder" width={24} height={24} />
|
||||
</main>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
Next.js emits a separate SVG asset with a content hash. The same generated code is used during SSR and in the browser, with no URL mismatch.
|
||||
|
||||
## 5. Add SpriteViewer
|
||||
|
||||
The viewer is interactive, so it requires a separate Client Component boundary:
|
||||
|
||||
```tsx
|
||||
'use client'
|
||||
|
||||
import { SpriteViewer } from '@gromlab/svg-sprites/react'
|
||||
|
||||
const sources = [
|
||||
() => import('@/ui/file-manager/svg-sprite/.svg-sprite/svg-sprite.manifest.js'),
|
||||
]
|
||||
|
||||
export default function SpritesPage() {
|
||||
return <SpriteViewer sources={sources} />
|
||||
}
|
||||
```
|
||||
|
||||
## Verify the bundler
|
||||
|
||||
Run the project's build script configured for the selected bundler:
|
||||
|
||||
```bash
|
||||
npm run build
|
||||
```
|
||||
|
||||
The build script and the generator mode key must target the same bundler.
|
||||
- [App Router + Turbopack](guides/next-app-turbopack.md)
|
||||
- [App Router + Webpack](guides/next-app-webpack.md)
|
||||
|
||||
@@ -1,105 +1,4 @@
|
||||
# Next.js Pages Router
|
||||
# Next.js Pages Router Guides Moved
|
||||
|
||||
[← Back to home](../../README.md)
|
||||
|
||||
Two explicit modes are supported:
|
||||
|
||||
| Bundler | Mode key |
|
||||
|---|---|
|
||||
| Turbopack | `next@pages/turbopack` |
|
||||
| Webpack 5 | `next@pages/webpack` |
|
||||
|
||||
## 1. Install the package
|
||||
|
||||
```bash
|
||||
npm install --save-dev @gromlab/svg-sprites
|
||||
```
|
||||
|
||||
## 2. Create a sprite module
|
||||
|
||||
```text
|
||||
src/ui/file-manager/svg-sprite/
|
||||
├── icons/
|
||||
│ ├── check.svg
|
||||
│ └── folder.svg
|
||||
├── index.ts
|
||||
└── svg-sprite.config.ts
|
||||
```
|
||||
|
||||
```ts
|
||||
// src/ui/file-manager/svg-sprite/svg-sprite.config.ts
|
||||
import { defineSpriteConfig } from '@gromlab/svg-sprites'
|
||||
|
||||
export default defineSpriteConfig({
|
||||
mode: 'next@pages/webpack',
|
||||
name: 'file-manager',
|
||||
description: 'File manager icons',
|
||||
})
|
||||
```
|
||||
|
||||
The root barrel is application-owned:
|
||||
|
||||
```ts
|
||||
// src/ui/file-manager/svg-sprite/index.ts
|
||||
export * from './.svg-sprite'
|
||||
```
|
||||
|
||||
## 3. Add generation
|
||||
|
||||
```json
|
||||
{
|
||||
"scripts": {
|
||||
"sprite:file-manager": "svg-sprites src/ui/file-manager/svg-sprite/svg-sprite.config.ts",
|
||||
"predev": "npm run sprite:file-manager",
|
||||
"prebuild": "npm run sprite:file-manager"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
For Turbopack, replace the mode key with `next@pages/turbopack`.
|
||||
|
||||
Run the first generation before importing the generated module:
|
||||
|
||||
```bash
|
||||
npm run sprite:file-manager
|
||||
```
|
||||
|
||||
## 4. Use it on a page
|
||||
|
||||
```tsx
|
||||
import { FileManagerIcon } from '@/ui/file-manager/svg-sprite'
|
||||
|
||||
export default function FilesPage() {
|
||||
return <FileManagerIcon icon="folder" width={24} height={24} />
|
||||
}
|
||||
|
||||
export function getServerSideProps() {
|
||||
return { props: {} }
|
||||
}
|
||||
```
|
||||
|
||||
The component works the same way with SSR, SSG, and client-side navigation. Next.js emits a separate SVG asset with a content hash.
|
||||
|
||||
## 5. Add SpriteViewer
|
||||
|
||||
```tsx
|
||||
import { SpriteViewer } from '@gromlab/svg-sprites/react'
|
||||
|
||||
const sources = [
|
||||
() => import('@/ui/file-manager/svg-sprite/.svg-sprite/svg-sprite.manifest.js'),
|
||||
]
|
||||
|
||||
export default function SpritesPage() {
|
||||
return <SpriteViewer sources={sources} />
|
||||
}
|
||||
```
|
||||
|
||||
## Verify the bundler
|
||||
|
||||
Run the project's build script configured for the selected bundler:
|
||||
|
||||
```bash
|
||||
npm run build
|
||||
```
|
||||
|
||||
The build script and the generator mode key must target the same bundler.
|
||||
- [Pages Router + Turbopack](guides/next-pages-turbopack.md)
|
||||
- [Pages Router + Webpack](guides/next-pages-webpack.md)
|
||||
|
||||
@@ -1,147 +1,3 @@
|
||||
# Programmatic API
|
||||
# Programmatic API Moved
|
||||
|
||||
[← Back to home](../../README.md)
|
||||
|
||||
The package is ESM-only and provides one Node.js generation API. The framework-neutral Viewer is available from `@gromlab/svg-sprites/viewer`, its auto-register entry from `@gromlab/svg-sprites/viewer/element`, and the React bridge from `@gromlab/svg-sprites/react`.
|
||||
|
||||
## `generateSprite`
|
||||
|
||||
```ts
|
||||
import { generateSprite } from '@gromlab/svg-sprites'
|
||||
|
||||
const result = await generateSprite(
|
||||
'src/ui/file-manager/svg-sprite/svg-sprite.config.ts',
|
||||
)
|
||||
```
|
||||
|
||||
For static standalone mode, use `result.spritePath` in a build script to publish the
|
||||
SVG under an application URL:
|
||||
|
||||
```ts
|
||||
import { copyFile } from 'node:fs/promises'
|
||||
|
||||
const result = await generateSprite('src/sprite/svg-sprite.config.ts', {
|
||||
mode: 'standalone',
|
||||
})
|
||||
await copyFile(result.spritePath, 'dist/app-icons/sprite.svg')
|
||||
```
|
||||
|
||||
`spritePath` is a filesystem path, not a browser URL. A deployment-neutral JSON
|
||||
manifest is available through `result.manifestPath` and is copied independently.
|
||||
|
||||
The first argument accepts the full path to an explicitly selected `.ts`, `.js`, or `.json` config file with any name. Passing a directory enables config-less mode and uses that directory as the sprite module root.
|
||||
|
||||
The second argument contains optional overrides and always takes precedence over the config:
|
||||
|
||||
```ts
|
||||
await generateSprite('src/ui/file-manager/svg-sprite/custom-config.json', {
|
||||
mode: 'react@webpack',
|
||||
name: 'documents',
|
||||
inputFolder: './assets',
|
||||
inputFiles: ['../../shared/search.svg'],
|
||||
transform: {
|
||||
addTransition: false,
|
||||
},
|
||||
generatedNotice: false,
|
||||
})
|
||||
```
|
||||
|
||||
Configuration is resolved in this order:
|
||||
|
||||
```text
|
||||
defaults → config → API overrides
|
||||
```
|
||||
|
||||
For fully programmatic generation, pass a directory and provide the required settings as overrides:
|
||||
|
||||
```ts
|
||||
await generateSprite('src/ui/file-manager/svg-sprite', {
|
||||
mode: 'react@vite',
|
||||
name: 'file-manager',
|
||||
inputFiles: [
|
||||
'../../shared/search.svg',
|
||||
'../../shared/settings.svg',
|
||||
],
|
||||
})
|
||||
```
|
||||
|
||||
## Configuration
|
||||
|
||||
```ts
|
||||
import { defineSpriteConfig } from '@gromlab/svg-sprites'
|
||||
|
||||
export default defineSpriteConfig({
|
||||
mode: 'react@vite',
|
||||
name: 'file-manager',
|
||||
description: 'File manager icons',
|
||||
inputFolder: './icons',
|
||||
inputFiles: ['../../shared/check.svg'],
|
||||
transform: {
|
||||
removeSize: true,
|
||||
replaceColors: true,
|
||||
addTransition: true,
|
||||
},
|
||||
generatedNotice: true,
|
||||
})
|
||||
```
|
||||
|
||||
`defineSpriteConfig` is an identity helper for TypeScript autocomplete. JavaScript can export the same object with `export default`, while JSON contains the object directly.
|
||||
|
||||
## Specialized wrappers
|
||||
|
||||
The specialized functions are available as wrappers around `generateSprite`:
|
||||
|
||||
```ts
|
||||
import { generateNextSprite, generateReactSprite } from '@gromlab/svg-sprites'
|
||||
|
||||
await generateReactSprite('path/to/config.ts', 'vite')
|
||||
await generateNextSprite('path/to/config.ts', {
|
||||
router: 'app',
|
||||
bundler: 'turbopack',
|
||||
})
|
||||
```
|
||||
|
||||
An explicitly supplied target overrides `mode` from the file. Prefer `generateSprite` in new code.
|
||||
|
||||
## Config API
|
||||
|
||||
```ts
|
||||
import {
|
||||
loadSpriteConfig,
|
||||
resolveSpriteConfig,
|
||||
validateSpriteConfig,
|
||||
} from '@gromlab/svg-sprites'
|
||||
```
|
||||
|
||||
- `loadSpriteConfig(file)` loads an explicitly selected `.ts`, `.js`, or `.json` file.
|
||||
- `validateSpriteConfig(value)` performs runtime validation.
|
||||
- `resolveSpriteConfig(root, config, overrides)` merges values, applies defaults, and resolves paths relative to `root`.
|
||||
|
||||
## Low-level compiler
|
||||
|
||||
```ts
|
||||
import {
|
||||
compileSprite,
|
||||
compileSpriteContent,
|
||||
createShapeTransform,
|
||||
} from '@gromlab/svg-sprites'
|
||||
```
|
||||
|
||||
These functions are intended for custom orchestration. Standard generation should use `generateSprite`.
|
||||
|
||||
## Viewer runtime
|
||||
|
||||
```ts
|
||||
import '@gromlab/svg-sprites/viewer/element'
|
||||
import type { SpriteViewerElement } from '@gromlab/svg-sprites/viewer'
|
||||
```
|
||||
|
||||
The browser entry registers `<gromlab-sprite-viewer>`. Bare standalone can also load the self-contained `dist/viewer-element.js` without a bundler.
|
||||
|
||||
The React bridge keeps the component API:
|
||||
|
||||
```tsx
|
||||
import { SpriteViewer } from '@gromlab/svg-sprites/react'
|
||||
```
|
||||
|
||||
`SpriteViewer` accepts generated manifests, remote standalone sources, lazy loaders, or an `import.meta.glob` result. The React entry contains `'use client'` and is intended for debug tools; production components are imported from local sprite modules.
|
||||
The canonical document is now the [programmatic API](reference/programmatic-api.md).
|
||||
|
||||
@@ -1,125 +1,3 @@
|
||||
# React + Vite
|
||||
# React + Vite Guide Moved
|
||||
|
||||
[← Back to home](../../README.md)
|
||||
|
||||
A quick guide to installing and using SVG sprites in a React and Vite project.
|
||||
|
||||
The result is a typed React component and a separate cacheable SVG asset.
|
||||
|
||||
## 1. Install the package
|
||||
|
||||
```bash
|
||||
npm install --save-dev @gromlab/svg-sprites
|
||||
```
|
||||
|
||||
## 2. Create the sprite directory
|
||||
|
||||
```text
|
||||
src/ui/file-manager/svg-sprite/
|
||||
├── icons/
|
||||
│ ├── check.svg
|
||||
│ └── folder.svg
|
||||
├── index.ts
|
||||
└── svg-sprite.config.ts
|
||||
```
|
||||
|
||||
Place the source SVG files in `icons/`.
|
||||
|
||||
## 3. Add the configuration
|
||||
|
||||
```ts
|
||||
// src/ui/file-manager/svg-sprite/svg-sprite.config.ts
|
||||
import { defineSpriteConfig } from '@gromlab/svg-sprites'
|
||||
|
||||
export default defineSpriteConfig({
|
||||
mode: 'react@vite',
|
||||
name: 'file-manager',
|
||||
description: 'File manager icons',
|
||||
})
|
||||
```
|
||||
|
||||
The root barrel is application-owned and explicitly re-exports the generated API:
|
||||
|
||||
```ts
|
||||
// src/ui/file-manager/svg-sprite/index.ts
|
||||
export * from './.svg-sprite'
|
||||
```
|
||||
|
||||
By default, SVG files are loaded from `./icons`. You can add shared icons from other directories through `inputFiles`: the directory and file list are combined into a single sprite.
|
||||
|
||||
The complete list of options is available under [Unified configuration](reference.md#unified-configuration).
|
||||
|
||||
## 4. Add generation to package.json
|
||||
|
||||
```json
|
||||
{
|
||||
"scripts": {
|
||||
"sprite:file-manager": "svg-sprites src/ui/file-manager/svg-sprite/svg-sprite.config.ts",
|
||||
"predev": "npm run sprite:file-manager",
|
||||
"prebuild": "npm run sprite:file-manager",
|
||||
"pretypecheck": "npm run sprite:file-manager"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Generated files are excluded from Git, so generation must run before `dev`, `build`, and `typecheck`.
|
||||
|
||||
First run:
|
||||
|
||||
```bash
|
||||
npm run sprite:file-manager
|
||||
```
|
||||
|
||||
## 5. Use the component
|
||||
|
||||
The name `file-manager` is converted to `FileManagerIcon`:
|
||||
|
||||
```tsx
|
||||
import { FileManagerIcon } from './svg-sprite'
|
||||
|
||||
export const OpenFolderButton = () => (
|
||||
<button type="button">
|
||||
<FileManagerIcon icon="folder" width={24} height={24} />
|
||||
Open
|
||||
</button>
|
||||
)
|
||||
```
|
||||
|
||||
TypeScript checks the `icon` value against the file names:
|
||||
|
||||
```tsx
|
||||
<FileManagerIcon icon="check" /> // valid
|
||||
<FileManagerIcon icon="unknown" /> // TypeScript error
|
||||
```
|
||||
|
||||
Types, rendering methods, and color controls are described in the [technical reference](reference.md#react-component-and-typescript).
|
||||
|
||||
Vite emits the sprite as a separate file named like `assets/sprite-<hash>.svg`. SVG path data is not included in JavaScript.
|
||||
|
||||
## 6. Add a debug page
|
||||
|
||||
After integrating the icons, you can display all React sprites with `SpriteViewer`:
|
||||
|
||||
```tsx
|
||||
import { SpriteViewer } from '@gromlab/svg-sprites/react'
|
||||
import type { SpriteManifestModule } from '@gromlab/svg-sprites/react'
|
||||
|
||||
const sources = import.meta.glob<SpriteManifestModule>(
|
||||
'/src/**/svg-sprite/.svg-sprite/svg-sprite.manifest.js',
|
||||
)
|
||||
|
||||
export const IconsDebugPage = () => (
|
||||
<SpriteViewer sources={sources} title="Project icons" />
|
||||
)
|
||||
```
|
||||
|
||||
Vite automatically finds the generated manifest for each React sprite. The `import.meta.glob` pattern must be a string literal, and generation must run before Vite starts.
|
||||
|
||||
Only include the Viewer on a debug route or in an internal tool.
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
- Missing `.svg-sprite/index.js`: run `npm run sprite:file-manager`.
|
||||
- The Viewer cannot find the sprite: check the glob path to `.svg-sprite/svg-sprite.manifest.js`.
|
||||
- `Refusing to overwrite a user file` error: there is a user file at a generated path.
|
||||
- The icon does not change color: use `color` or `--icon-color-N`.
|
||||
The canonical guide is now [React + Vite](guides/react-vite.md).
|
||||
|
||||
@@ -1,129 +1,3 @@
|
||||
# React + Webpack 5
|
||||
# React + Webpack Guide Moved
|
||||
|
||||
[← Back to home](../../README.md)
|
||||
|
||||
A quick guide to installing and using SVG sprites in a React and Webpack 5 project.
|
||||
|
||||
The result is a typed React component and a separate SVG asset emitted through Webpack Asset Modules.
|
||||
|
||||
## 1. Install the package
|
||||
|
||||
```bash
|
||||
npm install --save-dev @gromlab/svg-sprites
|
||||
```
|
||||
|
||||
## 2. Create the sprite directory
|
||||
|
||||
```text
|
||||
src/ui/file-manager/svg-sprite/
|
||||
├── icons/
|
||||
│ ├── check.svg
|
||||
│ └── folder.svg
|
||||
├── index.ts
|
||||
└── svg-sprite.config.ts
|
||||
```
|
||||
|
||||
Place the source SVG files in `icons/`.
|
||||
|
||||
## 3. Add the configuration
|
||||
|
||||
```ts
|
||||
// src/ui/file-manager/svg-sprite/svg-sprite.config.ts
|
||||
import { defineSpriteConfig } from '@gromlab/svg-sprites'
|
||||
|
||||
export default defineSpriteConfig({
|
||||
mode: 'react@webpack',
|
||||
name: 'file-manager',
|
||||
description: 'File manager icons',
|
||||
})
|
||||
```
|
||||
|
||||
The root barrel is application-owned and explicitly re-exports the generated API:
|
||||
|
||||
```ts
|
||||
// src/ui/file-manager/svg-sprite/index.ts
|
||||
export * from './.svg-sprite'
|
||||
```
|
||||
|
||||
By default, SVG files are loaded from `./icons`. You can add shared icons from other directories through `inputFiles`: the directory and file list are combined into a single sprite.
|
||||
|
||||
The complete list of options is available under [Unified configuration](reference.md#unified-configuration).
|
||||
|
||||
## 4. Add generation to package.json
|
||||
|
||||
```json
|
||||
{
|
||||
"scripts": {
|
||||
"sprite:file-manager": "svg-sprites src/ui/file-manager/svg-sprite/svg-sprite.config.ts",
|
||||
"predev": "npm run sprite:file-manager",
|
||||
"prebuild": "npm run sprite:file-manager",
|
||||
"pretypecheck": "npm run sprite:file-manager"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Generated files are excluded from Git, so generation must run before `dev`, `build`, and `typecheck`.
|
||||
|
||||
First run:
|
||||
|
||||
```bash
|
||||
npm run sprite:file-manager
|
||||
```
|
||||
|
||||
## 5. Use the component
|
||||
|
||||
```tsx
|
||||
import { FileManagerIcon } from './svg-sprite'
|
||||
|
||||
export const OpenFolderButton = () => (
|
||||
<button type="button">
|
||||
<FileManagerIcon icon="folder" width={24} height={24} />
|
||||
Open
|
||||
</button>
|
||||
)
|
||||
```
|
||||
|
||||
TypeScript checks the `icon` value against the file names:
|
||||
|
||||
```tsx
|
||||
<FileManagerIcon icon="folder" /> // valid
|
||||
<FileManagerIcon icon="missing" /> // TypeScript error
|
||||
```
|
||||
|
||||
Types, rendering methods, and color controls are described in the [technical reference](reference.md#react-component-and-typescript).
|
||||
|
||||
Webpack processes the generated `new URL('./sprite.svg', import.meta.url)` through Asset Modules and emits a separate SVG asset.
|
||||
|
||||
If the project already uses a custom SVG loader, make sure it does not intercept the generated `sprite.svg` instead of Asset Modules.
|
||||
|
||||
The generated component imports `react/react-component.module.css`, so Webpack must process CSS Modules through `css-loader` and `style-loader` or `MiniCssExtractPlugin`. If the TypeScript project does not include a declaration for CSS Modules, add one separately.
|
||||
|
||||
## 6. Add a debug page
|
||||
|
||||
Webpack does not support Vite's `import.meta.glob` API, so provide static loaders:
|
||||
|
||||
```tsx
|
||||
import { SpriteViewer } from '@gromlab/svg-sprites/react'
|
||||
|
||||
const sources = [
|
||||
() => import('./ui/file-manager/svg-sprite/.svg-sprite/svg-sprite.manifest.js'),
|
||||
() => import('./ui/navigation/svg-sprite/.svg-sprite/svg-sprite.manifest.js'),
|
||||
]
|
||||
|
||||
export const IconsDebugPage = () => (
|
||||
<SpriteViewer sources={sources} title="Project icons" />
|
||||
)
|
||||
```
|
||||
|
||||
The paths in `import()` must be string literals. Webpack creates chunks for the manifests and associates them with the SVG assets.
|
||||
|
||||
Only include the Viewer on a debug route or in an internal tool.
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
- Missing `.svg-sprite/index.js`: run `npm run sprite:file-manager`.
|
||||
- The Viewer does not load the sprite: check the `import()` path to `.svg-sprite/svg-sprite.manifest.js`.
|
||||
- Incorrect asset URL: check `output.publicPath`.
|
||||
- Another loader intercepts the SVG: exclude the generated sprite from the incompatible rule.
|
||||
|
||||
For Next.js, use the separate mode keys described in the [App Router](next-app.md) and [Pages Router](next-pages.md) guides.
|
||||
The canonical guide is now [React + Webpack](guides/react-webpack.md).
|
||||
|
||||
@@ -1,555 +1,3 @@
|
||||
# Technical reference
|
||||
# Technical Reference Moved
|
||||
|
||||
[← Back to home](../../README.md)
|
||||
|
||||
Reference for the configuration, generated API, and behavior of `@gromlab/svg-sprites`. For step-by-step setup instructions, see the guide for your stack:
|
||||
|
||||
- [Next.js App Router](next-app.md)
|
||||
- [Next.js Pages Router](next-pages.md)
|
||||
- [React + Vite](react-vite.md)
|
||||
- [React + Webpack 5](react-webpack.md)
|
||||
|
||||
## Requirements
|
||||
|
||||
- Node.js 18 or newer;
|
||||
- the package is distributed as ESM and is loaded with `import`;
|
||||
- React 18 or 19 is required for generated components and `@gromlab/svg-sprites/react`;
|
||||
- for typed package exports, use TypeScript 5+ with `moduleResolution: "bundler"`, `"node16"`, or `"nodenext"`.
|
||||
|
||||
Install the package as a development dependency:
|
||||
|
||||
```bash
|
||||
npm install --save-dev @gromlab/svg-sprites
|
||||
```
|
||||
|
||||
## CLI and generation modes
|
||||
|
||||
The CLI accepts exactly one path: an explicitly selected config file or a directory for config-less generation:
|
||||
|
||||
```text
|
||||
svg-sprites [options] <config-file-or-directory>
|
||||
```
|
||||
|
||||
| Environment | Mode |
|
||||
|---|---|
|
||||
| Static HTML / custom publishing | `standalone` |
|
||||
| Standalone + Vite | `standalone@vite` |
|
||||
| Standalone + Webpack 5 | `standalone@webpack` |
|
||||
| React + Vite | `react@vite` |
|
||||
| React + Webpack 5 | `react@webpack` |
|
||||
| Next.js App Router + Turbopack | `next@app/turbopack` |
|
||||
| Next.js App Router + Webpack 5 | `next@app/webpack` |
|
||||
| Next.js Pages Router + Turbopack | `next@pages/turbopack` |
|
||||
| Next.js Pages Router + Webpack 5 | `next@pages/webpack` |
|
||||
|
||||
The config file may have any name and use the `.ts`, `.js`, or `.json` extension. The CLI does not discover it by convention: pass the file explicitly. The guides use `svg-sprite.config.ts` as the recommended name.
|
||||
|
||||
When a directory is passed, all settings come from CLI options. When a config file is passed, CLI options override the file. The full order is `defaults → config → CLI`.
|
||||
|
||||
Available options are `--mode`, `--name`, `--description`, `--input-folder`, repeatable `--input-file`, plus the `--remove-size`/`--no-remove-size`, `--replace-colors`/`--no-replace-colors`, `--add-transition`/`--no-add-transition`, and `--generated-notice`/`--no-generated-notice` pairs. Transform flags override individual fields, while supplying at least one `--input-file` replaces the complete config `inputFiles` array.
|
||||
|
||||
The mode must match the application's publishing strategy. Bare `standalone` leaves the public URL to the application; Vite and Webpack modes generate bundler-specific SVG asset integration.
|
||||
|
||||
## Unified configuration
|
||||
|
||||
Each config file defines one independent sprite.
|
||||
|
||||
```ts
|
||||
import { defineSpriteConfig } from '@gromlab/svg-sprites'
|
||||
|
||||
export default defineSpriteConfig({
|
||||
mode: 'next@app/turbopack',
|
||||
name: 'app',
|
||||
description: 'Shared application icons',
|
||||
inputFolder: './local-icons',
|
||||
inputFiles: [
|
||||
'../../assets/icons/search.svg',
|
||||
'../../assets/icons/settings.svg',
|
||||
],
|
||||
transform: {
|
||||
removeSize: true,
|
||||
replaceColors: true,
|
||||
addTransition: true,
|
||||
},
|
||||
generatedNotice: true,
|
||||
})
|
||||
```
|
||||
|
||||
| Option | Type | Default | Purpose |
|
||||
|---|---|---|---|
|
||||
| `mode` | `SpriteMode` | None | Generation mode; may be supplied by CLI/API |
|
||||
| `name` | `string` | Derived from the directory | Name of the sprite, component, and public types |
|
||||
| `description` | `string` | None | Description for types and the debug manifest |
|
||||
| `inputFolder` | `string` | `./icons` | SVG directory relative to the module root |
|
||||
| `inputFiles` | `string[]` | `[]` | Paths to individual SVG files relative to the module root |
|
||||
| `transform` | `TransformOptions` | All enabled | SVG preparation settings |
|
||||
| `generatedNotice` | `boolean` | `true` | Full or abbreviated warning in generated files |
|
||||
|
||||
### Sprite name
|
||||
|
||||
`name` is written in kebab-case and must start with an ASCII letter:
|
||||
|
||||
```text
|
||||
app → AppIcon
|
||||
file-manager → FileManagerIcon
|
||||
```
|
||||
|
||||
If `name` is omitted, the generator derives it from the directory. For a directory named `svg-sprite` or `svg-sprites`, the parent directory's name is used.
|
||||
|
||||
### Icon sources
|
||||
|
||||
`inputFolder` and `inputFiles` are combined into one set. This lets you keep local SVG files next to a module and add shared icons from other parts of the project without copying them.
|
||||
|
||||
If `inputFiles` is populated and the implicit `./icons` directory does not exist, generation uses only the file list. An explicitly configured `inputFolder` that does not exist is an error.
|
||||
|
||||
Only the top level of the directory is scanned. Nested directories are not traversed recursively. For a nested structure, list the exact paths through `inputFiles`.
|
||||
|
||||
Identical absolute paths are deduplicated. Different SVG files with the same file name are treated as a conflict because the public icon name is derived from the basename.
|
||||
|
||||
## Generated module
|
||||
|
||||
After generation, a React or Next.js sprite directory looks like this:
|
||||
|
||||
```text
|
||||
app-icons/
|
||||
├── .gitignore
|
||||
├── svg-sprite.config.ts
|
||||
├── index.ts # optional user-owned barrel
|
||||
└── .svg-sprite/
|
||||
├── state.json
|
||||
├── index.js
|
||||
├── index.d.ts
|
||||
├── icon-data.js
|
||||
├── icon-data.d.ts
|
||||
├── sprite.svg
|
||||
├── svg-sprite.manifest.js
|
||||
├── svg-sprite.manifest.d.ts
|
||||
└── react/
|
||||
├── react-component.js
|
||||
├── react-component.d.ts
|
||||
└── react-component.module.css
|
||||
```
|
||||
|
||||
| File | Purpose |
|
||||
|---|---|
|
||||
| `.svg-sprite/index.js` | Production exports for the component and runtime icon-name list |
|
||||
| `.svg-sprite/index.d.ts` | Public declarations for the component, props, styles, and icon-name union |
|
||||
| `.svg-sprite/svg-sprite.manifest.js` | Debug metadata and the asset URL for `SpriteViewer` |
|
||||
| `.svg-sprite/sprite.svg` | Compiled SVG sprite |
|
||||
| `.svg-sprite/react/react-component.js` | React component runtime without TypeScript or JSX |
|
||||
| `.svg-sprite/react/react-component.d.ts` | React component props, style, and declaration |
|
||||
| `.svg-sprite/react/react-component.module.css` | Styles for the React implementation |
|
||||
| `.svg-sprite/icon-data.js` | Runtime icon-name list and internal IDs |
|
||||
| `.svg-sprite/*.d.ts` | TypeScript declarations for the corresponding JavaScript modules |
|
||||
| `.svg-sprite/state.json` | Mode, contract version, and managed file list |
|
||||
|
||||
Standalone contracts do not create `react/`. Bare `standalone` contains only the
|
||||
runtime asset and deployment-neutral manifest data:
|
||||
|
||||
```text
|
||||
.svg-sprite/
|
||||
├── state.json
|
||||
├── sprite.svg
|
||||
└── svg-sprite.manifest.json
|
||||
```
|
||||
|
||||
`standalone@vite` and `standalone@webpack` additionally create `index.*`,
|
||||
`icon-data.*`, and a resolved `svg-sprite.manifest.*`.
|
||||
|
||||
The generator overwrites and deletes only files that contain its marker. If a user file occupies a managed path, generation fails. The root `index.ts` is user-owned; create a barrel when needed:
|
||||
|
||||
```ts
|
||||
export * from './.svg-sprite'
|
||||
```
|
||||
|
||||
## React component and TypeScript
|
||||
|
||||
A sprite with `name: 'app'` exports:
|
||||
|
||||
```ts
|
||||
export { AppIcon, appIconNames }
|
||||
export type { AppIconName, AppIconProps, AppIconStyle }
|
||||
```
|
||||
|
||||
### Icon names
|
||||
|
||||
SVG file names become valid `icon` values:
|
||||
|
||||
```tsx
|
||||
<AppIcon icon="search" />
|
||||
<AppIcon icon="unknown" /> // TypeScript error
|
||||
```
|
||||
|
||||
The runtime list contains the same values:
|
||||
|
||||
```ts
|
||||
import { appIconNames } from '@/ui/app-icons'
|
||||
|
||||
// readonly ['search', 'settings', 'user']
|
||||
```
|
||||
|
||||
Names containing spaces or other characters that are unsafe in SVG IDs remain part of the public API. For the internal fragment ID, the generator creates a stable, safe hash:
|
||||
|
||||
```text
|
||||
folder open.svg → icon="folder open" → id="icon-<stable-hash>"
|
||||
```
|
||||
|
||||
For these names, use the generated component or the `id` from the debug manifest instead of constructing the fragment ID manually.
|
||||
|
||||
### SVG attributes
|
||||
|
||||
By default, the component renders an `<svg>` and accepts standard SVG attributes:
|
||||
|
||||
```tsx
|
||||
<AppIcon
|
||||
icon="search"
|
||||
width={24}
|
||||
height={24}
|
||||
color="rebeccapurple"
|
||||
className="searchIcon"
|
||||
aria-label="Search"
|
||||
/>
|
||||
```
|
||||
|
||||
The component does not add accessibility semantics automatically. Pass appropriate `aria-*` attributes, a `role`, or a label based on the icon's purpose.
|
||||
|
||||
### Wrapper
|
||||
|
||||
`wrapped` renders a `<span>` containing the SVG. In this mode, the remaining props apply to the `<span>`:
|
||||
|
||||
```tsx
|
||||
<AppIcon icon="search" wrapped className="iconWrapper" />
|
||||
```
|
||||
|
||||
### Typed CSS custom properties
|
||||
|
||||
`AppIconStyle` extends `CSSProperties` and supports properties in the form `--icon-color-N`:
|
||||
|
||||
```tsx
|
||||
<AppIcon
|
||||
icon="user"
|
||||
style={{
|
||||
'--icon-color-1': '#2563eb',
|
||||
'--icon-color-2': '#dbeafe',
|
||||
}}
|
||||
/>
|
||||
```
|
||||
|
||||
## Multiple sprites
|
||||
|
||||
Each directory with a configuration creates an independent component, types, manifest, and SVG asset:
|
||||
|
||||
```text
|
||||
app-icons → AppIcon → shared icons
|
||||
analytics-icons → AnalyticsIcon → analytics page icons
|
||||
editor-icons → EditorIcon → editor icons
|
||||
```
|
||||
|
||||
The same source SVG can be added to multiple configurations through `inputFiles`. You do not need to copy the file into each sprite directory.
|
||||
|
||||
For multiple sprites, add a separate CLI command for each directory or combine the commands in a shared npm script.
|
||||
|
||||
## Formats and rendering methods
|
||||
|
||||
All current modes generate the `stack` format.
|
||||
|
||||
| Format | `<svg><use>` | `<img>` | CSS background |
|
||||
|---|---:|---:|---:|
|
||||
| `stack` | Yes | Yes | Yes |
|
||||
|
||||
### Generated component
|
||||
|
||||
For React and Next.js, use the generated component. It knows the internal IDs, constructs the URL, and provides a TypeScript API:
|
||||
|
||||
```tsx
|
||||
<AppIcon icon="search" width={24} height={24} />
|
||||
```
|
||||
|
||||
### Manually with `<svg><use>`
|
||||
|
||||
How you obtain `spriteUrl` depends on the bundler.
|
||||
|
||||
Static HTML after the application publishes `.svg-sprite/sprite.svg`:
|
||||
|
||||
```html
|
||||
<svg aria-hidden="true">
|
||||
<use href="/assets/icons.svg#search"></use>
|
||||
</svg>
|
||||
```
|
||||
|
||||
Standalone Vite/Webpack provides generated `getIconsIconHref()` and an internal ID
|
||||
map. Do not construct fragments from unsafe file names manually.
|
||||
|
||||
Vite:
|
||||
|
||||
```ts
|
||||
import spriteUrl from './.svg-sprite/sprite.svg?no-inline'
|
||||
```
|
||||
|
||||
Webpack 5, Turbopack, and Next.js:
|
||||
|
||||
```ts
|
||||
const spriteUrl = new URL('./.svg-sprite/sprite.svg', import.meta.url).href
|
||||
```
|
||||
|
||||
After obtaining the URL, use it in JSX:
|
||||
|
||||
```tsx
|
||||
<svg width="24" height="24" aria-label="Search">
|
||||
<use href={`${spriteUrl}#search`} />
|
||||
</svg>
|
||||
```
|
||||
|
||||
For names that are unsafe as SVG IDs, use the internal `id` from the manifest.
|
||||
|
||||
### With `<img>`
|
||||
|
||||
```tsx
|
||||
<img src={`${spriteUrl}#search`} width={24} height={24} alt="Search" />
|
||||
```
|
||||
|
||||
An SVG inside `<img>` is isolated from the page's CSS. Setting `color` or `--icon-color-N` on the outer element does not change its internal colors.
|
||||
|
||||
### With CSS
|
||||
|
||||
```css
|
||||
.icon {
|
||||
background: url('./.svg-sprite/sprite.svg#search') center / contain no-repeat;
|
||||
}
|
||||
```
|
||||
|
||||
For a single-color silhouette, you can use a mask:
|
||||
|
||||
```css
|
||||
.icon {
|
||||
background-color: currentColor;
|
||||
mask: url('./.svg-sprite/sprite.svg#search') center / contain no-repeat;
|
||||
}
|
||||
```
|
||||
|
||||
A mask does not preserve original colors, gradients, or differences between `fill` and `stroke`.
|
||||
|
||||
The path in CSS is resolved relative to the CSS file itself. In these examples, the CSS file is next to `svg-sprite.config.ts`.
|
||||
|
||||
## Assets and caching
|
||||
|
||||
The generated component or standalone facade passes the SVG to the bundler as a separate asset:
|
||||
|
||||
- Vite uses a static import with `?no-inline`;
|
||||
- Webpack 5, Turbopack, and Next.js use `new URL(..., import.meta.url)`;
|
||||
- SVG path data is not serialized into generated JavaScript.
|
||||
|
||||
Bare `standalone` does not participate in an asset pipeline: the application copies
|
||||
or publishes `sprite.svg` and owns its URL, versioning, and cache policy.
|
||||
|
||||
With standard asset naming, the bundler adds a content hash:
|
||||
|
||||
```text
|
||||
/assets/sprite-<hash>.svg
|
||||
```
|
||||
|
||||
This allows the SVG to be cached separately from JavaScript. Changing React code does not change the sprite contents, while changing icons creates a new asset version.
|
||||
|
||||
HTTP cache headers, CDN behavior, and `Cache-Control` are configured by the application or hosting platform. With Webpack, the final file name depends on the project's `assetModuleFilename`.
|
||||
|
||||
## SVG transformations
|
||||
|
||||
All transformations are enabled by default and can be configured independently:
|
||||
|
||||
| Option | Behavior |
|
||||
|---|---|
|
||||
| `removeSize` | Removes `width` and `height` from the root `<svg>` while preserving an existing `viewBox` |
|
||||
| `replaceColors` | Replaces detected `fill` and `stroke` values with `--icon-color-N` |
|
||||
| `addTransition` | Adds transitions for `fill` and `stroke` to colored elements and generated styles |
|
||||
|
||||
To disable an individual operation:
|
||||
|
||||
```ts
|
||||
export default defineSpriteConfig({
|
||||
mode: 'next@app/turbopack',
|
||||
transform: {
|
||||
removeSize: false,
|
||||
replaceColors: false,
|
||||
addTransition: false,
|
||||
},
|
||||
})
|
||||
```
|
||||
|
||||
Source SVG files are not modified. Transformations apply only to the generated sprite contents.
|
||||
|
||||
## Color management
|
||||
|
||||
### Monochrome icons
|
||||
|
||||
If one color is detected, its fallback becomes `currentColor`:
|
||||
|
||||
```svg
|
||||
stroke="var(--icon-color-1, currentColor)"
|
||||
```
|
||||
|
||||
Set the color through a prop or CSS:
|
||||
|
||||
```tsx
|
||||
<AppIcon icon="search" color="rebeccapurple" />
|
||||
```
|
||||
|
||||
### Multicolor icons
|
||||
|
||||
Each unique color gets its own custom property with the original color as its fallback:
|
||||
|
||||
```svg
|
||||
fill="var(--icon-color-1, #798198)"
|
||||
fill="var(--icon-color-2, #ffffff)"
|
||||
fill="var(--icon-color-3, #129d9d)"
|
||||
```
|
||||
|
||||
You can override only the values you need:
|
||||
|
||||
```css
|
||||
.icon {
|
||||
--icon-color-1: #4b5563;
|
||||
--icon-color-3: #14b8a6;
|
||||
}
|
||||
```
|
||||
|
||||
### Limitations
|
||||
|
||||
- `none`, `transparent`, `inherit`, `unset`, and `initial` are not replaced;
|
||||
- colors in `fill`, `stroke`, and inline `style` attributes are handled most reliably;
|
||||
- CSS classes and external stylesheets inside the SVG are not the primary transformation use case;
|
||||
- `url(#...)` values may be replaced along with colors, so gradients and patterns require a separate sprite with `replaceColors: false`;
|
||||
- masks, filters, and complex internal CSS rules require visual verification;
|
||||
- page CSS custom properties are available through `<svg><use>`, but not inside `<img>` or a CSS background.
|
||||
|
||||
For a complex icon, you can disable `replaceColors` in a separate sprite configuration.
|
||||
|
||||
## SpriteViewer
|
||||
|
||||
The Viewer uses one Shadow DOM Web Component for every mode. React and future framework components are bridges to that same element, so the visuals and behavior are not duplicated.
|
||||
|
||||
Bare `standalone` loads the self-contained browser bundle and supplies the JSON manifest URL and the published SVG URL:
|
||||
|
||||
```html
|
||||
<script
|
||||
type="module"
|
||||
src="https://unpkg.com/@gromlab/svg-sprites@<version>/dist/viewer-element.js"
|
||||
></script>
|
||||
|
||||
<gromlab-sprite-viewer
|
||||
viewer-title="Project icons"
|
||||
manifest-url="/app-icons/manifest.json"
|
||||
sprite-url="/app-icons/sprite.svg"
|
||||
></gromlab-sprite-viewer>
|
||||
```
|
||||
|
||||
`viewer-element.js` has no additional runtime files and can be copied with the other static assets for self-hosting.
|
||||
|
||||
`standalone@vite` and `standalone@webpack` register the same element through an npm entry and pass the generated JS manifest through the `sources` property:
|
||||
|
||||
```ts
|
||||
import '@gromlab/svg-sprites/viewer/element'
|
||||
import type { SpriteViewerElement } from '@gromlab/svg-sprites/viewer'
|
||||
import spriteManifest from './svg-sprite/.svg-sprite/svg-sprite.manifest.js'
|
||||
|
||||
const viewer = document.querySelector<SpriteViewerElement>('gromlab-sprite-viewer')!
|
||||
viewer.sources = [spriteManifest]
|
||||
```
|
||||
|
||||
React and Next.js keep the component API:
|
||||
|
||||
```tsx
|
||||
import { SpriteViewer } from '@gromlab/svg-sprites/react'
|
||||
```
|
||||
|
||||
It accepts ready-made manifests, remote standalone sources, an array of lazy loaders, or a record in the format returned by `import.meta.glob`.
|
||||
|
||||
Vite:
|
||||
|
||||
```tsx
|
||||
import { SpriteViewer } from '@gromlab/svg-sprites/react'
|
||||
import type { SpriteManifestModule } from '@gromlab/svg-sprites/react'
|
||||
|
||||
const sources = import.meta.glob<SpriteManifestModule>(
|
||||
'/src/**/svg-sprite/.svg-sprite/svg-sprite.manifest.js',
|
||||
)
|
||||
|
||||
export const IconsDebugPage = () => (
|
||||
<SpriteViewer sources={sources} title="Project icons" />
|
||||
)
|
||||
```
|
||||
|
||||
Webpack and Next.js:
|
||||
|
||||
```tsx
|
||||
const sources = [
|
||||
() => import('@/ui/app-icons/.svg-sprite/svg-sprite.manifest.js'),
|
||||
() => import('@/features/analytics/icons/.svg-sprite/svg-sprite.manifest.js'),
|
||||
]
|
||||
|
||||
export const IconsDebugPage = () => (
|
||||
<SpriteViewer sources={sources} />
|
||||
)
|
||||
```
|
||||
|
||||
The Viewer displays groups, search, `viewBox`, CSS custom properties, and fallback colors. React/Next manifests get React, SVG, IMG, and CSS tabs; standalone manifests get SVG, IMG, and CSS. You can change color values in the interface and immediately inspect the result.
|
||||
|
||||
### Viewer theme
|
||||
|
||||
By default, `colorTheme="auto"` follows `prefers-color-scheme`. You can explicitly pass `light` or `dark`:
|
||||
|
||||
```tsx
|
||||
<SpriteViewer sources={sources} colorTheme="dark" />
|
||||
```
|
||||
|
||||
To synchronize it with the application theme:
|
||||
|
||||
```tsx
|
||||
<SpriteViewer
|
||||
sources={sources}
|
||||
colorTheme={appTheme}
|
||||
onColorThemeChange={setAppTheme}
|
||||
/>
|
||||
```
|
||||
|
||||
`@gromlab/svg-sprites/react` contains `'use client'` and renders the Web Component host; its internal Shadow DOM is created after the browser runtime loads. In the Next.js App Router, place the Viewer inside a separate Client Component boundary and use it only on a debug route or in an internal tool.
|
||||
|
||||
## Generated files, Git, and CI
|
||||
|
||||
A modern sprite module creates a local `.gitignore` for:
|
||||
|
||||
```text
|
||||
/.svg-sprite/
|
||||
```
|
||||
|
||||
Commit the local `.gitignore` to the repository once. It excludes the other generated files, so generation must run before commands that import the sprite module:
|
||||
|
||||
```json
|
||||
{
|
||||
"scripts": {
|
||||
"sprites": "svg-sprites src/ui/app-icons/svg-sprite.config.ts",
|
||||
"predev": "npm run sprites",
|
||||
"prebuild": "npm run sprites",
|
||||
"pretypecheck": "npm run sprites"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
CI must install development dependencies and run the generation script before building or type-checking.
|
||||
|
||||
If the sprite directory already contains a user-created `.gitignore` or a user-owned file inside `.svg-sprite`, the generator will not overwrite it. The root `index.ts` remains user-owned and may re-export the generated API.
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
- Missing `.svg-sprite/index.js`: run the generation script before importing the generated module.
|
||||
- Source not found: pass an existing config file or sprite module directory.
|
||||
- Mode missing: add `mode` to the config or pass `--mode`.
|
||||
- Icon missing from the type: check `inputFiles`, the `.svg` extension, and the nesting level under `inputFolder`.
|
||||
- Name conflict: two different SVG files have the same basename; rename one of them.
|
||||
- `Refusing to overwrite a user file`: a file without the generated marker occupies a managed path.
|
||||
- The icon does not change color: use `<svg><use>` or the generated component and check `replaceColors`.
|
||||
- Webpack emits an incorrect URL: check Asset Modules, `output.publicPath`, and SVG loaders.
|
||||
- Static sprite returns 404: check the post-generation copy or server alias, and do not put a filesystem `spritePath` into HTML.
|
||||
- The Viewer cannot find the sprite: check the path to `.svg-sprite/svg-sprite.manifest.js` and run generation before starting the application.
|
||||
- Build and mode do not match: use the target that corresponds to the actual bundler.
|
||||
|
||||
For custom orchestration and low-level compilation, see the [Programmatic API](programmatic-api.md).
|
||||
The canonical document is now the [technical reference](reference/technical.md).
|
||||
|
||||
4
docs/en/reference/README.md
Normal file
4
docs/en/reference/README.md
Normal file
@@ -0,0 +1,4 @@
|
||||
# Reference
|
||||
|
||||
- [Technical reference](technical.md)
|
||||
- [Programmatic API](programmatic-api.md)
|
||||
147
docs/en/reference/programmatic-api.md
Normal file
147
docs/en/reference/programmatic-api.md
Normal file
@@ -0,0 +1,147 @@
|
||||
# Programmatic API
|
||||
|
||||
[Documentation index](../README.md)
|
||||
|
||||
The package is ESM-only and provides one Node.js generation API. The framework-neutral Viewer is available from `@gromlab/svg-sprites/viewer`, its auto-register entry from `@gromlab/svg-sprites/viewer/element`, and the React bridge from `@gromlab/svg-sprites/react`.
|
||||
|
||||
## `generateSprite`
|
||||
|
||||
```ts
|
||||
import { generateSprite } from '@gromlab/svg-sprites'
|
||||
|
||||
const result = await generateSprite(
|
||||
'src/ui/file-manager/svg-sprite/svg-sprite.config.ts',
|
||||
)
|
||||
```
|
||||
|
||||
For static standalone mode, use `result.spritePath` in a build script to publish the
|
||||
SVG under an application URL:
|
||||
|
||||
```ts
|
||||
import { copyFile } from 'node:fs/promises'
|
||||
|
||||
const result = await generateSprite('src/sprite/svg-sprite.config.ts', {
|
||||
mode: 'standalone',
|
||||
})
|
||||
await copyFile(result.spritePath, 'dist/app-icons/sprite.svg')
|
||||
```
|
||||
|
||||
`spritePath` is a filesystem path, not a browser URL. A deployment-neutral JSON
|
||||
manifest is available through `result.manifestPath` and is copied independently.
|
||||
|
||||
The first argument accepts the full path to an explicitly selected `.ts`, `.js`, or `.json` config file with any name. Passing a directory enables config-less mode and uses that directory as the sprite module root.
|
||||
|
||||
The second argument contains optional overrides and always takes precedence over the config:
|
||||
|
||||
```ts
|
||||
await generateSprite('src/ui/file-manager/svg-sprite/custom-config.json', {
|
||||
mode: 'react@webpack',
|
||||
name: 'documents',
|
||||
input: ['./assets', '../../shared/search.svg'],
|
||||
transform: {
|
||||
addTransition: false,
|
||||
},
|
||||
generatedNotice: false,
|
||||
})
|
||||
```
|
||||
|
||||
Configuration is resolved in this order:
|
||||
|
||||
```text
|
||||
defaults → config → API overrides
|
||||
```
|
||||
|
||||
For fully programmatic generation, pass a directory and provide the required settings as overrides:
|
||||
|
||||
```ts
|
||||
await generateSprite('src/ui/file-manager/svg-sprite', {
|
||||
mode: 'react@vite',
|
||||
name: 'file-manager',
|
||||
input: [
|
||||
'../../shared/search.svg',
|
||||
'../../shared/settings.svg',
|
||||
],
|
||||
})
|
||||
```
|
||||
|
||||
## Configuration
|
||||
|
||||
```ts
|
||||
import { defineSpriteConfig } from '@gromlab/svg-sprites'
|
||||
|
||||
export default defineSpriteConfig({
|
||||
mode: 'react@vite',
|
||||
name: 'file-manager',
|
||||
description: 'File manager icons',
|
||||
input: ['./icons', '../../shared/check.svg'],
|
||||
transform: {
|
||||
removeSize: true,
|
||||
replaceColors: true,
|
||||
addTransition: true,
|
||||
},
|
||||
generatedNotice: true,
|
||||
})
|
||||
```
|
||||
|
||||
`input` accepts one folder, SVG file, or glob pattern, or an array that combines them. When omitted, it defaults to `./icons`; relative paths start at the config directory.
|
||||
|
||||
`defineSpriteConfig` is an identity helper for TypeScript autocomplete. JavaScript can export the same object with `export default`, while JSON contains the object directly.
|
||||
|
||||
## Specialized wrappers
|
||||
|
||||
The specialized functions are available as wrappers around `generateSprite`:
|
||||
|
||||
```ts
|
||||
import { generateNextSprite, generateReactSprite } from '@gromlab/svg-sprites'
|
||||
|
||||
await generateReactSprite('path/to/config.ts', 'vite')
|
||||
await generateNextSprite('path/to/config.ts', {
|
||||
router: 'app',
|
||||
bundler: 'turbopack',
|
||||
})
|
||||
```
|
||||
|
||||
An explicitly supplied target overrides `mode` from the file. Prefer `generateSprite` in new code.
|
||||
|
||||
## Config API
|
||||
|
||||
```ts
|
||||
import {
|
||||
loadSpriteConfig,
|
||||
resolveSpriteConfig,
|
||||
validateSpriteConfig,
|
||||
} from '@gromlab/svg-sprites'
|
||||
```
|
||||
|
||||
- `loadSpriteConfig(file)` loads an explicitly selected `.ts`, `.js`, or `.json` file.
|
||||
- `validateSpriteConfig(value)` performs runtime validation.
|
||||
- `resolveSpriteConfig(root, config, overrides)` merges values, applies defaults, and resolves paths relative to `root`.
|
||||
|
||||
## Low-level compiler
|
||||
|
||||
```ts
|
||||
import {
|
||||
compileSprite,
|
||||
compileSpriteContent,
|
||||
createShapeTransform,
|
||||
} from '@gromlab/svg-sprites'
|
||||
```
|
||||
|
||||
These functions are intended for custom orchestration. Standard generation should use `generateSprite`.
|
||||
|
||||
## Viewer runtime
|
||||
|
||||
```ts
|
||||
import '@gromlab/svg-sprites/viewer/element'
|
||||
import type { SpriteViewerElement } from '@gromlab/svg-sprites/viewer'
|
||||
```
|
||||
|
||||
The browser entry registers `<gromlab-sprite-viewer>`. Bare standalone can also load the self-contained `dist/viewer-element.js` without a bundler.
|
||||
|
||||
The React bridge keeps the component API:
|
||||
|
||||
```tsx
|
||||
import { SpriteViewer } from '@gromlab/svg-sprites/react'
|
||||
```
|
||||
|
||||
`SpriteViewer` accepts generated manifests, remote standalone sources, lazy loaders, or an `import.meta.glob` result. The React entry contains `'use client'` and is intended for debug tools; production components are imported from local sprite modules.
|
||||
632
docs/en/reference/technical.md
Normal file
632
docs/en/reference/technical.md
Normal file
@@ -0,0 +1,632 @@
|
||||
# Technical reference
|
||||
|
||||
[Documentation index](../README.md)
|
||||
|
||||
Reference for the configuration, generated API, and behavior of `@gromlab/svg-sprites`. For step-by-step setup instructions, see the guide for your stack:
|
||||
|
||||
- [Bare standalone](../guides/standalone.md)
|
||||
- [Standalone + Vite](../guides/standalone-vite.md)
|
||||
- [Standalone + Webpack 5](../guides/standalone-webpack.md)
|
||||
- [React + Vite](../guides/react-vite.md)
|
||||
- [React + Webpack 5](../guides/react-webpack.md)
|
||||
- [Next.js App Router + Turbopack](../guides/next-app-turbopack.md)
|
||||
- [Next.js App Router + Webpack](../guides/next-app-webpack.md)
|
||||
- [Next.js Pages Router + Turbopack](../guides/next-pages-turbopack.md)
|
||||
- [Next.js Pages Router + Webpack](../guides/next-pages-webpack.md)
|
||||
|
||||
## Requirements
|
||||
|
||||
- Node.js 18 or newer;
|
||||
- the package is distributed as ESM and is loaded with `import`;
|
||||
- React 18 or 19 is required only for React/Next generated components and `@gromlab/svg-sprites/react`;
|
||||
- for typed package exports, use TypeScript 5+ with `moduleResolution: "bundler"`, `"node16"`, or `"nodenext"`.
|
||||
|
||||
Generation does not require a project dependency. Run the CLI through `npx`:
|
||||
|
||||
```bash
|
||||
npx --yes --package=@gromlab/svg-sprites@latest svg-sprites path/to/svg-sprite.config.ts
|
||||
```
|
||||
|
||||
Install the package as a development dependency only when the project needs the
|
||||
Viewer, config types, or the programmatic API:
|
||||
|
||||
```bash
|
||||
npm install --save-dev @gromlab/svg-sprites
|
||||
```
|
||||
|
||||
## CLI and generation modes
|
||||
|
||||
The CLI accepts exactly one path: an explicitly selected config file or a directory for config-less generation:
|
||||
|
||||
```text
|
||||
svg-sprites [options] <config-file-or-directory>
|
||||
```
|
||||
|
||||
| Environment | Mode |
|
||||
|---|---|
|
||||
| Static HTML / custom publishing | `standalone` |
|
||||
| Standalone + Vite | `standalone@vite` |
|
||||
| Standalone + Webpack 5 | `standalone@webpack` |
|
||||
| React + Vite | `react@vite` |
|
||||
| React + Webpack 5 | `react@webpack` |
|
||||
| Next.js App Router + Turbopack | `next@app/turbopack` |
|
||||
| Next.js App Router + Webpack 5 | `next@app/webpack` |
|
||||
| Next.js Pages Router + Turbopack | `next@pages/turbopack` |
|
||||
| Next.js Pages Router + Webpack 5 | `next@pages/webpack` |
|
||||
|
||||
The config file may have any name and use the `.ts`, `.js`, or `.json` extension. The CLI does not discover it by convention: pass the file explicitly. The guides use `svg-sprite.config.ts` as the recommended name.
|
||||
|
||||
When a directory is passed, all settings come from CLI options. When a config file is passed, CLI options override the file. The full order is `defaults → config → CLI`.
|
||||
|
||||
Available options are `--mode`, `--name`, `--description`, repeatable `--input <path-or-glob>`, plus the `--remove-size`/`--no-remove-size`, `--replace-colors`/`--no-replace-colors`, `--add-transition`/`--no-add-transition`, and `--generated-notice`/`--no-generated-notice` pairs. Transform flags override individual fields, while supplying at least one `--input` replaces the complete config `input` value.
|
||||
|
||||
Quote CLI glob patterns with single quotes so the shell does not expand them before the generator receives them:
|
||||
|
||||
```bash
|
||||
svg-sprites --input './icons/**/*.svg' --input '!./icons/legacy/**' svg-sprite.config.ts
|
||||
```
|
||||
|
||||
The mode must match the application's publishing strategy. Bare `standalone` leaves the public URL to the application; Vite and Webpack modes generate bundler-specific SVG asset integration.
|
||||
|
||||
## Unified configuration
|
||||
|
||||
Each config file defines one independent sprite.
|
||||
|
||||
```ts
|
||||
import { defineSpriteConfig } from '@gromlab/svg-sprites'
|
||||
|
||||
export default defineSpriteConfig({
|
||||
mode: 'next@app/turbopack',
|
||||
name: 'app',
|
||||
description: 'Shared application icons',
|
||||
input: [
|
||||
'./local-icons',
|
||||
'../../assets/icons/*.svg',
|
||||
'!../../assets/icons/deprecated-*.svg',
|
||||
],
|
||||
transform: {
|
||||
removeSize: true,
|
||||
replaceColors: true,
|
||||
addTransition: true,
|
||||
},
|
||||
generatedNotice: true,
|
||||
})
|
||||
```
|
||||
|
||||
| Option | Type | Default | Purpose |
|
||||
|---|---|---|---|
|
||||
| `mode` | `SpriteMode` | None | Generation mode; may be supplied by CLI/API |
|
||||
| `name` | `string` | Derived from the directory | Name of the sprite, component, and public types |
|
||||
| `description` | `string` | None | Description for types and the debug manifest |
|
||||
| `input` | `string \| string[]` | `./icons` | SVG folders, files, and glob patterns relative to the config directory |
|
||||
| `transform` | `TransformOptions` | All enabled | SVG preparation settings |
|
||||
| `generatedNotice` | `boolean` | `true` | Full or abbreviated warning in generated files |
|
||||
|
||||
### Sprite name
|
||||
|
||||
`name` is written in kebab-case and must start with an ASCII letter:
|
||||
|
||||
```text
|
||||
app → AppIcon
|
||||
file-manager → FileManagerIcon
|
||||
```
|
||||
|
||||
If `name` is omitted, the generator derives it from the directory. For a directory named `svg-sprite` or `svg-sprites`, the parent directory's name is used.
|
||||
|
||||
### Icon sources
|
||||
|
||||
`SpriteConfig.input` is optional and has the type `string | string[]`. When it is omitted, the source is the literal `./icons` folder relative to the config directory. In config-less mode, relative paths start at the directory passed to the CLI or API.
|
||||
|
||||
Each positive string may be a literal folder, a literal `.svg` file, or a glob pattern. A literal folder includes only its immediate `*.svg` children. Use an explicit pattern such as `icons/**/*.svg` to traverse nested directories.
|
||||
|
||||
An array combines all positive sources. A pattern prefixed with `!` excludes its matches from the combined result globally, regardless of which positive source included them.
|
||||
|
||||
Supported glob syntax includes:
|
||||
|
||||
| Syntax | Meaning |
|
||||
|---|---|
|
||||
| `*` | Any characters within one path segment |
|
||||
| `**` | Any number of nested directories |
|
||||
| `?` | One character within a path segment |
|
||||
| `{a,b}` | Either alternative |
|
||||
| `[abc]` | One character from the set or range |
|
||||
| `!pattern` | Exclude matches from the full combined input |
|
||||
|
||||
Every positive source or pattern must find at least one SVG, otherwise generation fails. Duplicate paths are removed and the final file list is sorted deterministically. Different SVG files with the same basename remain a conflict because the basename defines the public icon name.
|
||||
|
||||
## Generated module
|
||||
|
||||
After generation, a React or Next.js sprite directory looks like this:
|
||||
|
||||
```text
|
||||
app-icons/
|
||||
├── .gitignore
|
||||
├── svg-sprite.config.ts
|
||||
├── index.ts # optional user-owned barrel
|
||||
└── .svg-sprite/
|
||||
├── index.js
|
||||
├── index.d.ts
|
||||
├── icon-data.js
|
||||
├── icon-data.d.ts
|
||||
├── sprite.svg
|
||||
├── svg-sprite.manifest.js
|
||||
├── svg-sprite.manifest.d.ts
|
||||
└── react/
|
||||
├── react-component.js
|
||||
├── react-component.d.ts
|
||||
└── react-component.module.css
|
||||
```
|
||||
|
||||
| File | Purpose |
|
||||
|---|---|
|
||||
| `.svg-sprite/index.js` | Mode-specific production facade and runtime icon-name list |
|
||||
| `.svg-sprite/index.d.ts` | Public declarations for the facade, component, and icon-name union |
|
||||
| `.svg-sprite/svg-sprite.manifest.js` | Debug metadata and the asset URL for `SpriteViewer` |
|
||||
| `.svg-sprite/sprite.svg` | Compiled SVG sprite |
|
||||
| `.svg-sprite/react/react-component.js` | React component runtime without TypeScript or JSX |
|
||||
| `.svg-sprite/react/react-component.d.ts` | React component props, style, and declaration |
|
||||
| `.svg-sprite/react/react-component.module.css` | Styles for the React implementation |
|
||||
| `.svg-sprite/icon-data.js` | Runtime icon-name list and internal IDs |
|
||||
| `.svg-sprite/*.d.ts` | TypeScript declarations for the corresponding JavaScript modules |
|
||||
|
||||
Standalone contracts do not create `react/`. Bare `standalone` contains only the
|
||||
runtime asset and deployment-neutral manifest data:
|
||||
|
||||
```text
|
||||
.svg-sprite/
|
||||
├── sprite.svg
|
||||
└── svg-sprite.manifest.json
|
||||
```
|
||||
|
||||
`standalone@vite` and `standalone@webpack` additionally create `index.*`,
|
||||
`icon-data.*`, and a resolved `svg-sprite.manifest.*`. Their facade contains a
|
||||
native generated Web Component with no external runtime dependencies. Bare
|
||||
`standalone` intentionally does not generate a JavaScript component.
|
||||
|
||||
The generator overwrites and deletes only files that contain its marker. If a user file occupies a managed path, generation fails. The root `index.ts` is user-owned; create a barrel when needed:
|
||||
|
||||
```ts
|
||||
export * from './.svg-sprite'
|
||||
```
|
||||
|
||||
## Standalone Web Component and TypeScript
|
||||
|
||||
In `standalone@vite` and `standalone@webpack`, a sprite with `name: 'app'`
|
||||
exports the `defineAppIconElement()` registration function and the `<app-icon>`
|
||||
tag:
|
||||
|
||||
```ts
|
||||
import { defineAppIconElement } from '@/ui/app-icons'
|
||||
|
||||
defineAppIconElement()
|
||||
```
|
||||
|
||||
After registration, use the element in HTML:
|
||||
|
||||
```html
|
||||
<app-icon icon="search" aria-hidden="true"></app-icon>
|
||||
|
||||
<app-icon
|
||||
icon="settings"
|
||||
role="img"
|
||||
aria-label="Settings"
|
||||
></app-icon>
|
||||
```
|
||||
|
||||
The component renders `<svg><use>` in an open Shadow DOM, selects the internal
|
||||
ID and `viewBox`, and obtains the asset URL through the corresponding Vite or
|
||||
Webpack mechanism. The host defaults to `1em × 1em`; set `class`, `style`,
|
||||
`color`, and `--icon-color-N` with ordinary CSS.
|
||||
|
||||
The generated `HTMLElementTagNameMap` types the property API:
|
||||
|
||||
```ts
|
||||
const icon = document.createElement('app-icon')
|
||||
|
||||
icon.icon = 'search'
|
||||
icon.icon = 'unknown' // TypeScript error
|
||||
```
|
||||
|
||||
TypeScript does not validate attribute values in plain HTML. Therefore an
|
||||
unknown `icon="unknown"` is also validated at runtime: the component hides its
|
||||
inner SVG and reports an error instead of creating a `#undefined` fragment.
|
||||
Calling `defineAppIconElement()` repeatedly is safe for the same sprite; a
|
||||
different element already registered as `<app-icon>` causes an error.
|
||||
|
||||
## React component and TypeScript
|
||||
|
||||
A sprite with `name: 'app'` exports:
|
||||
|
||||
```ts
|
||||
export { AppIcon, appIconNames }
|
||||
export type { AppIconName, AppIconProps, AppIconStyle }
|
||||
```
|
||||
|
||||
### Icon names
|
||||
|
||||
SVG file names become valid `icon` values:
|
||||
|
||||
```tsx
|
||||
<AppIcon icon="search" />
|
||||
<AppIcon icon="unknown" /> // TypeScript error
|
||||
```
|
||||
|
||||
The runtime list contains the same values:
|
||||
|
||||
```ts
|
||||
import { appIconNames } from '@/ui/app-icons'
|
||||
|
||||
// readonly ['search', 'settings', 'user']
|
||||
```
|
||||
|
||||
Names containing spaces or other characters that are unsafe in SVG IDs remain part of the public API. For the internal fragment ID, the generator creates a stable, safe hash:
|
||||
|
||||
```text
|
||||
folder open.svg → icon="folder open" → id="icon-<stable-hash>"
|
||||
```
|
||||
|
||||
For these names, use the generated component or the `id` from the debug manifest instead of constructing the fragment ID manually.
|
||||
|
||||
### SVG attributes
|
||||
|
||||
By default, the component renders an `<svg>` and accepts standard SVG attributes:
|
||||
|
||||
```tsx
|
||||
<AppIcon
|
||||
icon="search"
|
||||
width={24}
|
||||
height={24}
|
||||
color="rebeccapurple"
|
||||
className="searchIcon"
|
||||
aria-label="Search"
|
||||
/>
|
||||
```
|
||||
|
||||
The component does not add accessibility semantics automatically. Pass appropriate `aria-*` attributes, a `role`, or a label based on the icon's purpose.
|
||||
|
||||
### Wrapper
|
||||
|
||||
`wrapped` renders a `<span>` containing the SVG. In this mode, the remaining props apply to the `<span>`:
|
||||
|
||||
```tsx
|
||||
<AppIcon icon="search" wrapped className="iconWrapper" />
|
||||
```
|
||||
|
||||
### Typed CSS custom properties
|
||||
|
||||
`AppIconStyle` extends `CSSProperties` and supports properties in the form `--icon-color-N`:
|
||||
|
||||
```tsx
|
||||
<AppIcon
|
||||
icon="user"
|
||||
style={{
|
||||
'--icon-color-1': '#2563eb',
|
||||
'--icon-color-2': '#dbeafe',
|
||||
}}
|
||||
/>
|
||||
```
|
||||
|
||||
## Multiple sprites
|
||||
|
||||
Each directory with a configuration creates an independent component, types, manifest, and SVG asset:
|
||||
|
||||
```text
|
||||
app-icons → AppIcon → shared icons
|
||||
analytics-icons → AnalyticsIcon → analytics page icons
|
||||
editor-icons → EditorIcon → editor icons
|
||||
```
|
||||
|
||||
The same source SVG can be added to multiple configurations through `input`. You do not need to copy the file into each sprite directory.
|
||||
|
||||
For multiple sprites, add a separate CLI command for each directory or combine the commands in a shared npm script.
|
||||
|
||||
## Formats and rendering methods
|
||||
|
||||
All current modes generate the `stack` format.
|
||||
|
||||
| Format | `<svg><use>` | `<img>` | CSS background |
|
||||
|---|---:|---:|---:|
|
||||
| `stack` | Yes | Yes | Yes |
|
||||
|
||||
### Generated component
|
||||
|
||||
For React and Next.js, use the generated React component. It knows the internal IDs, constructs the URL, and provides a TypeScript API:
|
||||
|
||||
```tsx
|
||||
<AppIcon icon="search" width={24} height={24} />
|
||||
```
|
||||
|
||||
For `standalone@vite` and `standalone@webpack`, use the generated Web Component:
|
||||
|
||||
```html
|
||||
<app-icon icon="search" style="font-size: 24px"></app-icon>
|
||||
```
|
||||
|
||||
### Manually with `<svg><use>`
|
||||
|
||||
How you obtain `spriteUrl` depends on the bundler.
|
||||
|
||||
Static HTML after the application publishes `.svg-sprite/sprite.svg`:
|
||||
|
||||
```html
|
||||
<svg aria-hidden="true">
|
||||
<use href="/assets/icons.svg#search"></use>
|
||||
</svg>
|
||||
```
|
||||
|
||||
Standalone Vite/Webpack provides generated `getIconsIconHref()` and an internal ID
|
||||
map. Do not construct fragments from unsafe file names manually.
|
||||
|
||||
Vite:
|
||||
|
||||
```ts
|
||||
import spriteUrl from './.svg-sprite/sprite.svg?no-inline'
|
||||
```
|
||||
|
||||
Webpack 5, Turbopack, and Next.js:
|
||||
|
||||
```ts
|
||||
const spriteUrl = new URL('./.svg-sprite/sprite.svg', import.meta.url).href
|
||||
```
|
||||
|
||||
After obtaining the URL, use it in JSX:
|
||||
|
||||
```tsx
|
||||
<svg width="24" height="24" aria-label="Search">
|
||||
<use href={`${spriteUrl}#search`} />
|
||||
</svg>
|
||||
```
|
||||
|
||||
For names that are unsafe as SVG IDs, use the internal `id` from the manifest.
|
||||
|
||||
### With `<img>`
|
||||
|
||||
```tsx
|
||||
<img src={`${spriteUrl}#search`} width={24} height={24} alt="Search" />
|
||||
```
|
||||
|
||||
An SVG inside `<img>` is isolated from the page's CSS. Setting `color` or `--icon-color-N` on the outer element does not change its internal colors.
|
||||
|
||||
### With CSS
|
||||
|
||||
```css
|
||||
.icon {
|
||||
background: url('./.svg-sprite/sprite.svg#search') center / contain no-repeat;
|
||||
}
|
||||
```
|
||||
|
||||
For a single-color silhouette, you can use a mask:
|
||||
|
||||
```css
|
||||
.icon {
|
||||
background-color: currentColor;
|
||||
mask: url('./.svg-sprite/sprite.svg#search') center / contain no-repeat;
|
||||
}
|
||||
```
|
||||
|
||||
A mask does not preserve original colors, gradients, or differences between `fill` and `stroke`.
|
||||
|
||||
The path in CSS is resolved relative to the CSS file itself. In these examples, the CSS file is next to `svg-sprite.config.ts`.
|
||||
|
||||
## Assets and caching
|
||||
|
||||
The generated component or standalone facade passes the SVG to the bundler as a separate asset:
|
||||
|
||||
- Vite uses a static import with `?no-inline`;
|
||||
- Webpack 5, Turbopack, and Next.js use `new URL(..., import.meta.url)`;
|
||||
- SVG path data is not serialized into generated JavaScript.
|
||||
|
||||
Bare `standalone` does not participate in an asset pipeline: the application copies
|
||||
or publishes `sprite.svg` and owns its URL, versioning, and cache policy.
|
||||
|
||||
With standard asset naming, the bundler adds a content hash:
|
||||
|
||||
```text
|
||||
/assets/sprite-<hash>.svg
|
||||
```
|
||||
|
||||
This allows the SVG to be cached separately from JavaScript. Changing React code does not change the sprite contents, while changing icons creates a new asset version.
|
||||
|
||||
HTTP cache headers, CDN behavior, and `Cache-Control` are configured by the application or hosting platform. With Webpack, the final file name depends on the project's `assetModuleFilename`.
|
||||
|
||||
## SVG transformations
|
||||
|
||||
All transformations are enabled by default and can be configured independently:
|
||||
|
||||
| Option | Behavior |
|
||||
|---|---|
|
||||
| `removeSize` | Removes `width` and `height` from the root `<svg>` while preserving an existing `viewBox` |
|
||||
| `replaceColors` | Replaces detected `fill` and `stroke` values with `--icon-color-N` |
|
||||
| `addTransition` | Adds transitions for `fill` and `stroke` to colored elements and generated styles |
|
||||
|
||||
To disable an individual operation:
|
||||
|
||||
```ts
|
||||
export default defineSpriteConfig({
|
||||
mode: 'next@app/turbopack',
|
||||
transform: {
|
||||
removeSize: false,
|
||||
replaceColors: false,
|
||||
addTransition: false,
|
||||
},
|
||||
})
|
||||
```
|
||||
|
||||
Source SVG files are not modified. Transformations apply only to the generated sprite contents.
|
||||
|
||||
## Color management
|
||||
|
||||
### Monochrome icons
|
||||
|
||||
If one color is detected, its fallback becomes `currentColor`:
|
||||
|
||||
```svg
|
||||
stroke="var(--icon-color-1, currentColor)"
|
||||
```
|
||||
|
||||
Set the color through a prop or CSS:
|
||||
|
||||
```tsx
|
||||
<AppIcon icon="search" color="rebeccapurple" />
|
||||
```
|
||||
|
||||
### Multicolor icons
|
||||
|
||||
Each unique color gets its own custom property with the original color as its fallback:
|
||||
|
||||
```svg
|
||||
fill="var(--icon-color-1, #798198)"
|
||||
fill="var(--icon-color-2, #ffffff)"
|
||||
fill="var(--icon-color-3, #129d9d)"
|
||||
```
|
||||
|
||||
You can override only the values you need:
|
||||
|
||||
```css
|
||||
.icon {
|
||||
--icon-color-1: #4b5563;
|
||||
--icon-color-3: #14b8a6;
|
||||
}
|
||||
```
|
||||
|
||||
### Limitations
|
||||
|
||||
- `none`, `transparent`, `inherit`, `unset`, and `initial` are not replaced;
|
||||
- colors in `fill`, `stroke`, and inline `style` attributes are handled most reliably;
|
||||
- CSS classes and external stylesheets inside the SVG are not the primary transformation use case;
|
||||
- `url(#...)` values may be replaced along with colors, so gradients and patterns require a separate sprite with `replaceColors: false`;
|
||||
- masks, filters, and complex internal CSS rules require visual verification;
|
||||
- page CSS custom properties are available through `<svg><use>`, but not inside `<img>` or a CSS background.
|
||||
|
||||
For a complex icon, you can disable `replaceColors` in a separate sprite configuration.
|
||||
|
||||
## SpriteViewer
|
||||
|
||||
The Viewer uses one Shadow DOM Web Component for every mode. React and future framework components are bridges to that same element, so the visuals and behavior are not duplicated.
|
||||
|
||||
Bare `standalone` loads the self-contained browser bundle and supplies the JSON manifest URL and the published SVG URL:
|
||||
|
||||
```html
|
||||
<script
|
||||
type="module"
|
||||
src="https://unpkg.com/@gromlab/svg-sprites@<version>/dist/viewer-element.js"
|
||||
></script>
|
||||
|
||||
<gromlab-sprite-viewer
|
||||
viewer-title="Project icons"
|
||||
manifest-url="/app-icons/manifest.json"
|
||||
sprite-url="/app-icons/sprite.svg"
|
||||
></gromlab-sprite-viewer>
|
||||
```
|
||||
|
||||
`viewer-element.js` has no additional runtime files and can be copied with the other static assets for self-hosting.
|
||||
|
||||
`standalone@vite` and `standalone@webpack` register the same element through an npm entry and pass the generated JS manifest through the `sources` property:
|
||||
|
||||
```ts
|
||||
import '@gromlab/svg-sprites/viewer/element'
|
||||
import type { SpriteViewerElement } from '@gromlab/svg-sprites/viewer'
|
||||
import spriteManifest from './svg-sprite/.svg-sprite/svg-sprite.manifest.js'
|
||||
|
||||
const viewer = document.querySelector<SpriteViewerElement>('gromlab-sprite-viewer')!
|
||||
viewer.sources = [spriteManifest]
|
||||
```
|
||||
|
||||
React and Next.js keep the component API:
|
||||
|
||||
```tsx
|
||||
import { SpriteViewer } from '@gromlab/svg-sprites/react'
|
||||
```
|
||||
|
||||
It accepts ready-made manifests, remote standalone sources, an array of lazy loaders, or a record in the format returned by `import.meta.glob`.
|
||||
|
||||
Vite:
|
||||
|
||||
```tsx
|
||||
import { SpriteViewer } from '@gromlab/svg-sprites/react'
|
||||
import type { SpriteManifestModule } from '@gromlab/svg-sprites/react'
|
||||
|
||||
const sources = import.meta.glob<SpriteManifestModule>(
|
||||
'/src/**/svg-sprite/.svg-sprite/svg-sprite.manifest.js',
|
||||
)
|
||||
|
||||
export const IconsDebugPage = () => (
|
||||
<SpriteViewer sources={sources} title="Project icons" />
|
||||
)
|
||||
```
|
||||
|
||||
Webpack and Next.js:
|
||||
|
||||
```tsx
|
||||
const sources = [
|
||||
() => import('@/ui/app-icons/.svg-sprite/svg-sprite.manifest.js'),
|
||||
() => import('@/features/analytics/icons/.svg-sprite/svg-sprite.manifest.js'),
|
||||
]
|
||||
|
||||
export const IconsDebugPage = () => (
|
||||
<SpriteViewer sources={sources} />
|
||||
)
|
||||
```
|
||||
|
||||
The Viewer displays groups, search, `viewBox`, CSS custom properties, and fallback colors. React/Next manifests get React, SVG, IMG, and CSS tabs; standalone manifests get SVG, IMG, and CSS. You can change color values in the interface and immediately inspect the result.
|
||||
|
||||
### Viewer theme
|
||||
|
||||
By default, `colorTheme="auto"` follows `prefers-color-scheme`. You can explicitly pass `light` or `dark`:
|
||||
|
||||
```tsx
|
||||
<SpriteViewer sources={sources} colorTheme="dark" />
|
||||
```
|
||||
|
||||
To synchronize it with the application theme:
|
||||
|
||||
```tsx
|
||||
<SpriteViewer
|
||||
sources={sources}
|
||||
colorTheme={appTheme}
|
||||
onColorThemeChange={setAppTheme}
|
||||
/>
|
||||
```
|
||||
|
||||
`@gromlab/svg-sprites/react` contains `'use client'` and renders the Web Component host; its internal Shadow DOM is created after the browser runtime loads. In the Next.js App Router, place the Viewer inside a separate Client Component boundary and use it only on a debug route or in an internal tool.
|
||||
|
||||
## Generated files, Git, and CI
|
||||
|
||||
Every mode except bare `standalone` creates a local `.gitignore` for:
|
||||
|
||||
```text
|
||||
/.svg-sprite/
|
||||
```
|
||||
|
||||
Commit the local `.gitignore` to the repository once. It excludes the other generated files, so generation must run before commands that import the sprite module:
|
||||
|
||||
```json
|
||||
{
|
||||
"scripts": {
|
||||
"sprites": "npx --yes --package=@gromlab/svg-sprites@latest svg-sprites src/ui/app-icons/svg-sprite.config.ts",
|
||||
"predev": "npm run sprites",
|
||||
"prebuild": "npm run sprites",
|
||||
"pretypecheck": "npm run sprites"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
CI must run generation before building or type-checking. Replace `latest` with an exact version for reproducibility. A local package installation is not required unless CI also uses the Viewer, package config types, or the programmatic API.
|
||||
|
||||
Bare `standalone` does not create or modify `.gitignore`; the application decides whether its `.svg-sprite/` output is committed or ignored. In other modes, the generator will not overwrite a user-created `.gitignore`. It also refuses to overwrite a user-owned file inside `.svg-sprite`. The root `index.ts` remains user-owned and may re-export the generated API.
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
- Missing `.svg-sprite/index.js`: run the generation script before importing the generated module.
|
||||
- Source not found: pass an existing config file or sprite module directory.
|
||||
- Mode missing: add `mode` to the config or pass `--mode`.
|
||||
- Icon missing from the type: check `input`, the `.svg` extension, glob exclusions, and whether nested folders require `**/*.svg`.
|
||||
- Name conflict: two different SVG files have the same basename; rename one of them.
|
||||
- `Refusing to overwrite a user file`: a file without the generated marker occupies a managed path.
|
||||
- The icon does not change color: use `<svg><use>` or the generated component and check `replaceColors`.
|
||||
- Webpack emits an incorrect URL: check Asset Modules, `output.publicPath`, and SVG loaders.
|
||||
- Static sprite returns 404: check the post-generation copy or server alias, and do not put a filesystem `spritePath` into HTML.
|
||||
- The Viewer cannot find the sprite: check the path to `.svg-sprite/svg-sprite.manifest.js` and run generation before starting the application.
|
||||
- Build and mode do not match: use the target that corresponds to the actual bundler.
|
||||
|
||||
For custom orchestration and low-level compilation, see the [Programmatic API](programmatic-api.md).
|
||||
Reference in New Issue
Block a user