From e54ab4991c043b6b61d412cee5ca4cffbc3a5107 Mon Sep 17 00:00:00 2001 From: "S.Gromov" Date: Wed, 15 Jul 2026 13:41:24 +0300 Subject: [PATCH] =?UTF-8?q?style:=20=D0=A1=D0=B8=D0=BD=D1=85=D1=80=D0=BE?= =?UTF-8?q?=D0=BD=D0=B8=D0=B7=D0=B8=D1=80=D0=BE=D0=B2=D0=B0=D1=82=D1=8C=20?= =?UTF-8?q?=D0=B0=D0=BD=D0=B3=D0=BB=D0=B8=D0=B9=D1=81=D0=BA=D1=83=D1=8E=20?= =?UTF-8?q?=D0=B4=D0=BE=D0=BA=D1=83=D0=BC=D0=B5=D0=BD=D1=82=D0=B0=D1=86?= =?UTF-8?q?=D0=B8=D1=8E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 83 ++--- docs/en/README.md | 7 +- docs/en/configuration.md | 99 ++++++ docs/en/guides/next-app-turbopack.md | 153 ++++----- docs/en/guides/next-app-webpack.md | 153 ++++----- docs/en/guides/next-pages-turbopack.md | 148 ++++----- docs/en/guides/next-pages-webpack.md | 148 ++++----- docs/en/guides/react-vite.md | 173 +++++------ docs/en/guides/react-webpack.md | 184 +++++------ docs/en/guides/standalone-vite.md | 170 ++++------ docs/en/guides/standalone-webpack.md | 162 ++++------ docs/en/guides/standalone.md | 169 ++++------ docs/en/next-app.md | 4 - docs/en/next-pages.md | 4 - docs/en/programmatic-api.md | 3 - docs/en/react-vite.md | 3 - docs/en/react-webpack.md | 3 - docs/en/reference.md | 3 - docs/en/reference/programmatic-api.md | 42 ++- docs/en/reference/technical.md | 34 +- docs/ru/guides/next-app-turbopack.md | 2 +- docs/ru/guides/next-app-webpack.md | 2 +- docs/ru/guides/next-pages-turbopack.md | 2 +- docs/ru/guides/next-pages-webpack.md | 2 +- docs/ru/guides/react-vite.md | 2 +- docs/ru/guides/react-webpack.md | 10 +- docs/ru/guides/standalone-vite.md | 2 +- docs/ru/guides/standalone-webpack.md | 2 +- skills/README.md | 14 +- skills/svg-sprites/skill.config.mjs | 36 +-- skills/svg-sprites/src/en/SKILL.md | 293 +++++++++++++++++- .../src/en/core/00-package-overview.md | 16 - .../src/en/core/10-mode-selection.md | 30 -- .../src/en/core/20-project-inspection.md | 22 -- .../src/en/core/30-react-next-setup.md | 63 ---- .../src/en/core/40-generated-contract.md | 51 --- .../src/en/core/50-usage-and-colors.md | 87 ------ .../src/en/core/60-verification.md | 15 - .../svg-sprites/src/en/core/70-diagnostics.md | 24 -- .../src/en/references/complex-svg.md | 4 +- .../src/en/references/programmatic-api.md | 46 --- .../src/ru/references/complex-svg.md | 4 +- test/documentation-guides.test.mjs | 43 +-- 43 files changed, 1081 insertions(+), 1436 deletions(-) create mode 100644 docs/en/configuration.md delete mode 100644 docs/en/next-app.md delete mode 100644 docs/en/next-pages.md delete mode 100644 docs/en/programmatic-api.md delete mode 100644 docs/en/react-vite.md delete mode 100644 docs/en/react-webpack.md delete mode 100644 docs/en/reference.md delete mode 100644 skills/svg-sprites/src/en/core/00-package-overview.md delete mode 100644 skills/svg-sprites/src/en/core/10-mode-selection.md delete mode 100644 skills/svg-sprites/src/en/core/20-project-inspection.md delete mode 100644 skills/svg-sprites/src/en/core/30-react-next-setup.md delete mode 100644 skills/svg-sprites/src/en/core/40-generated-contract.md delete mode 100644 skills/svg-sprites/src/en/core/50-usage-and-colors.md delete mode 100644 skills/svg-sprites/src/en/core/60-verification.md delete mode 100644 skills/svg-sprites/src/en/core/70-diagnostics.md delete mode 100644 skills/svg-sprites/src/en/references/programmatic-api.md diff --git a/README.md b/README.md index ab4a13a..22f9bcb 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # @gromlab/svg-sprites -🇬🇧 English | [🇷🇺 Русский](README_RU.md) +🇬🇧 English | [🇷🇺 Русский](https://github.com/gromlab-ru/svg-sprites/blob/master/README_RU.md) ![npm](https://img.shields.io/npm/v/@gromlab/svg-sprites) ![license](https://img.shields.io/npm/l/@gromlab/svg-sprites) @@ -24,20 +24,6 @@ The component accepts familiar SVG attributes: dimensions, `color`, `className`, You do not have to work with the sprite directly in your application. Use it like a regular SVG icon while benefiting from a single component, autocomplete, and TypeScript validation for every name. -In `standalone@vite` and `standalone@webpack`, the same approach works without React: - -```ts -import { defineAppIconElement } from './app-icons' - -defineAppIconElement() -``` - -```html - -``` - -Bare `standalone` remains minimal and generates only an SVG asset and JSON manifest, with no JavaScript runtime. - ## AI-friendly out of the box `@gromlab/svg-sprites` is designed to work with AI agents from the start. Add the ready-made skill and ask an agent to configure, migrate, or troubleshoot the package without lengthy instructions or manual documentation research. @@ -46,62 +32,55 @@ Bare `standalone` remains minimal and generates only an SVG asset and JSON manif [🇷🇺 Download AI skill (Russian)](https://github.com/gromlab-ru/svg-sprites/releases/latest/download/svg-sprites-ru.zip) -## From SVG to component in four steps +## From SVG to component in three steps The main example uses the Next.js App Router and Turbopack. -### 1. Generate without installing the package +### 1. Specify the icons you need -```bash -npx --yes --package=@gromlab/svg-sprites@latest svg-sprites --help -``` - -`npx` downloads the CLI temporarily. It does not add `@gromlab/svg-sprites` to -`package.json`, and the generated production runtime does not import the package. - -### 2. Specify the icons you need - -SVG files can remain in your project's existing structure: +Create directories for the source icons and the sprite: ```text -src/ -├── assets/icons/ -│ ├── search.svg -│ └── settings.svg -├── features/profile/ -│ └── user.svg -└── ui/app-icons/ - └── svg-sprite.config.ts +assets/ +├── app-icons/ +│ └── svg-sprite.config.json +└── svg-icons/ + ├── search.svg + └── settings.svg ``` Create the sprite configuration: -```ts -// src/ui/app-icons/svg-sprite.config.ts -export default { - mode: 'next@app/turbopack', - name: 'app', - input: [ - '../../assets/icons/search.svg', - '../../assets/icons/settings.svg', - '../../features/profile/user.svg', - ], +```json +{ + "mode": "next@app/turbopack", + "name": "app", + "input": "../svg-icons/**/*.svg" } ``` -### 3. Add generation +`input` supports directory paths, individual SVG files, and glob patterns. + +### 2. Add a generation script ```json { "scripts": { - "sprites": "npx --yes --package=@gromlab/svg-sprites@latest svg-sprites src/ui/app-icons/svg-sprite.config.ts", + "sprites": "npx --yes @gromlab/svg-sprites assets/app-icons/svg-sprite.config.json", "predev": "npm run sprites", "prebuild": "npm run sprites" } } ``` -Run it for the first time: +Create an entry point for the generated API: + +```ts +// assets/app-icons/index.ts +export * from './.svg-sprite/index.js' +``` + +First run: ```bash npm run sprites @@ -109,10 +88,11 @@ npm run sprites The package will generate `AppIcon`, TypeScript types, and a separate SVG sprite. -### 4. Use it like a regular icon +### 3. Use it like a regular icon ```tsx -import { AppIcon } from '@/ui/app-icons' +// app/page.tsx +import { AppIcon } from '../assets/app-icons' export default function SearchButton() { return ( @@ -240,7 +220,7 @@ It also provides ready-to-use integration examples for: The Viewer is added only to an internal debug page and does not become part of the generated icon components. -Bare standalone loads the Viewer as a browser script and HTML element; bundler modes use the npm entry, while React and Next.js import `SpriteViewer` from `@gromlab/svg-sprites/react`. +With bare standalone, the application loads the Viewer as a browser script and HTML element; bundler modes use the npm entry, while React and Next.js import `SpriteViewer` from `@gromlab/svg-sprites/react`. ## Standalone, React, and Next.js @@ -277,6 +257,7 @@ This README introduces the project's capabilities and demonstrates the primary u ### Technical resources - [Documentation index](docs/en/README.md) +- [Configuration](docs/en/configuration.md) - [Technical reference](docs/en/reference/technical.md) - [Programmatic API](docs/en/reference/programmatic-api.md) diff --git a/docs/en/README.md b/docs/en/README.md index 23519ca..4adf85e 100644 --- a/docs/en/README.md +++ b/docs/en/README.md @@ -3,6 +3,8 @@ Choose one exact mode guide for setup. The guides are standalone documents and can also be used unchanged by AI skills. +The common format for JSON, JavaScript, and TypeScript config files is described in the [configuration guide](configuration.md). + ## Quick Start Guides | Project | Exact mode | Guide | @@ -20,10 +22,11 @@ can also be used unchanged by AI skills. 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. +2. Use the sprite in the application. +3. Optionally add the Viewer for debugging and previews. ## Reference +- [Configuration](configuration.md) - [Technical reference](reference/technical.md) - [Programmatic API](reference/programmatic-api.md) diff --git a/docs/en/configuration.md b/docs/en/configuration.md new file mode 100644 index 0000000..1c4e847 --- /dev/null +++ b/docs/en/configuration.md @@ -0,0 +1,99 @@ +# Configuration + +Each config file describes one independent sprite. The CLI does not discover config files automatically, so always pass the path explicitly: + +```bash +npx --yes @gromlab/svg-sprites path/to/svg-sprite.config.json +``` + +## JSON + +JSON works for most projects and does not require installing the package locally: + +```json +{ + "mode": "next@app/turbopack", + "name": "app", + "description": "Shared application icons", + "input": [ + "./icons", + "../../assets/icons/**/*.svg", + "!../../assets/icons/deprecated-*.svg" + ], + "transform": { + "removeSize": true, + "replaceColors": true, + "addTransition": true + }, + "generatedNotice": true +} +``` + +| Field | Default | Purpose | +|---|---|---| +| `mode` | None | Exact mode matching the framework and bundler | +| `name` | Kebab-case module directory name; for `svg-sprite` and `svg-sprites`, the parent directory name | Sprite name; in modes with a component, it also determines the component and type names | +| `description` | None | Description used in types and the Viewer | +| `input` | `./icons` | Directory, SVG file, glob pattern, or array of sources | +| `transform` | All enabled | SVG preparation options | +| `generatedNotice` | `true` | Full or compact warning in generated files | + +Paths and glob patterns in `input` are resolved relative to the config file's directory. A pattern prefixed with `!` excludes matches. + +## JavaScript + +A JavaScript config default-exports a plain object: + +```js +export default { + mode: 'react@vite', + name: 'icons', + input: './icons', +} +``` + +Pass the path to the `.js` file to the CLI just like a JSON file: + +```bash +npx --yes @gromlab/svg-sprites path/to/svg-sprite.config.js +``` + +## TypeScript + +To type-check a TypeScript config, install the package as a development dependency: + +```bash +npm install --save-dev @gromlab/svg-sprites +``` + +Use `defineSpriteConfig`: + +```ts +import { defineSpriteConfig } from '@gromlab/svg-sprites' + +export default defineSpriteConfig({ + mode: 'react@vite', + name: 'icons', + input: './icons', +}) +``` + +Alternatively, use `satisfies` with a type-only import: + +```ts +import type { SpriteConfig } from '@gromlab/svg-sprites' + +export default { + mode: 'react@vite', + name: 'icons', + input: './icons', +} satisfies SpriteConfig +``` + +The CLI loads `.ts` config files directly: + +```bash +npx --yes @gromlab/svg-sprites path/to/svg-sprite.config.ts +``` + +For the complete list of modes, CLI flags, naming rules, and transform options, see the [technical reference](reference/technical.md). diff --git a/docs/en/guides/next-app-turbopack.md b/docs/en/guides/next-app-turbopack.md index aaef31a..964be0b 100644 --- a/docs/en/guides/next-app-turbopack.md +++ b/docs/en/guides/next-app-turbopack.md @@ -1,153 +1,108 @@ -# Next.js App Router Turbopack SVG Sprite Quick Start +# SVG Sprite for Next.js App Router with Turbopack -This guide targets the exact mode key `next@app/turbopack`: a generated typed React icon for the Next.js App Router and Turbopack. +A quick guide to creating an SVG sprite in a Next.js application using App Router and Turbopack. -## 1. Generate the sprite +## 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`. +Choose a folder for the sprite. This example uses `assets/app-icons`, with source SVG files, including the `check.svg` used below, in `assets/svg-icons`. -Keep the config and source icons together: +Create `assets/app-icons/svg-sprite.config.json`: -```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', +```json +{ + "mode": "next@app/turbopack", + "name": "app", + "input": "../svg-icons/**/*.svg" } ``` -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: +The `input` path is relative to the config folder. -```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: +Add generation commands to `package.json`. Generated files are excluded from Git by default, so `predev` and `prebuild` rebuild the sprite before every start and build: ```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" + "sprites": "npx --yes @gromlab/svg-sprites assets/app-icons/svg-sprite.config.json", + "predev": "npm run sprites", + "dev": "next dev --turbopack", + "prebuild": "npm run sprites", + "build": "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. +## Use the sprite -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. +The value `name: "app"` creates the React component `AppIcon`. -### Production usage +Create the entry point `assets/app-icons/index.ts`: -The generated icon has no `'use client'` directive and is Server Component-compatible. Import it directly in an App Router page or layout: +```ts +export * from './.svg-sprite/index.js' +``` + +Use the component in a Server Component: ```tsx -// src/app/page.tsx -import { - IconsIcon, - iconsIconNames, -} from '../ui/icons/.svg-sprite/index.js' +// app/page.tsx +import { AppIcon } from '../assets/app-icons' export default function Page() { return ( -
- -

{iconsIconNames.length} icons available

-
+ ) } ``` -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. +`AppIcon` does not need `'use client'`. Turbopack automatically adds `sprite.svg` to the production build, so you do not need to move it to `public`. -## 2. Debug and preview +## Debug and preview -This section is optional. Only users who need the Viewer or icon previews should install: +Viewer displays all icons on one page so you can check their rendering, change colors, and inspect the related CSS variables. It is only needed for development and is installed separately: ```bash npm install --save-dev @gromlab/svg-sprites ``` -Viewer is interactive, so place the React bridge in a separate Client Component: +Create the Client Component `app/svg-sprite/SvgSpriteViewer.tsx`: ```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'), -] + () => import('../../assets/app-icons/.svg-sprite/svg-sprite.manifest.js'), +] as const -export function IconsViewer() { +export function SvgSpriteViewer() { return } ``` -Render it from the route's Server Component: +Create the route `app/svg-sprite/page.tsx`: ```tsx -// src/app/icon-debug/page.tsx -import { IconsViewer } from './IconsViewer' +import { notFound } from 'next/navigation' -export default function IconDebugPage() { - return +import { SvgSpriteViewer } from './SvgSpriteViewer' + +export default function SvgSpritePage() { + if (process.env.NODE_ENV !== 'development') notFound() + + return } ``` -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 -``` +Run `npm run dev` and open `/svg-sprite`. In production, the route returns 404. diff --git a/docs/en/guides/next-app-webpack.md b/docs/en/guides/next-app-webpack.md index 08ac234..c2b91b6 100644 --- a/docs/en/guides/next-app-webpack.md +++ b/docs/en/guides/next-app-webpack.md @@ -1,153 +1,108 @@ -# Next.js App Router Webpack SVG Sprite Quick Start +# SVG Sprite for Next.js App Router with Webpack -This guide targets the exact mode key `next@app/webpack`: a generated typed React icon for the Next.js App Router and Webpack 5. +A quick guide to creating an SVG sprite in a Next.js application using App Router and Webpack. -## 1. Generate the sprite +## 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`. +Choose a folder for the sprite. This example uses `assets/app-icons`, with source SVG files, including the `check.svg` used below, in `assets/svg-icons`. -Keep the config adjacent to its source icons: +Create `assets/app-icons/svg-sprite.config.json`: -```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', +```json +{ + "mode": "next@app/webpack", + "name": "app", + "input": "../svg-icons/**/*.svg" } ``` -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: +The `input` path is relative to the config folder. -```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: +Add generation commands to `package.json`. Generated files are excluded from Git by default, so `predev` and `prebuild` rebuild the sprite before every start and build: ```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" + "sprites": "npx --yes @gromlab/svg-sprites assets/app-icons/svg-sprite.config.json", + "predev": "npm run sprites", + "dev": "next dev --webpack", + "prebuild": "npm run sprites", + "build": "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. +## Use the sprite -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. +The value `name: "app"` creates the React component `AppIcon`. -### Production usage +Create the entry point `assets/app-icons/index.ts`: -The generated icon has no `'use client'` directive and is Server Component-compatible. Import it directly in an App Router page or layout: +```ts +export * from './.svg-sprite/index.js' +``` + +Use the component in a Server Component: ```tsx -// src/app/page.tsx -import { - IconsIcon, - iconsIconNames, -} from '../ui/icons/.svg-sprite/index.js' +// app/page.tsx +import { AppIcon } from '../assets/app-icons' export default function Page() { return ( -
- -

{iconsIconNames.length} icons available

-
+ ) } ``` -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. +`AppIcon` does not need `'use client'`. Next.js automatically adds `sprite.svg` to the production build, so you do not need to move it to `public`. -## 2. Debug and preview +## Debug and preview -This section is optional. Only users who need the Viewer or icon previews should install: +Viewer displays all icons on one page so you can check their rendering, change colors, and inspect the related CSS variables. It is only needed for development and is installed separately: ```bash npm install --save-dev @gromlab/svg-sprites ``` -Viewer is interactive, so place the React bridge in a separate Client Component: +Create the Client Component `app/svg-sprite/SvgSpriteViewer.tsx`: ```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'), -] + () => import('../../assets/app-icons/.svg-sprite/svg-sprite.manifest.js'), +] as const -export function IconsViewer() { +export function SvgSpriteViewer() { return } ``` -Render it from the route's Server Component: +Create the route `app/svg-sprite/page.tsx`: ```tsx -// src/app/icon-debug/page.tsx -import { IconsViewer } from './IconsViewer' +import { notFound } from 'next/navigation' -export default function IconDebugPage() { - return +import { SvgSpriteViewer } from './SvgSpriteViewer' + +export default function SvgSpritePage() { + if (process.env.NODE_ENV !== 'development') notFound() + + return } ``` -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 -``` +Run `npm run dev` and open `/svg-sprite`. In production, the route returns 404. diff --git a/docs/en/guides/next-pages-turbopack.md b/docs/en/guides/next-pages-turbopack.md index a1e53d3..3f0163b 100644 --- a/docs/en/guides/next-pages-turbopack.md +++ b/docs/en/guides/next-pages-turbopack.md @@ -1,140 +1,98 @@ -# Next.js Pages Router Turbopack SVG Sprite Quick Start +# SVG Sprite for Next.js Pages Router with Turbopack -This guide targets the exact mode key `next@pages/turbopack`: a generated typed React icon for the Next.js Pages Router and Turbopack. +A quick guide to creating an SVG sprite in a Next.js application using Pages Router and Turbopack. -## 1. Generate the sprite +## 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`. +Choose a folder for the sprite. This example uses `assets/app-icons`, with source SVG files, including the `check.svg` used below, in `assets/svg-icons`. -Keep the config and source icons together: +Create `assets/app-icons/svg-sprite.config.json`: -```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', +```json +{ + "mode": "next@pages/turbopack", + "name": "app", + "input": "../svg-icons/**/*.svg" } ``` -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: +The `input` path is relative to the config folder. -```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: +Add generation commands to `package.json`. Generated files are excluded from Git by default, so `predev` and `prebuild` rebuild the sprite before every start and build: ```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" + "sprites": "npx --yes @gromlab/svg-sprites assets/app-icons/svg-sprite.config.json", + "predev": "npm run sprites", + "dev": "next dev --turbopack", + "prebuild": "npm run sprites", + "build": "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. +## Use the sprite -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. +The value `name: "app"` creates the React component `AppIcon`. -### Production usage +Create the entry point `assets/app-icons/index.ts`: -Import the generated component and icon-name list into a Pages Router page: +```ts +export * from './.svg-sprite/index.js' +``` + +Use the component on a page: ```tsx -// src/pages/index.tsx -import { - IconsIcon, - iconsIconNames, -} from '../ui/icons/.svg-sprite/index.js' +// pages/index.tsx +import { AppIcon } from '../assets/app-icons' -export default function HomePage() { +export default function Page() { return ( -
- -

{iconsIconNames.length} icons available

-
+ ) } ``` -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. +The component works with SSR, SSG, and client-side navigation. Turbopack automatically adds `sprite.svg` to the production build, so you do not need to move it to `public`. -## 2. Debug and preview +## Debug and preview -This section is optional. Only users who need the Viewer or icon previews should install: +Viewer displays all icons on one page so you can check their rendering, change colors, and inspect the related CSS variables. It is only needed for development and is installed separately: ```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: +Create the page `pages/svg-sprite.tsx`: ```tsx -// src/pages/icon-debug.tsx +import type { GetStaticProps } from 'next' import { SpriteViewer } from '@gromlab/svg-sprites/react' const sources = [ - () => import('../ui/icons/.svg-sprite/svg-sprite.manifest.js'), -] + () => import('../assets/app-icons/.svg-sprite/svg-sprite.manifest.js'), +] as const -export default function IconDebugPage() { +export default function SvgSpritePage() { return } + +export const getStaticProps: GetStaticProps = () => + process.env.NODE_ENV === 'development' + ? { props: {} } + : { notFound: true } ``` -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 -``` +Run `npm run dev` and open `/svg-sprite`. In production, the route returns 404. diff --git a/docs/en/guides/next-pages-webpack.md b/docs/en/guides/next-pages-webpack.md index 32a97b2..5c19d93 100644 --- a/docs/en/guides/next-pages-webpack.md +++ b/docs/en/guides/next-pages-webpack.md @@ -1,140 +1,98 @@ -# Next.js Pages Router Webpack SVG Sprite Quick Start +# SVG Sprite for Next.js Pages Router with Webpack -This guide targets the exact mode key `next@pages/webpack`: a generated typed React icon for the Next.js Pages Router and Webpack 5. +A quick guide to creating an SVG sprite in a Next.js application using Pages Router and Webpack. -## 1. Generate the sprite +## 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`. +Choose a folder for the sprite. This example uses `assets/app-icons`, with source SVG files, including the `check.svg` used below, in `assets/svg-icons`. -Keep the config adjacent to its source icons: +Create `assets/app-icons/svg-sprite.config.json`: -```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', +```json +{ + "mode": "next@pages/webpack", + "name": "app", + "input": "../svg-icons/**/*.svg" } ``` -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: +The `input` path is relative to the config folder. -```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: +Add generation commands to `package.json`. Generated files are excluded from Git by default, so `predev` and `prebuild` rebuild the sprite before every start and build: ```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" + "sprites": "npx --yes @gromlab/svg-sprites assets/app-icons/svg-sprite.config.json", + "predev": "npm run sprites", + "dev": "next dev --webpack", + "prebuild": "npm run sprites", + "build": "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. +## Use the sprite -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. +The value `name: "app"` creates the React component `AppIcon`. -### Production usage +Create the entry point `assets/app-icons/index.ts`: -Import the generated component and icon-name list into a Pages Router page: +```ts +export * from './.svg-sprite/index.js' +``` + +Use the component on a page: ```tsx -// src/pages/index.tsx -import { - IconsIcon, - iconsIconNames, -} from '../ui/icons/.svg-sprite/index.js' +// pages/index.tsx +import { AppIcon } from '../assets/app-icons' -export default function HomePage() { +export default function Page() { return ( -
- -

{iconsIconNames.length} icons available

-
+ ) } ``` -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. +The component works with SSR, SSG, and client-side navigation. Next.js automatically adds `sprite.svg` to the production build, so you do not need to move it to `public`. -## 2. Debug and preview +## Debug and preview -This section is optional. Only users who need the Viewer or icon previews should install: +Viewer displays all icons on one page so you can check their rendering, change colors, and inspect the related CSS variables. It is only needed for development and is installed separately: ```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: +Create the page `pages/svg-sprite.tsx`: ```tsx -// src/pages/icon-debug.tsx +import type { GetStaticProps } from 'next' import { SpriteViewer } from '@gromlab/svg-sprites/react' const sources = [ - () => import('../ui/icons/.svg-sprite/svg-sprite.manifest.js'), -] + () => import('../assets/app-icons/.svg-sprite/svg-sprite.manifest.js'), +] as const -export default function IconDebugPage() { +export default function SvgSpritePage() { return } + +export const getStaticProps: GetStaticProps = () => + process.env.NODE_ENV === 'development' + ? { props: {} } + : { notFound: true } ``` -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 -``` +Run `npm run dev` and open `/svg-sprite`. In production, the route returns 404. diff --git a/docs/en/guides/react-vite.md b/docs/en/guides/react-vite.md index 96ed9ea..d51cf11 100644 --- a/docs/en/guides/react-vite.md +++ b/docs/en/guides/react-vite.md @@ -1,148 +1,115 @@ -# React Vite SVG Sprite Quick Start +# SVG Sprite for React with Vite -This guide targets the exact mode key `react@vite`: a generated typed React component with a Vite-managed SVG asset. +A quick guide to creating an SVG sprite in a React application built with Vite. -## 1. Generate the sprite +## 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`. +Choose a folder for the sprite. This example uses `assets/app-icons`, with source SVG files, including the `check.svg` used below, in `assets/svg-icons`. -Keep the config and source icons together: +Create `assets/app-icons/svg-sprite.config.json`: -```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', +```json +{ + "mode": "react@vite", + "name": "app", + "input": "../svg-icons/**/*.svg" } ``` -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: +The `input` path is relative to the config folder. -```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: +Add generation commands to `package.json`. Generated files are excluded from Git by default, so `predev` and `prebuild` rebuild the sprite before every start and build: ```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" + "sprites": "npx --yes @gromlab/svg-sprites assets/app-icons/svg-sprite.config.json", + "predev": "npm run sprites", + "dev": "vite", + "prebuild": "npm run sprites", + "build": "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. +## Use the sprite -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. +The value `name: "app"` creates the React component `AppIcon`. -### Production usage +Create the entry point `assets/app-icons/index.ts`: -Import the generated component and icon-name list directly: +```ts +export * from './.svg-sprite/index.js' +``` + +Use the component in your application: ```tsx -// src/App.tsx -import { - IconsIcon, - iconsIconNames, -} from './ui/icons/.svg-sprite/index.js' +import { AppIcon } from '../assets/app-icons' -export function App() { +export function SaveIcon() { return ( -
- - {iconsIconNames.length} icons available -
+ ) } ``` -`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: +The `icon` prop accepts source SVG file names without the extension. A monochrome icon inherits `color`, while colors in a multicolor icon are overridden with `--icon-color-N`. -```json -{ - "compilerOptions": { - "types": ["vite/client"] - } -} -``` +Vite automatically includes the component styles and adds `sprite.svg` to the production build. -## 2. Debug and preview +## Debug and preview -This section is optional. Only users who need the Viewer or icon previews should install: +Viewer displays all icons on one page so you can check their rendering, change colors, and inspect the related CSS variables. It is only needed for development and is installed separately: ```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: +Create `svg-sprite.html` in the project root: + +```html + + + + + Project icons + + + +
+ + + + + +``` + +Create `src/svg-sprite-debug.tsx`: ```tsx -// src/IconsDebugPage.tsx +import { createRoot } from 'react-dom/client' import { SpriteViewer } from '@gromlab/svg-sprites/react' const sources = [ - () => import('./ui/icons/.svg-sprite/svg-sprite.manifest.js'), -] + () => import('../assets/app-icons/.svg-sprite/svg-sprite.manifest.js'), +] as const -export function IconsDebugPage() { - return -} +createRoot(document.getElementById('svg-sprite-viewer')!).render( + , +) ``` -Keep this component on a debug route or in an internal tool. Viewer is not part of the production icon runtime. +Run `npm run dev` and open `/svg-sprite.html`. -## 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 -``` +The standard Vite production build uses only `index.html` and does not include the Viewer page. diff --git a/docs/en/guides/react-webpack.md b/docs/en/guides/react-webpack.md index 31a83fd..9153adb 100644 --- a/docs/en/guides/react-webpack.md +++ b/docs/en/guides/react-webpack.md @@ -1,156 +1,132 @@ -# React Webpack SVG Sprite Quick Start +# SVG Sprite for React with Webpack 5 -This guide targets the exact mode key `react@webpack`: a generated typed React component using Webpack 5 Asset Modules and CSS Modules. +A quick guide to creating an SVG sprite in a React application built with Webpack 5. -## 1. Generate the sprite +## 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`. +Choose a folder for the sprite. This example uses `assets/app-icons`, with source SVG files, including the `check.svg` used below, in `assets/svg-icons`. -Keep the config adjacent to its source icons: +Create `assets/app-icons/svg-sprite.config.json`: -```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', +```json +{ + "mode": "react@webpack", + "name": "app", + "input": "../svg-icons/**/*.svg" } ``` -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: +The `input` path is relative to the config folder. -```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: +Add generation commands to `package.json`. Generated files are excluded from Git by default, so `predev` and `prebuild` rebuild the sprite before every start and build: ```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" + "sprites": "npx --yes @gromlab/svg-sprites assets/app-icons/svg-sprite.config.json", + "predev": "npm run sprites", + "dev": "webpack serve --mode development", + "prebuild": "npm run sprites", + "build": "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. +## Use the sprite -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. +The value `name: "app"` creates the React component `AppIcon`. -### Production usage +Create the entry point `assets/app-icons/index.ts`: -Import the generated component and icon-name list directly: +```ts +export * from './.svg-sprite/index.js' +``` + +Use the component in your application: ```tsx -// src/App.tsx -import { - IconsIcon, - iconsIconNames, -} from './ui/icons/.svg-sprite/index.js' +import { AppIcon } from '../assets/app-icons' -export function App() { +export function SaveIcon() { return ( -
- - {iconsIconNames.length} icons available -
+ ) } ``` -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 `icon` prop accepts source SVG file names without the extension. A monochrome icon inherits `color`, while colors in a multicolor icon are overridden with `--icon-color-N`. -The generated component also imports `react-component.module.css`. Configure `.module.css` through `css-loader` with modules enabled, plus `style-loader` or `MiniCssExtractPlugin`: +The component uses CSS Modules. If the project does not process them yet, install the loaders: + +```bash +npm install --save-dev style-loader css-loader +``` + +Then add a rule with a default export to `webpack.config.js`: ```js -// webpack.config.js (relevant rule) -export default { - module: { - rules: [ - { - test: /\.module\.css$/i, - use: ['style-loader', { loader: 'css-loader', options: { modules: true } }], - }, - ], - }, +{ + test: /\.module\.css$/i, + use: [ + 'style-loader', + { + loader: 'css-loader', + options: { modules: { namedExport: false } }, + }, + ], } ``` -## 2. Debug and preview +Webpack 5 automatically adds `sprite.svg` to the production build. -This section is optional. Only users who need the Viewer or icon previews should install: +## Debug and preview + +Viewer displays all icons on one page so you can check their rendering, change colors, and inspect the related CSS variables. It is only needed for development. + +Install Viewer: ```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: +Create the entry `src/svg-sprite-debug.tsx`: ```tsx -// src/IconsDebugPage.tsx +import { createRoot } from 'react-dom/client' import { SpriteViewer } from '@gromlab/svg-sprites/react' const sources = [ - () => import('./ui/icons/.svg-sprite/svg-sprite.manifest.js'), -] + () => import('../assets/app-icons/.svg-sprite/svg-sprite.manifest.js'), +] as const -export function IconsDebugPage() { - return -} +const container = document.createElement('div') +document.body.append(container) + +createRoot(container).render( + , +) ``` -Keep this component on a debug route or in an internal tool. Viewer is not part of the production icon runtime. +Add the script to the main entry only in development mode. Keep the rest of your `webpack.config.js` settings: -## 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', +```js +export default (_env, argv) => ({ + // Other Webpack settings. + entry: [ + './src/main.tsx', + ...(argv.mode === 'development' ? ['./src/svg-sprite-debug.tsx'] : []), + ], }) ``` -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 -``` +Run `npm run dev`. Viewer appears on the application's main page and is not included in the production build. diff --git a/docs/en/guides/standalone-vite.md b/docs/en/guides/standalone-vite.md index 27f151e..ab46219 100644 --- a/docs/en/guides/standalone-vite.md +++ b/docs/en/guides/standalone-vite.md @@ -1,156 +1,114 @@ -# Standalone Vite SVG Sprite Quick Start +# SVG Sprite for Vite Without a Framework -This guide targets the exact mode key `standalone@vite`: a native generated Web Component with Vite-managed SVG assets. +A quick guide to creating an SVG sprite in a Vite application without a framework. -## 1. Generate the sprite +## 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`. +Choose a folder for the sprite. This example uses `assets/app-icons`, with source SVG files, including the `check.svg` used below, in `assets/svg-icons`. -Keep the config and source icons together: +Create `assets/app-icons/svg-sprite.config.json`: -```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', +```json +{ + "mode": "standalone@vite", + "name": "app", + "input": "../svg-icons/**/*.svg" } ``` -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: +The `input` path is relative to the config folder. -```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: +Add generation commands to `package.json`. Generated files are excluded from Git by default, so `predev` and `prebuild` rebuild the sprite before every start and build: ```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" + "sprites": "npx --yes @gromlab/svg-sprites assets/app-icons/svg-sprite.config.json", + "predev": "npm run sprites", + "dev": "vite", + "prebuild": "npm run sprites", + "build": "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. +## Use the sprite -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`. +The value `name: "app"` creates the `` element. -### Production usage - -Register the generated element once, then use ``: +Create the entry point `assets/app-icons/index.ts`: ```ts -// src/main.ts -import { - defineIconsIconElement, - iconsIconNames, -} from './ui/icons/.svg-sprite/index.js' - -defineIconsIconElement() -console.log('Available icons:', iconsIconNames) +export * from './.svg-sprite/index.js' ``` +Register the element in `src/main.ts`: + +```ts +import { defineAppIconElement } from '../assets/app-icons' +import './style.css' + +defineAppIconElement() +``` + +Use the icon in HTML: + ```html - + ``` -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`: +The file `check.svg` is available as `icon="check"`. Set its size and colors with CSS: ```css -icons-icon { +app-icon { font-size: 24px; - color: #2563eb; - --icon-color-2: #dbeafe; + color: #334155; + --icon-color-2: #f59e0b; } ``` -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: +A monochrome icon inherits `color`, while colors in a multicolor icon are overridden with `--icon-color-N`. Viewer shows the variables you need. -```json -{ - "compilerOptions": { - "types": ["vite/client"] - } -} -``` +Vite automatically adds `sprite.svg` to the production build. You do not need to copy it to `public`. -## 2. Debug and preview +## Debug and preview -This section is optional. Only users who need the Viewer or icon previews should install: +Viewer displays all icons on one page so you can check their rendering, change colors, and inspect the related CSS variables. It is only needed for development and is installed separately: ```bash npm install --save-dev @gromlab/svg-sprites ``` -Register the Viewer element, import its type, and assign the generated JavaScript manifest to `sources`: +Create `svg-sprite.html` in the project root: + +```html + + + + + Project icons + + + + + + + + + +``` + +Create `src/svg-sprite-debug.ts`: ```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('#debug')!.innerHTML = ` - -` +import spriteManifest from '../assets/app-icons/.svg-sprite/svg-sprite.manifest.js' const viewer = document.querySelector('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. +Run `npm run dev` and open `/svg-sprite.html`. -## 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 -``` +Viewer is not required for `` and is not imported by the application's main code. diff --git a/docs/en/guides/standalone-webpack.md b/docs/en/guides/standalone-webpack.md index 29e477b..94d663d 100644 --- a/docs/en/guides/standalone-webpack.md +++ b/docs/en/guides/standalone-webpack.md @@ -1,143 +1,111 @@ -# Standalone Webpack SVG Sprite Quick Start +# SVG Sprite for Webpack 5 Without a Framework -This guide targets the exact mode key `standalone@webpack`: a native generated Web Component using Webpack 5 Asset Modules. +A quick guide to creating an SVG sprite in a Webpack 5 application without a framework. -## 1. Generate the sprite +## 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`. +Choose a folder for the sprite. This example uses `assets/app-icons`, with source SVG files, including the `check.svg` used below, in `assets/svg-icons`. -Keep the config adjacent to its source icons: +Create `assets/app-icons/svg-sprite.config.json`: -```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', +```json +{ + "mode": "standalone@webpack", + "name": "app", + "input": "../svg-icons/**/*.svg" } ``` -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: +The `input` path is relative to the config folder. -```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: +Add generation commands to `package.json`. Generated files are excluded from Git by default, so `predev` and `prebuild` rebuild the sprite before every start and build: ```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" + "sprites": "npx --yes @gromlab/svg-sprites assets/app-icons/svg-sprite.config.json", + "predev": "npm run sprites", + "dev": "webpack serve --mode development", + "prebuild": "npm run sprites", + "build": "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. +## Use the sprite -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. +The value `name: "app"` creates the `` element. -### Production usage - -Register the generated element once, then use ``: +Create the entry point `assets/app-icons/index.ts`: ```ts -// src/main.ts -import { - defineIconsIconElement, - iconsIconNames, -} from './ui/icons/.svg-sprite/index.js' - -defineIconsIconElement() -console.log('Available icons:', iconsIconNames) +export * from './.svg-sprite/index.js' ``` +Register the element in the application's main entry: + +```ts +import { defineAppIconElement } from '../assets/app-icons' +import './style.css' + +defineAppIconElement() +``` + +Use the icon in HTML: + ```html - + ``` -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. +The file `check.svg` is available as `icon="check"`. Set its size and colors with CSS: -## 2. Debug and preview +```css +app-icon { + font-size: 24px; + color: #334155; + --icon-color-2: #f59e0b; +} +``` -This section is optional. Only users who need the Viewer or icon previews should install: +A monochrome icon inherits `color`, while colors in a multicolor icon are overridden with `--icon-color-N`. Viewer shows the variables you need. + +Webpack 5 automatically adds `sprite.svg` to the production build. + +## Debug and preview + +Viewer displays all icons on one page so you can check their rendering, change colors, and inspect the related CSS variables. It is only needed for development. + +Install Viewer: ```bash npm install --save-dev @gromlab/svg-sprites ``` -Register the Viewer element, import its type, and assign the generated JavaScript manifest to `sources`: +Create the entry `src/svg-sprite-debug.ts`: ```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' +import spriteManifest from '../assets/app-icons/.svg-sprite/svg-sprite.manifest.js' -document.querySelector('#debug')!.innerHTML = ` - -` - -const viewer = document.querySelector('gromlab-sprite-viewer')! +const viewer = document.createElement('gromlab-sprite-viewer') as SpriteViewerElement +viewer.viewerTitle = 'Project icons' viewer.sources = [spriteManifest] +document.body.append(viewer) ``` -Keep this code on a debug route or in an internal tool. Viewer is not part of the production icon runtime. +Add the script to the main entry only in development mode. Keep the rest of your `webpack.config.js` settings: -## 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', +```js +export default (_env, argv) => ({ + // Other Webpack settings. + entry: [ + './src/main.ts', + ...(argv.mode === 'development' ? ['./src/svg-sprite-debug.ts'] : []), + ], }) ``` -You can alternatively import `type SpriteConfig` and apply `satisfies SpriteConfig`. +Run `npm run dev`. Viewer appears on the application's main page. -### 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 -``` +Viewer is only added to the development build and is not included in production. diff --git a/docs/en/guides/standalone.md b/docs/en/guides/standalone.md index 4309921..47b715b 100644 --- a/docs/en/guides/standalone.md +++ b/docs/en/guides/standalone.md @@ -1,22 +1,26 @@ -# Standalone SVG Sprite Quick Start +# SVG Sprite for a Site Without a Bundler -This guide targets the exact mode key `standalone`: static HTML or a custom asset pipeline with no generated JavaScript facade. +Combine SVG icons into one file and use them on an HTML page. -## 1. Generate the sprite +## 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. +You do not need to install the package in your project. -Keep the config next to its source icons: +This guide uses the following project structure: ```text -src/ui/icons/ -├── icons/ -│ ├── check.svg -│ └── folder.svg -└── svg-sprite.config.json +/ +├── index.html +└── assets/ + ├── app-icons/ + └── svg-icons/ + ├── check.svg + └── warning.svg ``` -Create a JSON config: +### 1. Create the sprite config + +Choose a folder for the sprite. This example uses `assets/app-icons`. Create `svg-sprite.config.json` inside it: ```json { @@ -25,147 +29,80 @@ Create a JSON config: } ``` -When `input` is omitted, the generator reads `./icons` next to the config. +### 2. Set the icon source -To include SVG files from nested directories, set one glob pattern: +`input` can point to a folder, an individual SVG file, or a glob pattern. To use multiple sources, provide an array with any combination of these values: ```json { "mode": "standalone", "name": "icons", - "input": "../assets/icons/**/*.svg" + "input": "../svg-icons/**/*.svg" } ``` -An array can mix folders, individual SVG files, and glob patterns: +### 3. Generate the sprite -```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: +Pass the config path to the command: ```bash -npx --yes --package=@gromlab/svg-sprites@latest svg-sprites src/ui/icons/svg-sprite.config.json +npx --yes @gromlab/svg-sprites assets/app-icons/svg-sprite.config.json ``` -For repeatable local commands, the same temporary CLI can be used from a script: +The package collects the icons in a `.svg-sprite` directory next to the config: -```json -{ - "scripts": { - "sprites": "npx --yes --package=@gromlab/svg-sprites@latest svg-sprites src/ui/icons/svg-sprite.config.json" - } -} +```text +assets/app-icons/.svg-sprite/ +├── sprite.svg +└── svg-sprite.manifest.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. +- `sprite.svg` is the finished sprite for use on the site. +- `svg-sprite.manifest.json` contains icon data for Viewer. -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. +The `.svg-sprite` directory is created automatically and fully replaced on every generation. Do not edit its contents manually. -### Production usage +### 4. Use an icon -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: +In `index.html`, point to the generated `sprite.svg`. After `#`, add the icon file name without the `.svg` extension: ```html - - + + ``` -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. +The icon from `check.svg` is available as `#check`. -## 2. Debug and preview +## Debug and preview -This section is optional. Only install the package locally if you need the debug Viewer or an icon preview: +`sprite.svg` is a technical file, not an icon gallery. Opening it does not provide a convenient view of the whole set. Gradients, masks, filters, and references to internal `id` values may also render with artifacts. -```bash -npm install --save-dev @gromlab/svg-sprites -``` +Use the official Viewer for visual checks. It displays every icon in the sprite and helps you verify its colors and rendering. -Without a bundler, self-host the browser bundle by copying it from `node_modules` into the deploy output: +Viewer is optional and intended only for development. You do not need to install the package through npm. -```bash -cp node_modules/@gromlab/svg-sprites/dist/viewer-element.js public/debug/viewer-element.js -``` +Viewer works directly with files from `.svg-sprite`. Nothing needs to be copied. -Then provide both public asset URLs through HTML attributes: +### Add Viewer to the page -```html - - - -``` - -For a quick preview, a pinned CDN file can replace the self-hosted script: +Add a module script to `index.html` and provide paths to the generated manifest and sprite: ```html + + ``` -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 -``` +You can move Viewer to a separate HTML file in the site root used only for development and icon checks. diff --git a/docs/en/next-app.md b/docs/en/next-app.md deleted file mode 100644 index 97c95a7..0000000 --- a/docs/en/next-app.md +++ /dev/null @@ -1,4 +0,0 @@ -# Next.js App Router Guides Moved - -- [App Router + Turbopack](guides/next-app-turbopack.md) -- [App Router + Webpack](guides/next-app-webpack.md) diff --git a/docs/en/next-pages.md b/docs/en/next-pages.md deleted file mode 100644 index c4763b9..0000000 --- a/docs/en/next-pages.md +++ /dev/null @@ -1,4 +0,0 @@ -# Next.js Pages Router Guides Moved - -- [Pages Router + Turbopack](guides/next-pages-turbopack.md) -- [Pages Router + Webpack](guides/next-pages-webpack.md) diff --git a/docs/en/programmatic-api.md b/docs/en/programmatic-api.md deleted file mode 100644 index ad49c97..0000000 --- a/docs/en/programmatic-api.md +++ /dev/null @@ -1,3 +0,0 @@ -# Programmatic API Moved - -The canonical document is now the [programmatic API](reference/programmatic-api.md). diff --git a/docs/en/react-vite.md b/docs/en/react-vite.md deleted file mode 100644 index ed23a3c..0000000 --- a/docs/en/react-vite.md +++ /dev/null @@ -1,3 +0,0 @@ -# React + Vite Guide Moved - -The canonical guide is now [React + Vite](guides/react-vite.md). diff --git a/docs/en/react-webpack.md b/docs/en/react-webpack.md deleted file mode 100644 index dbdd36c..0000000 --- a/docs/en/react-webpack.md +++ /dev/null @@ -1,3 +0,0 @@ -# React + Webpack Guide Moved - -The canonical guide is now [React + Webpack](guides/react-webpack.md). diff --git a/docs/en/reference.md b/docs/en/reference.md deleted file mode 100644 index 8138c45..0000000 --- a/docs/en/reference.md +++ /dev/null @@ -1,3 +0,0 @@ -# Technical Reference Moved - -The canonical document is now the [technical reference](reference/technical.md). diff --git a/docs/en/reference/programmatic-api.md b/docs/en/reference/programmatic-api.md index cef0c34..a875156 100644 --- a/docs/en/reference/programmatic-api.md +++ b/docs/en/reference/programmatic-api.md @@ -14,6 +14,24 @@ const result = await generateSprite( ) ``` +The result contains the sprite name, exact mode, mode-specific asset target, icon count, and absolute filesystem paths: + +```ts +result.name +result.mode +result.target +result.iconCount +result.rootDir +result.generatedDir +result.spritePath +result.manifestPath +``` + +Next.js modes additionally return `router` and `bundler`. +For bare `standalone`, `target` is `static`; standalone bundler and React modes +return `vite` or `webpack`; Next.js modes return their full exact mode as the +target. + For static standalone mode, use `result.spritePath` in a build script to publish the SVG under an application URL: @@ -29,7 +47,7 @@ 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 first argument accepts an absolute or relative 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: @@ -51,7 +69,7 @@ Configuration is resolved in this order: defaults → config → API overrides ``` -For fully programmatic generation, pass a directory and provide the required settings as overrides: +For fully programmatic generation, pass a directory and provide the required `mode` and any other settings as overrides. `name` is optional: when omitted, it is inferred in kebab-case from the directory name, or from the parent directory when the module directory is named `svg-sprite` or `svg-sprites`: ```ts await generateSprite('src/ui/file-manager/svg-sprite', { @@ -107,13 +125,17 @@ An explicitly supplied target overrides `mode` from the file. Prefer `generateSp ```ts import { + isSpriteMode, loadSpriteConfig, resolveSpriteConfig, + resolveSpriteConfigSource, validateSpriteConfig, } from '@gromlab/svg-sprites' ``` +- `isSpriteMode(value)` checks whether a value is a supported exact mode. - `loadSpriteConfig(file)` loads an explicitly selected `.ts`, `.js`, or `.json` file. +- `resolveSpriteConfigSource(source)` resolves a path as either a config file or a config-less directory. - `validateSpriteConfig(value)` performs runtime validation. - `resolveSpriteConfig(root, config, overrides)` merges values, applies defaults, and resolves paths relative to `root`. @@ -138,6 +160,22 @@ import type { SpriteViewerElement } from '@gromlab/svg-sprites/viewer' The browser entry registers ``. Bare standalone can also load the self-contained `dist/viewer-element.js` without a bundler. +For manual registration, import the runtime without the auto-register entry: + +```ts +import { defineSpriteViewerElement } from '@gromlab/svg-sprites/viewer' + +defineSpriteViewerElement() +``` + +Both Viewer entries export the registration function and the same public types: +`SpriteViewerColorTheme`, `SpriteViewerElement`, `SpriteViewerManifest`, +`SpriteViewerManifestColor`, `SpriteViewerManifestIcon`, +`SpriteViewerManifestLoader`, `SpriteViewerManifestModule`, +`SpriteViewerManifestUsage`, `SpriteViewerRemoteSource`, `SpriteViewerSource`, +and `SpriteViewerSources`. Only `@gromlab/svg-sprites/viewer/element` registers the +element as an import side effect. + The React bridge keeps the component API: ```tsx diff --git a/docs/en/reference/technical.md b/docs/en/reference/technical.md index d89a8ce..86822a6 100644 --- a/docs/en/reference/technical.md +++ b/docs/en/reference/technical.md @@ -2,6 +2,8 @@ [Documentation index](../README.md) +[JSON, JavaScript, and TypeScript configuration](../configuration.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) @@ -24,7 +26,7 @@ Reference for the configuration, generated API, and behavior of `@gromlab/svg-sp 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 +npx --yes @gromlab/svg-sprites path/to/svg-sprite.config.json ``` Install the package as a development dependency only when the project needs the @@ -54,11 +56,11 @@ svg-sprites [options] | 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. +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 recommended name is `svg-sprite.config.json`. 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 `, 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. +`--help` and `-h` print usage information without requiring a path. Generation options are `--mode`, `--name`, `--description`, repeatable `--input `, 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: @@ -96,7 +98,7 @@ export default defineSpriteConfig({ | 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 | +| `name` | `string` | Derived from the directory | Sprite name; in modes with a component, it also determines the component and public type names | | `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 | @@ -111,7 +113,7 @@ 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. +If `name` is omitted, the generator converts the directory name to kebab-case. For a directory named `svg-sprite` or `svg-sprites`, the parent directory's name is used. ### Icon sources @@ -141,7 +143,7 @@ After generation, a React or Next.js sprite directory looks like this: ```text app-icons/ ├── .gitignore -├── svg-sprite.config.ts +├── svg-sprite.config.json ├── index.ts # optional user-owned barrel └── .svg-sprite/ ├── index.js @@ -183,10 +185,10 @@ runtime asset and deployment-neutral manifest data: 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: +The generator fully manages `.svg-sprite` and replaces the whole directory on every generation through a staged write with rollback on replacement failure. Any files added inside it are deleted during the next generation. Keep user-owned files alongside it, for example in a root `index.ts` barrel: ```ts -export * from './.svg-sprite' +export * from './.svg-sprite/index.js' ``` ## Standalone Web Component and TypeScript @@ -308,7 +310,7 @@ The component does not add accessibility semantics automatically. Pass appropria ## Multiple sprites -Each directory with a configuration creates an independent component, types, manifest, and SVG asset: +Each directory with a configuration creates an independent mode-specific contract. React and Next.js modes generate a React component and types, `standalone@vite` and `standalone@webpack` generate a Web Component and types, and bare `standalone` generates an SVG and JSON manifest: ```text app-icons → AppIcon → shared icons @@ -354,7 +356,7 @@ Static HTML after the application publishes `.svg-sprite/sprite.svg`: ``` -Standalone Vite/Webpack provides generated `getIconsIconHref()` and an internal ID +Standalone Vite/Webpack provides generated `getAppIconHref()` and an internal ID map. Do not construct fragments from unsafe file names manually. Vite: @@ -603,7 +605,7 @@ Commit the local `.gitignore` to the repository once. It excludes the other gene ```json { "scripts": { - "sprites": "npx --yes --package=@gromlab/svg-sprites@latest svg-sprites src/ui/app-icons/svg-sprite.config.ts", + "sprites": "npx --yes @gromlab/svg-sprites src/ui/app-icons/svg-sprite.config.ts", "predev": "npm run sprites", "prebuild": "npm run sprites", "pretypecheck": "npm run sprites" @@ -611,22 +613,22 @@ Commit the local `.gitignore` to the repository once. It excludes the other gene } ``` -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. +CI must run generation before building or type-checking. Pin `@gromlab/svg-sprites` to an exact version when the CI toolchain must be reproducible. 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. +Bare `standalone` does not create a `.gitignore` and preserves a user-owned file. If a managed `.gitignore` remains after another mode, bare mode removes it. In every other mode, the generator refuses to overwrite a user-owned `.gitignore` without a generated marker. 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. +- In every mode except bare `standalone`, 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. +- `Refusing to overwrite a user file`: the sprite module root contains a user-owned `.gitignore` that the generator cannot replace. - The icon does not change color: 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. +- The Viewer cannot find the sprite: in bundler modes, check the path to `.svg-sprite/svg-sprite.manifest.js`; for bare `standalone`, check the published `svg-sprite.manifest.json` and `sprite.svg` URLs. 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). diff --git a/docs/ru/guides/next-app-turbopack.md b/docs/ru/guides/next-app-turbopack.md index 12d8d66..5b6d7eb 100644 --- a/docs/ru/guides/next-app-turbopack.md +++ b/docs/ru/guides/next-app-turbopack.md @@ -4,7 +4,7 @@ ## Генерация спрайта -Выберите папку для спрайта. В примере используется `assets/app-icons`, а исходные SVG находятся в `assets/svg-icons`. +Выберите папку для спрайта. В примере используется `assets/app-icons`, а исходные SVG, включая используемый ниже `check.svg`, находятся в `assets/svg-icons`. Создайте конфиг `assets/app-icons/svg-sprite.config.json`: diff --git a/docs/ru/guides/next-app-webpack.md b/docs/ru/guides/next-app-webpack.md index 493f202..3b8c683 100644 --- a/docs/ru/guides/next-app-webpack.md +++ b/docs/ru/guides/next-app-webpack.md @@ -4,7 +4,7 @@ ## Генерация спрайта -Выберите папку для спрайта. В примере используется `assets/app-icons`, а исходные SVG находятся в `assets/svg-icons`. +Выберите папку для спрайта. В примере используется `assets/app-icons`, а исходные SVG, включая используемый ниже `check.svg`, находятся в `assets/svg-icons`. Создайте конфиг `assets/app-icons/svg-sprite.config.json`: diff --git a/docs/ru/guides/next-pages-turbopack.md b/docs/ru/guides/next-pages-turbopack.md index 638c690..7c10e58 100644 --- a/docs/ru/guides/next-pages-turbopack.md +++ b/docs/ru/guides/next-pages-turbopack.md @@ -4,7 +4,7 @@ ## Генерация спрайта -Выберите папку для спрайта. В примере используется `assets/app-icons`, а исходные SVG находятся в `assets/svg-icons`. +Выберите папку для спрайта. В примере используется `assets/app-icons`, а исходные SVG, включая используемый ниже `check.svg`, находятся в `assets/svg-icons`. Создайте конфиг `assets/app-icons/svg-sprite.config.json`: diff --git a/docs/ru/guides/next-pages-webpack.md b/docs/ru/guides/next-pages-webpack.md index d98d63a..e44e2fb 100644 --- a/docs/ru/guides/next-pages-webpack.md +++ b/docs/ru/guides/next-pages-webpack.md @@ -4,7 +4,7 @@ ## Генерация спрайта -Выберите папку для спрайта. В примере используется `assets/app-icons`, а исходные SVG находятся в `assets/svg-icons`. +Выберите папку для спрайта. В примере используется `assets/app-icons`, а исходные SVG, включая используемый ниже `check.svg`, находятся в `assets/svg-icons`. Создайте конфиг `assets/app-icons/svg-sprite.config.json`: diff --git a/docs/ru/guides/react-vite.md b/docs/ru/guides/react-vite.md index 320168c..67503a0 100644 --- a/docs/ru/guides/react-vite.md +++ b/docs/ru/guides/react-vite.md @@ -4,7 +4,7 @@ ## Генерация спрайта -Выберите папку для спрайта. В примере используется `assets/app-icons`, а исходные SVG находятся в `assets/svg-icons`. +Выберите папку для спрайта. В примере используется `assets/app-icons`, а исходные SVG, включая используемый ниже `check.svg`, находятся в `assets/svg-icons`. Создайте конфиг `assets/app-icons/svg-sprite.config.json`: diff --git a/docs/ru/guides/react-webpack.md b/docs/ru/guides/react-webpack.md index b265fc7..b7e201b 100644 --- a/docs/ru/guides/react-webpack.md +++ b/docs/ru/guides/react-webpack.md @@ -4,7 +4,7 @@ ## Генерация спрайта -Выберите папку для спрайта. В примере используется `assets/app-icons`, а исходные SVG находятся в `assets/svg-icons`. +Выберите папку для спрайта. В примере используется `assets/app-icons`, а исходные SVG, включая используемый ниже `check.svg`, находятся в `assets/svg-icons`. Создайте конфиг `assets/app-icons/svg-sprite.config.json`: @@ -66,7 +66,13 @@ export function SaveIcon() { Свойство `icon` принимает имена исходных SVG без расширения. Монохромная иконка наследует `color`, а цвета многоцветной переопределяются через `--icon-color-N`. -Компонент использует CSS Modules. Если проект ещё не обрабатывает их с default export, добавьте правило в `webpack.config.js`: +Компонент использует CSS Modules. Если проект ещё не обрабатывает их, установите loaders: + +```bash +npm install --save-dev style-loader css-loader +``` + +Затем добавьте правило с default export в `webpack.config.js`: ```js { diff --git a/docs/ru/guides/standalone-vite.md b/docs/ru/guides/standalone-vite.md index 379db66..ed01987 100644 --- a/docs/ru/guides/standalone-vite.md +++ b/docs/ru/guides/standalone-vite.md @@ -4,7 +4,7 @@ ## Генерация спрайта -Выберите папку для спрайта. В примере используется `assets/app-icons`, а исходные SVG находятся в `assets/svg-icons`. +Выберите папку для спрайта. В примере используется `assets/app-icons`, а исходные SVG, включая используемый ниже `check.svg`, находятся в `assets/svg-icons`. Создайте конфиг `assets/app-icons/svg-sprite.config.json`: diff --git a/docs/ru/guides/standalone-webpack.md b/docs/ru/guides/standalone-webpack.md index bc3bb31..ca13ba4 100644 --- a/docs/ru/guides/standalone-webpack.md +++ b/docs/ru/guides/standalone-webpack.md @@ -4,7 +4,7 @@ ## Генерация спрайта -Выберите папку для спрайта. В примере используется `assets/app-icons`, а исходные SVG находятся в `assets/svg-icons`. +Выберите папку для спрайта. В примере используется `assets/app-icons`, а исходные SVG, включая используемый ниже `check.svg`, находятся в `assets/svg-icons`. Создайте конфиг `assets/app-icons/svg-sprite.config.json`: diff --git a/skills/README.md b/skills/README.md index f963c3c..4f91d79 100644 --- a/skills/README.md +++ b/skills/README.md @@ -2,27 +2,25 @@ Исходники обязательного контекста английского и русского skills находятся в `skills/svg-sprites/src/{en,ru}/`. Готовые переносимые артефакты генерируются в `skills/artifacts/`, игнорируются Git и упаковываются в ZIP во время release workflow. -Русский skill хранит весь обязательный контекст в одном файле: +Обе языковые версии имеют симметричную single-file структуру: ```text -src/ru/ +src/{en,ru}/ ├── SKILL.md └── references/ └── complex-svg.md ``` -`src/ru/SKILL.md` содержит знания о пакете и рабочий процесс агента. Exact-mode настройка берётся из canonical guides, а не дублируется отдельными source-фрагментами. +Каждый `SKILL.md` содержит обязательные знания о пакете, рабочий процесс агента и operational map canonical-документации. Exact-mode настройка берётся из canonical guides, а не дублируется отдельными source-фрагментами. Agent-specific `complex-svg.md` остаётся отдельным reference. -Русский artifact дополнительно получает без изменений `README_RU.md` и содержательную пользовательскую документацию из `docs/ru/`. Локальный редакторский `guides/AGENTS.md`, а также навигационные `guides/README.md` и `reference/README.md` не копируются. Файлы находятся в `references/README_RU.md` и `references/docs/ru/`. Agent-specific `complex-svg.md` остаётся отдельным reference. - -Английский source пока сохраняет составную структуру с `core/`, а artifact — английские exact-mode guides и локальные `programmatic-api.md`/`complex-svg.md`. Его перевод на единый `SKILL.md` и полную canonical-документацию выполняется отдельно. +Английский artifact дополнительно получает без изменений `README.md` и содержательную пользовательскую документацию из `docs/en/`; русский — `README_RU.md` и `docs/ru/`. Локальный редакторский `guides/AGENTS.md`, а также навигационные `guides/README.md` и `reference/README.md` не копируются. Canonical-файлы находятся в `references/README.md` и `references/docs/en/` либо в `references/README_RU.md` и `references/docs/ru/`. ## Композиция Markdown -Сборщик сохраняет поддержку Markdown includes для английского skill и будущих документов: +Сборщик сохраняет поддержку Markdown includes для будущих документов: ```md - + ``` Include раскрываются рекурсивно, путь считается относительно включающего файла. Циклы, отсутствующие файлы, выход за `skills/svg-sprites/`, frontmatter во фрагментах и нераскрытые include завершают сборку ошибкой. Заголовки не сдвигаются автоматически: entry содержит единственный `# H1`, inline-фрагменты начинаются с `##`. diff --git a/skills/svg-sprites/skill.config.mjs b/skills/svg-sprites/skill.config.mjs index c48ee2e..d3bc0dd 100644 --- a/skills/svg-sprites/skill.config.mjs +++ b/skills/svg-sprites/skill.config.mjs @@ -1,6 +1,5 @@ const agentReferences = { en: [ - 'programmatic-api.md', 'complex-svg.md', ], ru: [ @@ -8,18 +7,6 @@ const agentReferences = { ], } -const guideFiles = [ - 'standalone.md', - 'standalone-vite.md', - 'standalone-webpack.md', - 'react-vite.md', - 'react-webpack.md', - 'next-app-turbopack.md', - 'next-app-webpack.md', - 'next-pages-turbopack.md', - 'next-pages-webpack.md', -] - function documents(language) { return [ { entry: `src/${language}/SKILL.md`, to: 'SKILL.md', skill: true }, @@ -30,12 +17,19 @@ function documents(language) { ] } -function guides(language) { - return guideFiles.map((file) => ({ - from: `../../docs/${language}/guides/${file}`, - to: `references/guides/${file}`, - })) -} +const englishDocumentation = [ + { from: '../../README.md', to: 'references/README.md' }, + { + fromDirectory: '../../docs/en', + toDirectory: 'references/docs/en', + extensions: ['.md'], + exclude: [ + 'guides/AGENTS.md', + 'guides/README.md', + 'reference/README.md', + ], + }, +] const russianDocumentation = [ { from: '../../README_RU.md', to: 'references/README_RU.md' }, @@ -54,11 +48,11 @@ const russianDocumentation = [ export default [ { name: 'svg-sprites', - description: 'Use only when configuring, generating, or troubleshooting @gromlab/svg-sprites. Triggers: @gromlab/svg-sprites, svg-sprite.config.ts, defineSpriteConfig, generateSprite, standalone, standalone@vite, standalone@webpack, react@vite, react@webpack, next@app, next@pages, SpriteConfig.input, --input, SpriteViewer, or --icon-color-N. Do NOT use for custom SVG sprites, favicons, raster images, icon fonts, choosing an icon set, or inline SVG without this package.', + description: 'Use only when configuring, generating, or troubleshooting @gromlab/svg-sprites. Triggers: @gromlab/svg-sprites, svg-sprite.config.json, svg-sprite.config.ts, defineSpriteConfig, generateSprite, standalone, standalone@vite, standalone@webpack, react@vite, react@webpack, next@app, next@pages, SpriteConfig.input, --input, SpriteViewer, or --icon-color-N. Do NOT use for custom SVG sprites, favicons, raster images, icon fonts, choosing an icon set, or inline SVG without this package.', output: '../artifacts/svg-sprites', maxSkillBytes: 48_000, documents: documents('en'), - copy: guides('en'), + copy: englishDocumentation, }, { name: 'svg-sprites-ru', diff --git a/skills/svg-sprites/src/en/SKILL.md b/skills/svg-sprites/src/en/SKILL.md index ed0909b..2b83029 100644 --- a/skills/svg-sprites/src/en/SKILL.md +++ b/skills/svg-sprites/src/en/SKILL.md @@ -1,19 +1,282 @@ # @gromlab/svg-sprites - - - - - - - - +## What the package does -## References to open as needed +`@gromlab/svg-sprites` is a CLI generator that builds SVG sprites from user-provided SVG files. The package does not include its own icon set: it compiles project SVGs into an external sprite asset, creates a native typed Web Component for standalone bundler modes, and creates a React component for React/Next.js. -- For static publishing, open [bare standalone](./references/guides/standalone.md). For vanilla bundler apps, open [standalone + Vite](./references/guides/standalone-vite.md) or [standalone + Webpack](./references/guides/standalone-webpack.md). -- For React, open the exact [Vite](./references/guides/react-vite.md) or [Webpack](./references/guides/react-webpack.md) guide. -- For the Next.js App Router, open the exact [Turbopack](./references/guides/next-app-turbopack.md) or [Webpack](./references/guides/next-app-webpack.md) guide. -- For the Next.js Pages Router, open the exact [Turbopack](./references/guides/next-pages-turbopack.md) or [Webpack](./references/guides/next-pages-webpack.md) guide. -- To invoke the generator from Node.js, open the [programmatic API](./references/programmatic-api.md). -- For gradients, filters, `url(#...)`, unusual colors, and `viewBox` issues, open [complex SVGs](./references/complex-svg.md). +The package supports multiple independent sprites in one project. Each explicitly selected config file or config-less directory describes one sprite and gets its own: + +- SVG asset; +- mode-specific manifest data; +- icon name types and production entry `.svg-sprite/index.js` for bundler modes; +- a native Web Component with an explicit registration function for `standalone@vite`/`standalone@webpack`; +- a React component only for React/Next.js; +- a deployment-neutral JSON manifest without a public URL for bare `standalone`. + +The project determines how many sprite directories exist and where they live. For example, `name: 'file-manager'` produces `FileManagerIcon`, `FileManagerIconName`, and `fileManagerIconNames`, while another directory with `name: 'navigation'` produces a separate `NavigationIcon`. These are examples of per-sprite APIs, not fixed package exports. + +Generated production runtime and declarations do not import `@gromlab/svg-sprites`. Generation through `npx --yes @gromlab/svg-sprites ` does not add the package to the project. Install it as a development dependency only for the Viewer, package-provided config types, or the programmatic API. + +## Selecting a mode + +Select exactly one supported mode key: + +| Project | Mode key | +|---|---| +| 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` | + +Mode may come from the config, CLI, or programmatic API. Values are applied as `defaults → config → CLI/API overrides`. A mode must exist after merging. + +`name` is optional. When omitted, the generator converts the sprite-module directory name to kebab-case; directories named `svg-sprite` and `svg-sprites` use their parent directory's name. An explicit `name` must already be kebab-case and begin with an ASCII letter. + +The CLI accepts exactly one path. A `.ts`, `.js`, or `.json` file loads that exact config regardless of its name. A directory enables config-less generation with settings supplied through CLI flags. + +```json +{ + "scripts": { + "sprite:": "npx --yes @gromlab/svg-sprites ", + "sprite::cli": "npx --yes @gromlab/svg-sprites --mode " + } +} +``` + +Generation through `npx` does not add the package to the project. Do not use incomplete `react`, `next@app`, `next@pages`, or `standalone@` keys, or the removed `legacy` mode. Use bare `standalone` only when the application publishes the SVG itself; use the complete Vite/Webpack key otherwise. Create one command per config file or directory when the project has multiple sprites. + +## Inspecting the project + +Establish the project's actual contract before making changes: + +1. Read the root `package.json`, lockfile, and workspace configuration; identify the framework, bundler, and existing commands. +2. Find config files, commands containing `svg-sprites`, and imports of generated components. Config names are arbitrary; use the explicit CLI path and object fields. +3. For React, determine whether the project uses Vite or Webpack 5 from its scripts and configuration. For Next.js, separately determine the App/Pages Router and the bundler used by the actual `dev`/`build` commands. +4. Check existing `predev`, `prebuild`, `pretypecheck`, and orchestration scripts. Do not overwrite them. +5. For a new sprite, choose a target directory without imposing a particular application layer or architecture. +6. Check TypeScript and alias settings. Package subpath exports require TypeScript 5+ with `moduleResolution: 'bundler'`, `'node16'`, or `'nodenext'`. + +All input paths are relative to the directory containing the explicitly selected config file; in config-less mode they are relative to the supplied directory. Inspect `input` using this single contract: + +- `input?: string | string[]` defaults to `./icons`; +- each string is a folder, an exact SVG file, or a glob; +- a folder is scanned shallowly; nested files are included only by an explicit recursive glob such as `./icons/**/*.svg`; +- an array combines positive sources, while an item prefixed with `!` excludes its matches from the combined set; +- every positive source must resolve to at least one SVG, so a missing or empty folder, an unmatched glob, a missing file, or a non-SVG exact file is an error; +- resolved files are deduplicated and sorted deterministically; +- different files with the same basename are a conflict, even when they came from different sources. + +Do not copy a shared SVG into several folders: add its exact path or a suitable glob to `input` in every sprite that needs it. Use `**/*.svg` only when recursive inclusion is intentional. + +## Setting up the integration + +Do not reproduce mode setup from memory. After inspecting the project, select one exact mode and open the corresponding file under `references/docs/en/guides/`. Treat that guide as the base operational contract, then adapt it to the project's existing structure. + +Work in this order: + +1. Identify the source SVG directory and the directory for one sprite module. One config creates one independent sprite; multiple sets require separate config files and unique `name` values. +2. Confirm the framework, router, and bundler against the exact mode. For Next.js, inspect the actual `dev` and `build` scripts, not just the presence of `next.config.*`. +3. Prefer a JSON config when the project does not need package-provided config types. A TypeScript config also loads through the CLI, but the package must be installed when the config imports `defineSpriteConfig` or package types. +4. Resolve every `input` from the config-file directory. Do not reorganize SVGs unnecessarily: use a folder path, exact file, glob, or array of these sources. +5. Add a sprite command with an explicit config path. Preserve existing `dev`, `build`, `typecheck`, and lifecycle hooks; place generation before the first process that imports `.svg-sprite`. +6. Do not run one generation twice through both a concurrent `predev` and `npm run sprites && ...`. For multiple sprites, create separate commands and one aggregate script. +7. If the application imports the sprite-module directory, create a user-owned `index.ts` next to `.svg-sprite`; do not place user files inside the generated directory. +8. Run the first generation before typecheck or application startup, then inspect the mode-specific output and the actual component import. + +Do not add the Viewer automatically. Connect it only when requested or when visual verification of the set, colors, or complex SVGs is needed. Get the production isolation pattern from the exact guide: Vite, Webpack, App Router, and Pages Router use different boundaries. + +Do not copy snippets between exact modes even when their APIs look similar. Asset URLs, generated files, CSS handling, router boundaries, and debug-tool setup differ. + +## Generated directory contract + +After generation, a React/Next.js directory has this structure: + +```text +svg-sprite/ +├── icons/ # user-owned sources +├── svg-sprite.config.json # recommended config name +├── index.ts # optional user-owned barrel +├── .gitignore # managed by the generator +└── .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 +``` + +Standalone modes do not create `react/`. Bare `standalone` generates `sprite.svg` and `svg-sprite.manifest.json`; `standalone@vite`/`standalone@webpack` additionally generate `index.*`, `icon-data.*`, and a resolved manifest. Their `index.*` also contains a native generated Web Component; bare `standalone` gets no JavaScript runtime and does not create `.gitignore`. + +Edit the source SVGs, selected config, and user-owned `index.ts`. Do not manually change anything in `.svg-sprite`: the next generation will overwrite it. In every mode except bare `standalone`, the generated `.gitignore` is also managed by the generator. To import from the sprite-module root, create a barrel: + +```ts +export * from './.svg-sprite/index.js' +``` + +The generator owns the complete `.svg-sprite` directory and replaces it on every run. Never put user files inside it. The generator also owns `.gitignore` when the selected mode creates it. Bare `standalone` preserves a user-owned `.gitignore`, but removes a managed `.gitignore` left by another mode. Generated paths must not contain symlinks. + +In React/Next modes, the internal `index.js` exports the component from `react/react-component.js` and the readonly name array; `index.d.ts` adds props/style types and the icon-name union. Standalone bundler modes export Web Component helpers and types without `react/`; bare `standalone` does not create a facade. Bundler-mode manifest declarations define their types locally and do not import the generator package. The manifest contains mode, target, icon list, and icon metadata for debug tools; bundler manifests also contain a URL and are not imported by the production component. + +In bundler modes, the sprite remains a separate asset and SVG path data is not embedded in JavaScript. The content hash depends on bundler settings. Bare `standalone` creates a fixed filename, and the application owns its public name and versioning: + +- `react@vite` generates a static `sprite.svg?no-inline` import, preventing Vite from inlining it; +- `standalone@vite` uses the same Vite asset mechanism and exports an href helper plus a native Web Component without React; +- `standalone@webpack` uses Webpack Asset Modules and exports the same mode-local Web Component without React; +- React Webpack 5 and all Next modes obtain the asset through `new URL(..., import.meta.url).href`, which must be processed by the selected bundler; +- a custom Webpack SVG loader must not intercept the generated `sprite.svg`; +- in Next mode, the generated component does not contain `'use client'` and works in Server Components, SSR, and SSG; do not add a client boundary solely for an icon; +- the Next build command and mode key must agree: Turbopack with `.../turbopack`, Webpack with `.../webpack`. + +For bundler modes, do not move the generated sprite into `public` or rewrite its URL manually. For bare `standalone`, do not move the managed original: the application may explicitly copy it into deploy output and owns the public URL and stale-copy cleanup. Regenerate with the new complete key when changing mode. + +## Usage, accessibility, and colors + +The component name depends on the specific sprite's `name`. In `standalone@vite` and `standalone@webpack`, `name: 'file-manager'` creates the `` tag and the `defineFileManagerIconElement()` function: + +```ts +import { defineFileManagerIconElement } from './svg-sprite' + +defineFileManagerIconElement() +``` + +```html + +``` + +The native element has no runtime dependencies, selects the generated ID and `viewBox`, obtains the URL through the bundler, and renders `` in Shadow DOM. Its `icon` property is typed with the exact name union, while plain HTML attribute values are validated only at runtime. It defaults to `1em × 1em`; resize the host with CSS. Bare `standalone` does not generate a Web Component. + +In React/Next.js, the same `name: 'file-manager'` creates the `FileManagerIcon` React component. For `name: 'navigation'`, use the generated `NavigationIcon`. + +Import the component from the root of its sprite directory. `width` and `height` are optional: ordinary CSS classes can control the size. + +```tsx +import { FileManagerIcon } from './svg-sprite' + +export const OpenButton = () => ( + Open + +) +``` + +```css +.icon { + width: 24px; + height: 24px; + color: #4b5563; +} +``` + +`icon` accepts exact source filenames without `.svg`; an unknown name is a TypeScript error. For names that are not safe SVG IDs, the generator preserves the public name but creates an internal stable hash ID, so do not construct a fragment URL from the name manually. + +By default, the component renders `` and accepts standard SVG attributes: optional `width`/`height`, `className`, `style`, `role`, `aria-*`, and event handlers. With `wrapped={true}`, the root becomes a ``, props apply to the span, and the inner SVG fills the wrapper. + +The generated component does not decide semantics for the application and does not add a `title`. For a decorative icon, pass `aria-hidden="true"`; for a standalone meaningful icon, pass `role="img"` and an accessible name through `aria-label`. Do not duplicate the name when adjacent text already announces the action. Put interactivity on a `button` or `a`, not on the icon itself. + +The `removeSize`, `replaceColors`, and `addTransition` transforms are enabled by default. A monochrome icon's only color gets a `currentColor` fallback, so control it with the CSS `color` property. For a multicolor icon, pass typed custom properties: + +```tsx + +``` + +Automatic replacement targets `fill`/`stroke` attributes and inline `style`. The values `none`, `transparent`, `inherit`, `unset`, and `initial` are not replaced. Check CSS classes and external stylesheets, gradients, patterns, filters, and `url(#...)` against the actual output. Page variables work through ``, but do not cross into an external document loaded through `` or `background-image`; a CSS mask preserves only a monochrome silhouette. + +`SpriteViewer` is optional. Install `@gromlab/svg-sprites` as a development dependency only when the project needs the Viewer. It accepts manifests or statically discoverable loaders and provides search, themes, colors, and examples, but production components do not depend on it. + +Open the exact guide before connecting the Viewer. Vite uses a separate HTML entry, plain Webpack uses a development-only entry, Next.js uses a debug route, and the App Router additionally requires a separate Client Component boundary. Do not transfer setup between modes. + +## Verifying the result + +After changing a config or SVG, perform these required checks: + +1. Run the exact sprite command. It must exit with code `0` and report the name, icon count, mode, and `.svg-sprite` directory. +2. Inspect the output for the selected exact mode: + - bare `standalone` creates `sprite.svg` and `svg-sprite.manifest.json`; + - `standalone@vite` and `standalone@webpack` additionally create `index.*`, `icon-data.*`, and a JS manifest, but no `react/` directory; + - React and Next.js modes also create `react/react-component.js`, its declaration, and its CSS Module. +3. For modes with a public facade, inspect `.svg-sprite/index.js`, the adjacent `index.d.ts`, the name list, and the actual import through the user-owned barrel. +4. Inspect the manifest: mode and target must match the selected adapter, and the icon list must match the source SVGs. In bundler modes the URL must use the mode-specific mechanism; the bare JSON manifest intentionally has no public `spriteUrl`. +5. Run the project's existing typecheck when the mode creates types or user-owned TypeScript changed. +6. Run the smallest application command affected by the change: `dev`, build, or a project-specific check. + +Do not run a full production build solely to verify a new icon name. It is required when the bundler target, router, Webpack loader, asset URL, or deployment path changed, or when diagnosing a production-only error. + +Perform visual, Network, and accessibility-tree checks only when a running application and browser tools are available. If those tools are unavailable, do not claim that colors, themes, accessibility, or the asset's HTTP response were verified; explicitly state what remains unchecked. + +Use the Viewer for complex colors, transforms, and broad visual checks. Do not add a debug route for routine generation of one sprite. + +## Diagnostics + +Match the symptom to the relevant check and fix the root cause: + +| Symptom | Likely cause | Action | +|---|---|---| +| `Missing sprite config file or module directory` | The positional path is missing | Pass one config file or a directory for config-less generation. | +| `Expected one config file or module directory` | Multiple paths were passed | Create one command per sprite and combine the scripts. | +| `Sprite mode is required` | Mode is absent from both config and CLI | Add `mode` to the object or pass the full `--mode`. | +| `Unsupported sprite config extension` | The supplied file is not `.ts`, `.js`, or `.json` | Use a supported config format. | +| A positive input source has no SVG matches | A folder is missing or empty, a glob matches nothing, or an exact path is missing or not an SVG | Resolve the source from the config directory and correct `input`; every positive item must produce at least one SVG. | +| Icons from a subdirectory are missing | A folder source was expected to scan recursively | Use an explicit glob such as `./icons/**/*.svg`; folders are shallow. | +| An excluded icon is still present | The exclusion lacks a leading `!`, is not in the `input` array, or is relative to the wrong directory | Add a matching `!` item and resolve it from the config directory. | +| CLI source selection is incomplete | Multiple sources were packed into one `--input` value or an option was omitted | Repeat `--input ` once per source or exclusion. | +| Icon name or SVG ID collision | Two different files have the same basename, or a hash ID collides with a name | Rename one source SVG; do not select a file implicitly. | +| `Refusing to overwrite a user file` | A user-owned `.gitignore` already exists at the sprite-module root where the mode must create one | Do not overwrite it: choose another sprite directory or coordinate moving the existing `.gitignore`. | +| Missing `.svg-sprite/index.js` or name absent from autocomplete | This is expected for bare `standalone`; in other modes generation did not run, the barrel is wrong, or the type server cached an old module | Confirm the exact mode, run the sprite command, check `export * from './.svg-sprite/index.js'`, then typecheck; restart the TypeScript server if necessary. | +| SVG does not load or the URL is wrong | Mode and bundler differ, Webpack `publicPath` is wrong, or a custom loader intercepted the asset | Align mode with the build command, check Asset Modules/`publicPath`, and exclude the generated SVG from the incompatible loader. | +| Next build differs between SSR and browser | The module targets another bundler/router, or the URL was rewritten manually | Restore the generated `new URL(...)`, select the exact Next mode, and regenerate. | +| `color` does not change a multicolor icon | The icon uses several variables or is rendered through ``/CSS background | Use ``/`` and the required `--icon-color-N` properties. | +| Gradient/filter renders incorrectly | Automatic color replacement cannot guarantee complex paint servers | Inspect the generated SVG; disable `replaceColors` for the sprite or simplify the source if necessary. | +| Viewer is empty | The manifest was not generated, the loader is not discoverable by the bundler, or the Client Component boundary is wrong | Generate the sprite first, then compare the manifest import and setup with the exact guide; in the App Router keep `'use client'` only in the Viewer component. | + +For an unknown error, record the complete CLI command, mode, config-file or directory path, and first stack/error message. Then reduce it to one sprite without deleting user files or a managed `.gitignore`. + +## Operational reference map + +References are included in the built skill. Open only the documents relevant to the current task, but always open the exact-mode guide before changing an integration. + +### Overview + +- [Package README](./references/README.md) covers capabilities, the primary React/Next.js scenario, and documentation links. + +### Configuration + +- [Configuration](./references/docs/en/configuration.md) covers JSON, JavaScript, and TypeScript configs, config fields, `input`, and CLI invocation. + +### Exact-mode guides + +- [`standalone`](./references/docs/en/guides/standalone.md) covers static HTML and custom SVG publishing. +- [`standalone@vite`](./references/docs/en/guides/standalone-vite.md) covers a vanilla Vite application and the Web Component. +- [`standalone@webpack`](./references/docs/en/guides/standalone-webpack.md) covers a vanilla Webpack 5 application and the Web Component. +- [`react@vite`](./references/docs/en/guides/react-vite.md) covers React with Vite. +- [`react@webpack`](./references/docs/en/guides/react-webpack.md) covers React with Webpack 5. +- [`next@app/turbopack`](./references/docs/en/guides/next-app-turbopack.md) covers the Next.js App Router with Turbopack. +- [`next@app/webpack`](./references/docs/en/guides/next-app-webpack.md) covers the Next.js App Router with Webpack. +- [`next@pages/turbopack`](./references/docs/en/guides/next-pages-turbopack.md) covers the Next.js Pages Router with Turbopack. +- [`next@pages/webpack`](./references/docs/en/guides/next-pages-webpack.md) covers the Next.js Pages Router with Webpack. + +### Technical references + +- [Technical reference](./references/docs/en/reference/technical.md) covers requirements, CLI, unified configuration, naming, generated APIs, assets, transforms, colors, Viewer, Git, CI, and troubleshooting. +- [Programmatic API](./references/docs/en/reference/programmatic-api.md) covers `generateSprite`, overrides, config APIs, low-level compilation, and Viewer runtime. + +### Agent-specific reference + +- [Complex SVGs](./references/complex-svg.md) covers gradients, patterns, filters, masks, `url(#...)`, `viewBox`, fragment IDs, and visual diagnostics. diff --git a/skills/svg-sprites/src/en/core/00-package-overview.md b/skills/svg-sprites/src/en/core/00-package-overview.md deleted file mode 100644 index c4ebb9d..0000000 --- a/skills/svg-sprites/src/en/core/00-package-overview.md +++ /dev/null @@ -1,16 +0,0 @@ -## What the package does - -`@gromlab/svg-sprites` is a CLI generator that builds SVG sprites from user-provided SVG files. The package does not include its own icon set: it compiles the project's SVGs into an external sprite asset, creates a native typed Web Component for standalone bundler modes, and creates a React component for React/Next.js. - -The package supports multiple independent sprites in one project. Each explicitly selected config file or config-less directory describes one sprite and gets its own: - -- SVG asset; -- mode-specific manifest data; -- icon name types and `.svg-sprite/index.js` for bundler modes; -- a native Web Component with an explicit registration function for `standalone@vite`/`standalone@webpack`; -- a React component only for React/Next.js; -- a deployment-neutral JSON manifest without a public URL for bare `standalone`. - -The project determines how many sprite directories exist and where they live. For example, `name: 'file-manager'` produces `FileManagerIcon`, while another directory with `name: 'navigation'` produces a separate `NavigationIcon`. The names `FileManagerIcon` and `fileManagerIconNames` used below are examples of the API for one possible sprite, not fixed package exports. - -Generated production runtime and declarations do not import `@gromlab/svg-sprites`. Generation can run through a pinned `npx --package` command without adding the package to the project. Install it as a development dependency only for the Viewer, package-provided config types, or the programmatic API. diff --git a/skills/svg-sprites/src/en/core/10-mode-selection.md b/skills/svg-sprites/src/en/core/10-mode-selection.md deleted file mode 100644 index 206fd8c..0000000 --- a/skills/svg-sprites/src/en/core/10-mode-selection.md +++ /dev/null @@ -1,30 +0,0 @@ -## Selecting a mode - -Select exactly one supported mode key: - -| Project | Mode key | -|---|---| -| 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` | - -Mode may come from the config, CLI, or programmatic API. Values are applied as `defaults → config → CLI/API overrides`. A mode must exist after merging. - -The CLI accepts exactly one path. A `.ts`, `.js`, or `.json` file loads that exact config regardless of its name. A directory enables config-less generation with settings supplied through CLI flags. - -```json -{ - "scripts": { - "sprite:": "npx --yes --package=@gromlab/svg-sprites@latest svg-sprites ", - "sprite::cli": "npx --yes --package=@gromlab/svg-sprites@latest svg-sprites --mode " - } -} -``` - -Generation through `npx` does not add the package to the project. Pin an exact package version instead of `latest` in CI. Do not use incomplete `react`, `next@app`, `next@pages`, or `standalone@` keys, or the removed `legacy` mode. Use bare `standalone` only when the application publishes the SVG itself; use the complete Vite/Webpack key otherwise. Create one command per config file or directory when the project has multiple sprites. diff --git a/skills/svg-sprites/src/en/core/20-project-inspection.md b/skills/svg-sprites/src/en/core/20-project-inspection.md deleted file mode 100644 index 800f700..0000000 --- a/skills/svg-sprites/src/en/core/20-project-inspection.md +++ /dev/null @@ -1,22 +0,0 @@ -## Inspecting the project - -Establish the project's actual contract before making changes: - -1. Read the root `package.json`, lockfile, and workspace configuration; identify the framework, bundler, and existing commands. -2. Find config files, commands containing `svg-sprites`, and imports of generated components. Config names are arbitrary; use the explicit CLI path and object fields. -3. For React, determine whether the project uses Vite or Webpack 5 from its scripts and configuration. For Next.js, separately determine the App/Pages Router and the bundler used by the actual `dev`/`build` commands. -4. Check existing `predev`, `prebuild`, `pretypecheck`, and orchestration scripts. Do not overwrite them. -5. For a new sprite, choose a target directory without imposing a particular application layer or architecture. -6. Check TypeScript and alias settings. Package subpath exports require TypeScript 5+ with `moduleResolution: 'bundler'`, `'node16'`, or `'nodenext'`. - -All input paths are relative to the directory containing the explicitly selected config file; in config-less mode they are relative to the supplied directory. Inspect `input` using this single contract: - -- `input?: string | string[]` defaults to `./icons`; -- each string is a folder, an exact SVG file, or a glob; -- a folder is scanned shallowly; nested files are included only by an explicit recursive glob such as `./icons/**/*.svg`; -- an array combines positive sources, while an item prefixed with `!` excludes its matches from the combined set; -- every positive source must resolve to at least one SVG, so a missing or empty folder, an unmatched glob, a missing file, or a non-SVG exact file is an error; -- resolved files are deduplicated and sorted deterministically; -- different files with the same basename are a conflict, even when they came from different sources. - -Do not copy a shared SVG into several folders: add its exact path or a suitable glob to `input` in every sprite that needs it. Use `**/*.svg` only when recursive inclusion is intentional. diff --git a/skills/svg-sprites/src/en/core/30-react-next-setup.md b/skills/svg-sprites/src/en/core/30-react-next-setup.md deleted file mode 100644 index 4a2c363..0000000 --- a/skills/svg-sprites/src/en/core/30-react-next-setup.md +++ /dev/null @@ -1,63 +0,0 @@ -## Setting up React or Next.js - -Choose a target directory for one sprite. It may live next to a feature, in a shared icons directory, or anywhere else that follows the project's conventions. The following structure is only an example: - -```text -src/ui/file-manager/svg-sprite/ -├── icons/ -│ ├── check.svg -│ └── folder.svg -└── svg-sprite.config.ts -``` - -One `svg-sprite.config.ts` creates one independent sprite. For multiple sets, choose multiple directories and assign each a unique `name`. - -The generator does not need to be installed in the project. Start with a plain -config that has no package import: - -```ts -export default { - mode: 'react@vite', - name: 'file-manager', - description: 'File manager icons', - input: ['./icons', '../../shared/icons/close.svg'], -} -``` - -`input` accepts one folder, exact SVG file, or glob, or an array that combines them. Prefix an array item with `!` to exclude matches. Folders are shallow; use an explicit `**/*.svg` glob for recursion. Omit `input` to use `./icons`. Every path is resolved from the config directory, and every positive source must match at least one SVG. - -The object contract is the same for React and Next.js; only the full `mode` differs. Install the package only for the optional Viewer, programmatic API, or package-provided config typing. Exact guides also provide a local copy-paste config type for projects that remain package-free. - -`name` must begin with an ASCII letter and use kebab-case. The example `file-manager` produces `FileManagerIcon`, `FileManagerIconName`, and `fileManagerIconNames`. Another sprite gets its own names. If `name` is omitted, the generator derives it from the directory. - -Add a separate command with the selected mode key and one path: - -```json -{ - "scripts": { - "sprite:file-manager": "npx --yes --package=@gromlab/svg-sprites@latest svg-sprites src/ui/file-manager/svg-sprite/svg-sprite.config.ts", - "sprites": "npm run sprite:file-manager" - } -} -``` - -For Next.js, set the full key in the config, for example `next@app/turbopack`. For multiple sprites, add one `sprite:` command per config file and invoke them sequentially from `sprites`. - -To select sources from the CLI instead, repeat `--input `; the values form the same array contract, including `!` exclusions: - -```bash -npx --yes --package=@gromlab/svg-sprites@latest svg-sprites src/ui/file-manager/svg-sprite/svg-sprite.config.ts \ - --input ./icons \ - --input '../../shared/icons/**/*.svg' \ - --input '!../../shared/icons/legacy-*.svg' -``` - -Generated files in `.svg-sprite` are excluded from Git by default, so run `sprites` before any process that needs the component, types, or asset. If the project imports the sprite-module root, create a user-owned `index.ts` with `export * from './.svg-sprite'`. Generated declarations are self-contained and do not import the generator package. - -Run generation either from `predev`/`prebuild`/`pretypecheck` hooks or explicitly inside the corresponding commands. Do not use both forms for the same command, or generation runs twice. Preserve existing script commands and never create a duplicate JSON key. - -Run the first generation manually: - -```bash -npm run sprites -``` diff --git a/skills/svg-sprites/src/en/core/40-generated-contract.md b/skills/svg-sprites/src/en/core/40-generated-contract.md deleted file mode 100644 index 136c737..0000000 --- a/skills/svg-sprites/src/en/core/40-generated-contract.md +++ /dev/null @@ -1,51 +0,0 @@ -## Generated directory contract - -After generation, a React/Next directory has this structure: - -```text -svg-sprite/ -├── icons/ # user-owned sources -├── svg-sprite.config.ts # recommended config name -├── index.ts # optional user-owned barrel -├── .gitignore # managed by the generator -└── .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 -``` - -Standalone does not create `react/`. Bare `standalone` generates `sprite.svg` and -`svg-sprite.manifest.json`; `standalone@vite`/`standalone@webpack` additionally -generate `index.*`, `icon-data.*`, and a resolved manifest. Their `index.*` also -contains a native generated Web Component; bare `standalone` gets no JavaScript runtime -and does not create or modify `.gitignore`. - -Edit the source SVGs, selected config, and user-owned `index.ts`. Do not manually change anything in `.svg-sprite`: the next generation will overwrite it. In modes other than bare `standalone`, the generated `.gitignore` is also managed and must not be edited manually. To import from the sprite-module root, create a barrel: - -```ts -export * from './.svg-sprite' -``` - -The generator owns the complete `.svg-sprite` directory and replaces it on every run. Never put user files inside it. The generator also owns `.gitignore` when the selected mode creates it; bare `standalone` leaves an existing `.gitignore` untouched. Generated paths must not contain symlinks. - -The internal `index.js` exports the component from `react/react-component.js` and the readonly name array; the adjacent `index.d.ts` adds props/style types and the icon-name union. Bundler-mode manifest declarations define their types locally and do not import the generator package. The manifest contains the mode, URL, target, icon list, and icon metadata for debug tools and is not imported by the production component. - -The sprite remains a separate content-hashed asset; SVG path data is not embedded in JavaScript: - -- `react@vite` generates a static `sprite.svg?no-inline` import, preventing Vite from inlining it; -- `standalone@vite` uses the same Vite asset mechanism and exports an href helper plus a native Web Component without React; -- `standalone@webpack` uses Webpack Asset Modules and exports the same mode-local Web Component without React; -- React Webpack 5 and all Next modes generate `new URL('./sprite.svg', import.meta.url).href`, which must be processed by the selected bundler's Asset Modules; -- a custom Webpack SVG loader must not intercept the generated `sprite.svg`; -- in Next mode, the generated component does not contain `'use client'` and works in Server Components, SSR, and SSG; do not add a client boundary solely for an icon; -- the Next build command and mode key must agree: Turbopack with `.../turbopack`, Webpack with `.../webpack`. - -For bundler modes, do not move the generated sprite into `public` or rewrite its URL manually. For bare `standalone`, do not move the managed original: the application may explicitly copy it into deploy output and owns the public URL and stale-copy cleanup. Regenerate with the new complete key when changing mode. diff --git a/skills/svg-sprites/src/en/core/50-usage-and-colors.md b/skills/svg-sprites/src/en/core/50-usage-and-colors.md deleted file mode 100644 index 72acb83..0000000 --- a/skills/svg-sprites/src/en/core/50-usage-and-colors.md +++ /dev/null @@ -1,87 +0,0 @@ -## Usage, accessibility, and colors - -The component name depends on the specific sprite's `name`. In `standalone@vite` and `standalone@webpack`, `name: 'file-manager'` creates the `` tag and the `defineFileManagerIconElement()` function: - -```ts -import { defineFileManagerIconElement } from './svg-sprite' - -defineFileManagerIconElement() -``` - -```html - -``` - -The native element has no runtime dependencies, selects the generated ID and `viewBox`, obtains the URL through the bundler, and renders `` in Shadow DOM. Its `icon` property is typed with the exact name union, while plain HTML attribute values are validated only at runtime. It defaults to `1em × 1em`; resize the host with CSS. Bare `standalone` does not generate a Web Component. - -In React/Next.js, the same `name: 'file-manager'` creates the `FileManagerIcon` React component. For `name: 'navigation'`, use the generated `NavigationIcon`. - -Import the component from the root of its sprite directory. `width` and `height` are optional: ordinary CSS classes can control the size. - -```tsx -import { FileManagerIcon } from './svg-sprite' - -export const OpenButton = () => ( - Open - -) -``` - -```css -.icon { - width: 24px; - height: 24px; - color: #4b5563; -} -``` - -`icon` accepts exact source filenames without `.svg`; an unknown name is a TypeScript error. For names that are not safe SVG IDs, the generator preserves the public name but creates an internal stable hash ID, so do not construct a fragment URL from the name manually. - -By default, the component renders `` and accepts standard SVG attributes: optional `width`/`height`, `className`, `style`, `role`, `aria-*`, and event handlers. With `wrapped={true}`, the root becomes a ``, props apply to the span, and the inner SVG fills the wrapper. This is convenient when a class controls both size and colors: - -```tsx -