diff --git a/README.md b/README.md index 8242cc9..5461b0e 100644 --- a/README.md +++ b/README.md @@ -1,77 +1,80 @@ # @gromlab/svg-sprites +πŸ‡¬πŸ‡§ English | [πŸ‡·πŸ‡Ί Русский](README_RU.md) + ![npm](https://img.shields.io/npm/v/@gromlab/svg-sprites) ![license](https://img.shields.io/npm/l/@gromlab/svg-sprites) -CLI для Π³Π΅Π½Π΅Ρ€Π°Ρ†ΠΈΠΈ SVG-спрайтов ΠΈ Ρ‚ΠΈΠΏΠΈΠ·ΠΈΡ€ΠΎΠ²Π°Π½Π½Ρ‹Ρ… ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚ΠΎΠ² ΠΈΠΊΠΎΠ½ΠΎΠΊ для React ΠΈ Next.js. +A CLI for generating SVG sprites and typed icon components for React and Next.js. ![Preview](https://gromlab.ru/gromov/svg-sprites/media/branch/master/preview-image.png) -## Навигация +## Navigation -- [ВозмоТности](#возмоТности) -- [Π’Π°Π±Π»ΠΈΡ†Π° ΠΏΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΊΠΈ](#Ρ‚Π°Π±Π»ΠΈΡ†Π°-ΠΏΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΊΠΈ) -- [ВрСбования](#трСбования) -- [Быстрый старт](#быстрый-старт) - - [React + Vite](docs/ru/react-vite.md) - - [React + Webpack 5](docs/ru/react-webpack.md) - - [Next.js App Router](docs/ru/next-app.md) - - [Next.js Pages Router](docs/ru/next-pages.md) -- [ΠšΠΎΠ½Ρ„ΠΈΠ³ΡƒΡ€Π°Ρ†ΠΈΡ](#конфигурация) +- [Features](#features) +- [Support matrix](#support-matrix) +- [Requirements](#requirements) +- [Quick start](#quick-start) + - [React + Vite](docs/en/react-vite.md) + - [React + Webpack 5](docs/en/react-webpack.md) + - [Next.js App Router](docs/en/next-app.md) + - [Next.js Pages Router](docs/en/next-pages.md) +- [Configuration](#configuration) - [React](#react) - [Next.js](#nextjs) -- [ΠœΠ½ΠΎΠΆΠ΅ΡΡ‚Π²Π΅Π½Π½Ρ‹Π΅ спрайты](#мноТСствСнныС-спрайты) +- [Multiple sprites](#multiple-sprites) - [TypeScript](#typescript) -- [Π€ΠΎΡ€ΠΌΠ°Ρ‚Ρ‹ спрайтов](#Ρ„ΠΎΡ€ΠΌΠ°Ρ‚Ρ‹-спрайтов) -- [Бпособы отобраТСния](#способы-отобраТСния) -- [Врансформации](#трансформации) -- [Π£ΠΏΡ€Π°Π²Π»Π΅Π½ΠΈΠ΅ Ρ†Π²Π΅Ρ‚ΠΎΠΌ ΠΈΠΊΠΎΠ½ΠΎΠΊ](#ΡƒΠΏΡ€Π°Π²Π»Π΅Π½ΠΈΠ΅-Ρ†Π²Π΅Ρ‚ΠΎΠΌ-ΠΈΠΊΠΎΠ½ΠΎΠΊ) -- [ΠšΠ΅ΡˆΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠ΅](#ΠΊΠ΅ΡˆΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠ΅) +- [Sprite formats](#sprite-formats) +- [Rendering methods](#rendering-methods) +- [Transformations](#transformations) +- [Icon color management](#icon-color-management) +- [Caching](#caching) - [SpriteViewer](#spriteviewer) -- [ΠœΠΈΠ³Ρ€Π°Ρ†ΠΈΡ с 0.1.x](docs/ru/migration-1.md) -- [ДокумСнтация](#докумСнтация) +- [Migrating from 0.1.x](docs/en/migration-1.md) +- [Documentation](#documentation) -## ВозмоТности +## Features -- **TypeScript-friendly** β€” Ρ‚ΠΈΠΏΠΈΠ·ΠΈΡ€ΠΎΠ²Π°Π½Π½Ρ‹Π΅ React-ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Ρ‹, union-Ρ‚ΠΈΠΏΡ‹ ΠΈ runtime-списки доступных ΠΈΠΊΠΎΠ½ΠΎΠΊ. -- **Чистая гСнСрация** β€” generated-Ρ„Π°ΠΉΠ»Ρ‹ автоматичСски ΠΈΡΠΊΠ»ΡŽΡ‡Π°ΡŽΡ‚ΡΡ ΠΈΠ· Git, спрайт Π½Π΅ Π½ΡƒΠΆΠ½ΠΎ Π²Ρ€ΡƒΡ‡Π½ΡƒΡŽ Ρ€Π°Π·ΠΌΠ΅Ρ‰Π°Ρ‚ΡŒ Π² `public`, Π° Π³Π΅Π½Π΅Ρ€Π°Ρ‚ΠΎΡ€ обновляСт Ρ‚ΠΎΠ»ΡŒΠΊΠΎ ΠΏΡ€ΠΈΠ½Π°Π΄Π»Π΅ΠΆΠ°Ρ‰ΠΈΠ΅ Π΅ΠΌΡƒ Ρ„Π°ΠΉΠ»Ρ‹. -- **ΠžΠ±Ρ‰ΠΈΠ΅ ΠΈΠΊΠΎΠ½ΠΊΠΈ Π±Π΅Π· копирования** β€” SVG ΠΈΠ· локальной ΠΏΠ°ΠΏΠΊΠΈ ΠΈ `inputFiles` ΠΎΠ±ΡŠΠ΅Π΄ΠΈΠ½ΡΡŽΡ‚ΡΡ Π² ΠΎΠ΄ΠΈΠ½ спрайт; ΠΎΠ΄ΠΈΠ½ Ρ„Π°ΠΉΠ» ΠΌΠΎΠΆΠ½ΠΎ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ Π² Π½Π΅ΡΠΊΠΎΠ»ΡŒΠΊΠΈΡ… спрайтах. -- **ВстроСнноС ΠΈΠ½Ρ‚Π΅Ρ€Π°ΠΊΡ‚ΠΈΠ²Π½ΠΎΠ΅ ΠΏΡ€Π΅Π²ΡŒΡŽ** β€” `` ΠΏΠΎΠ΄ΠΊΠ»ΡŽΡ‡Π°Π΅Ρ‚ΡΡ ΠΊΠ°ΠΊ страница прилоТСния ΠΈ ΠΏΠΎΠΊΠ°Π·Ρ‹Π²Π°Π΅Ρ‚ ΠΏΠ΅Ρ€Π΅Π΄Π°Π½Π½Ρ‹Π΅ React- ΠΈ Next.js-спрайты с поиском, настройкой Ρ†Π²Π΅Ρ‚ΠΎΠ² ΠΈ ΠΏΡ€ΠΈΠΌΠ΅Ρ€Π°ΠΌΠΈ использования. -- **НастраиваСмыС трансформации SVG** β€” ΡƒΠ΄Π°Π»Π΅Π½ΠΈΠ΅ `width` ΠΈ `height` с сохранСниСм `viewBox`, Π·Π°ΠΌΠ΅Π½Π° исходных Ρ†Π²Π΅Ρ‚ΠΎΠ² Π½Π° CSS-ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½Ρ‹Π΅ ΠΈ transitions для `fill` ΠΈ `stroke`. -- **ΠžΡ‚Π΄Π΅Π»ΡŒΠ½Ρ‹ΠΉ ΠΊΠ΅ΡˆΠΈΡ€ΡƒΠ΅ΠΌΡ‹ΠΉ SVG asset** β€” SVG path-Π΄Π°Π½Π½Ρ‹Π΅ Π½Π΅ ΠΏΠΎΠΏΠ°Π΄Π°ΡŽΡ‚ Π² JavaScript chunks, Π° сборщик выпускаСт Ρ„Π°ΠΉΠ» с content hash. -- **ΠœΠ½ΠΎΠΆΠ΅ΡΡ‚Π²Π΅Π½Π½Ρ‹Π΅ спрайты** β€” нСзависимыС React- ΠΈ Next.js-ΠΌΠΎΠ΄ΡƒΠ»ΠΈ со своими ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Π°ΠΌΠΈ, Ρ‚ΠΈΠΏΠ°ΠΌΠΈ ΠΈ SVG assets. -- **Server-first Next.js** β€” generated-ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Ρ‹ Ρ€Π°Π±ΠΎΡ‚Π°ΡŽΡ‚ Π² Server Components, SSR ΠΈ SSG Π±Π΅Π· Π΄ΠΈΡ€Π΅ΠΊΡ‚ΠΈΠ²Ρ‹ `'use client'`. -- **Π€ΠΎΡ€ΠΌΠ°Ρ‚Ρ‹ ΠΏΠΎΠ΄ Ρ€Π°Π·Π½Ρ‹Π΅ сцСнарии** β€” React ΠΈ Next.js ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΡŽΡ‚ `stack`, legacy-Ρ€Π΅ΠΆΠΈΠΌ Ρ‚Π°ΠΊΠΆΠ΅ ΠΏΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΈΠ²Π°Π΅Ρ‚ `symbol` для ΡΡƒΡ‰Π΅ΡΡ‚Π²ΡƒΡŽΡ‰ΠΈΡ… ΠΈΠ½Ρ‚Π΅Π³Ρ€Π°Ρ†ΠΈΠΉ. +- **AI-agent friendly** - the repository includes a ready-to-use skill with up-to-date documentation for configuring, migrating, and troubleshooting `@gromlab/svg-sprites`. +- **TypeScript-friendly** - typed React components, union types, and runtime lists of available icons. +- **Clean generation** - generated files are automatically excluded from Git, the sprite does not need to be placed in `public` manually, and the generator updates only files it owns. +- **Shared icons without copying** - SVGs from the local folder and `inputFiles` are merged into a single sprite; one file can be used in multiple sprites. +- **Built-in interactive preview** - `` is integrated as an application page and displays the provided React and Next.js sprites with search, color controls, and usage examples. +- **Configurable SVG transformations** - remove `width` and `height` while preserving `viewBox`, replace source colors with CSS variables, and add transitions for `fill` and `stroke`. +- **Separate cacheable SVG asset** - SVG path data does not end up in JavaScript chunks, and the bundler emits a file with a content hash. +- **Multiple sprites** - independent React and Next.js modules with their own components, types, and SVG assets. +- **Server-first Next.js** - generated components work in Server Components, SSR, and SSG without the `'use client'` directive. +- **Formats for different use cases** - React and Next.js use `stack`; legacy mode also supports `symbol` for existing integrations. -## Π’Π°Π±Π»ΠΈΡ†Π° ΠΏΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΊΠΈ +## Support matrix -| Π‘Ρ€Π΅Π΄Π° | ΠšΠ»ΡŽΡ‡ ΠΌΠΎΠ΄Π° API | Бтатус | +| Environment | API mode key | Status | |---|---|---| -| React + Vite | `react@vite` | Π“ΠΎΡ‚ΠΎΠ²ΠΎ | -| React + Webpack 5 | `react@webpack` | Π“ΠΎΡ‚ΠΎΠ²ΠΎ | -| Next.js 16.2+ App Router + Turbopack | `next@app/turbopack` | Π“ΠΎΡ‚ΠΎΠ²ΠΎ | -| Next.js 13.4+ App Router + Webpack 5 | `next@app/webpack` | Π“ΠΎΡ‚ΠΎΠ²ΠΎ | -| Next.js 16.2+ Pages Router + Turbopack | `next@pages/turbopack` | Π“ΠΎΡ‚ΠΎΠ²ΠΎ | -| Next.js 12.2+ Pages Router + Webpack 5 | `next@pages/webpack` | Π“ΠΎΡ‚ΠΎΠ²ΠΎ | -| Vue | β€” | Π‘ΠΊΠΎΡ€ΠΎ | -| Standalone | β€” | Π‘ΠΊΠΎΡ€ΠΎ | +| React + Vite | `react@vite` | Ready | +| React + Webpack 5 | `react@webpack` | Ready | +| Next.js 16.2+ App Router + Turbopack | `next@app/turbopack` | Ready | +| Next.js 13.4+ App Router + Webpack 5 | `next@app/webpack` | Ready | +| Next.js 16.2+ Pages Router + Turbopack | `next@pages/turbopack` | Ready | +| Next.js 12.2+ Pages Router + Webpack 5 | `next@pages/webpack` | Ready | +| Vue | - | Coming soon | +| Standalone | - | Coming soon | -## ВрСбования +## Requirements -- Node.js 18 ΠΈΠ»ΠΈ Π½ΠΎΠ²Π΅Π΅; -- ΠΏΠ°ΠΊΠ΅Ρ‚ распространяСтся Ρ‚ΠΎΠ»ΡŒΠΊΠΎ ΠΊΠ°ΠΊ ESM ΠΈ ΠΏΠΎΠ΄ΠΊΠ»ΡŽΡ‡Π°Π΅Ρ‚ΡΡ Ρ‡Π΅Ρ€Π΅Π· `import`; -- React 18 ΠΈΠ»ΠΈ 19 трСбуСтся Ρ‚ΠΎΠ»ΡŒΠΊΠΎ для generated-ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚ΠΎΠ² ΠΈ Ρ‚ΠΎΡ‡ΠΊΠΈ Π²Ρ…ΠΎΠ΄Π° `@gromlab/svg-sprites/react`; -- для Ρ‚ΠΈΠΏΠΈΠ·Π°Ρ†ΠΈΠΈ subpath exports ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠΉΡ‚Π΅ TypeScript 5+ с `moduleResolution: "bundler"`, `"node16"` ΠΈΠ»ΠΈ `"nodenext"`. +- Node.js 18 or newer; +- the package is distributed as ESM only and is loaded via `import`; +- React 18 or 19 is required only for generated components and the `@gromlab/svg-sprites/react` entry point; +- for subpath export typings, use TypeScript 5+ with `moduleResolution: "bundler"`, `"node16"`, or `"nodenext"`. -## Быстрый старт +## Quick start -Для быстрого старта Π²ΠΎΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠΉΡ‚Π΅ΡΡŒ инструкциСй для вашСго стСка: +For a quick start, follow the guide for your stack: -- [React + Vite](docs/ru/react-vite.md) -- [React + Webpack 5](docs/ru/react-webpack.md) -- [Next.js App Router](docs/ru/next-app.md) -- [Next.js Pages Router](docs/ru/next-pages.md) +- [React + Vite](docs/en/react-vite.md) +- [React + Webpack 5](docs/en/react-webpack.md) +- [Next.js App Router](docs/en/next-app.md) +- [Next.js Pages Router](docs/en/next-pages.md) -## ΠšΠΎΠ½Ρ„ΠΈΠ³ΡƒΡ€Π°Ρ†ΠΈΡ +## Configuration ### React @@ -80,7 +83,7 @@ import { defineReactSpriteConfig } from '@gromlab/svg-sprites' export default defineReactSpriteConfig({ name: 'file-manager', - description: 'Иконки Ρ„Π°ΠΉΠ»ΠΎΠ²ΠΎΠ³ΠΎ ΠΌΠ΅Π½Π΅Π΄ΠΆΠ΅Ρ€Π°', + description: 'File manager icons', inputFolder: './icons', inputFiles: [ '../../shared/icons/check.svg', @@ -94,78 +97,78 @@ export default defineReactSpriteConfig({ }) ``` -| ΠžΠΏΡ†ΠΈΡ | Π’ΠΈΠΏ | По ΡƒΠΌΠΎΠ»Ρ‡Π°Π½ΠΈΡŽ | НазначСниС | +| Option | Type | Default | Purpose | |---|---|---|---| -| `name` | `string` | Имя ΠΏΠ°ΠΏΠΊΠΈ | Имя спрайта, ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Π° ΠΈ ΠΏΡƒΠ±Π»ΠΈΡ‡Π½Ρ‹Ρ… Ρ‚ΠΈΠΏΠΎΠ² | -| `description` | `string` | НСт | ОписаниС для Ρ‚ΠΈΠΏΠΎΠ² ΠΈ debug-манифСста | -| `inputFolder` | `string` | `./icons` | Папка с исходными SVG ΠΎΡ‚Π½ΠΎΡΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎ ΠΊΠΎΠ½Ρ„ΠΈΠ³Π° | -| `inputFiles` | `string[]` | `[]` | Π”ΠΎΠΏΠΎΠ»Π½ΠΈΡ‚Π΅Π»ΡŒΠ½Ρ‹Π΅ SVG-Ρ„Π°ΠΉΠ»Ρ‹ ΠΎΡ‚Π½ΠΎΡΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎ ΠΊΠΎΠ½Ρ„ΠΈΠ³Π° | -| `transform` | `TransformOptions` | ВсС Π²ΠΊΠ»ΡŽΡ‡Π΅Π½Ρ‹ | [Настройки трансформации](#трансформации) исходных SVG | -| `generatedNotice` | `boolean` | `true` | ПолноС Π»ΠΈΠ±ΠΎ ΠΊΠΎΡ€ΠΎΡ‚ΠΊΠΎΠ΅ ΠΏΡ€Π΅Π΄ΡƒΠΏΡ€Π΅ΠΆΠ΄Π΅Π½ΠΈΠ΅ Π² generated-Ρ„Π°ΠΉΠ»Π°Ρ… | +| `name` | `string` | Folder name | Name of the sprite, component, and public types | +| `description` | `string` | None | Description for types and the debug manifest | +| `inputFolder` | `string` | `./icons` | Folder containing source SVGs, relative to the config | +| `inputFiles` | `string[]` | `[]` | Additional SVG files, relative to the config | +| `transform` | `TransformOptions` | All enabled | [Transformation settings](#transformations) for source SVGs | +| `generatedNotice` | `boolean` | `true` | Full or short warning in generated files | -`inputFolder` ΠΈ `inputFiles` ΠΎΠ±ΡŠΠ΅Π΄ΠΈΠ½ΡΡŽΡ‚ΡΡ Π² ΠΎΠ΄ΠΈΠ½ спрайт, поэтому ΠΎΠ΄ΠΈΠ½ SVG-Ρ„Π°ΠΉΠ» ΠΌΠΎΠΆΠ½ΠΎ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ Π² Π½Π΅ΡΠΊΠΎΠ»ΡŒΠΊΠΈΡ… спрайтах Π±Π΅Π· копирования. Если нСявной ΠΏΠ°ΠΏΠΊΠΈ `./icons` Π½Π΅Ρ‚, Π½ΠΎ `inputFiles` Π·Π°ΠΏΠΎΠ»Π½Π΅Π½, гСнСрация продолТаСтся Ρ‚ΠΎΠ»ΡŒΠΊΠΎ ΠΏΠΎ списку. Π―Π²Π½ΠΎ указанная ΠΎΡ‚ΡΡƒΡ‚ΡΡ‚Π²ΡƒΡŽΡ‰Π°Ρ ΠΏΠ°ΠΏΠΊΠ° считаСтся ошибкой. ΠžΠ΄ΠΈΠ½Π°ΠΊΠΎΠ²Ρ‹Π΅ ΠΏΡƒΡ‚ΠΈ Π΄Π΅Π΄ΡƒΠΏΠ»ΠΈΡ†ΠΈΡ€ΡƒΡŽΡ‚ΡΡ, Π° Ρ€Π°Π·Π½Ρ‹Π΅ Ρ„Π°ΠΉΠ»Ρ‹ с ΠΎΠ΄ΠΈΠ½Π°ΠΊΠΎΠ²Ρ‹ΠΌ ΠΈΠΌΠ΅Π½Π΅ΠΌ ΠΈΠΊΠΎΠ½ΠΊΠΈ ΡΡ‡ΠΈΡ‚Π°ΡŽΡ‚ΡΡ ошибкой. +`inputFolder` and `inputFiles` are merged into a single sprite, so one SVG file can be used in multiple sprites without copying. If the implicit `./icons` folder does not exist but `inputFiles` is populated, generation continues using only the list. An explicitly specified missing folder is an error. Duplicate paths are deduplicated, while different files with the same icon name are treated as an error. -`name` записываСтся Π² kebab-case ΠΈ Π΄ΠΎΠ»ΠΆΠ½ΠΎ Π½Π°Ρ‡ΠΈΠ½Π°Ρ‚ΡŒΡΡ с латинской Π±ΡƒΠΊΠ²Ρ‹. React ΠΈ Next.js presets ΡΠΎΠ·Π΄Π°ΡŽΡ‚ Ρ„ΠΎΡ€ΠΌΠ°Ρ‚ `stack`. +`name` is stored in kebab-case and must start with a Latin letter. The React and Next.js presets produce the `stack` format. ### Next.js -Next.js ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ Ρ‚ΠΎΡ‚ ΠΆΠ΅ `svg-sprite.config.ts` ΠΈ Π½Π°Π±ΠΎΡ€ ΠΎΠΏΡ†ΠΈΠΉ. Для Ρ‚ΠΈΠΏΠΈΠ·Π°Ρ†ΠΈΠΈ ΠΌΠΎΠΆΠ½ΠΎ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ ΠΎΡ‚Π΄Π΅Π»ΡŒΠ½Ρ‹ΠΉ Ρ…Π΅Π»ΠΏΠ΅Ρ€: +Next.js uses the same `svg-sprite.config.ts` and set of options. For type checking, you can use a dedicated helper: ```ts import { defineNextSpriteConfig } from '@gromlab/svg-sprites' export default defineNextSpriteConfig({ name: 'file-manager', - description: 'Иконки Ρ„Π°ΠΉΠ»ΠΎΠ²ΠΎΠ³ΠΎ ΠΌΠ΅Π½Π΅Π΄ΠΆΠ΅Ρ€Π°', + description: 'File manager icons', inputFolder: './icons', }) ``` -Π ΠΎΡƒΡ‚Π΅Ρ€ ΠΈ сборщик Π²Ρ‹Π±ΠΈΡ€Π°ΡŽΡ‚ΡΡ Ρ‡Π΅Ρ€Π΅Π· mode key, поэтому ΠΏΠ΅Ρ€Π΅ΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅ ΠΌΠ΅ΠΆΠ΄Ρƒ Turbopack ΠΈ Webpack всСгда явно ΠΎΡ‚Ρ€Π°ΠΆΠ΅Π½ΠΎ Π² ΠΊΠΎΠΌΠ°Π½Π΄Π΅ Π³Π΅Π½Π΅Ρ€Π°Ρ†ΠΈΠΈ. +The router and bundler are selected through the mode key, so switching between Turbopack and Webpack is always explicitly reflected in the generation command. -## ΠœΠ½ΠΎΠΆΠ΅ΡΡ‚Π²Π΅Π½Π½Ρ‹Π΅ спрайты +## Multiple sprites -ΠŸΡ€ΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅ ΠΌΠΎΠΆΠ΅Ρ‚ ΡΠΎΠ΄Π΅Ρ€ΠΆΠ°Ρ‚ΡŒ нСсколько нСзависимых спрайтов с Ρ€Π°Π·Π½ΠΎΠΉ ΠΎΠ±Π»Π°ΡΡ‚ΡŒΡŽ использования: +An application can contain several independent sprites for different scopes: -**ΠŸΡ€ΠΎΠ±Π»Π΅ΠΌΠ°:** ΠΎΠ΄ΠΈΠ½ Π³Π»ΠΎΠ±Π°Π»ΡŒΠ½Ρ‹ΠΉ спрайт Π·Π°Π³Ρ€ΡƒΠΆΠ°Π΅Ρ‚ ΠΈΠΊΠΎΠ½ΠΊΠΈ, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ Ρ‚Π΅ΠΊΡƒΡ‰Π΅ΠΌΡƒ экрану Π½Π΅ Π½ΡƒΠΆΠ½Ρ‹. +**Problem:** one global sprite loads icons that the current screen does not need. -**РСшСниС:** ΠΎΠ±Ρ‰ΠΈΠ΅ ΠΈΠΊΠΎΠ½ΠΊΠΈ Ρ…Ρ€Π°Π½ΠΈΡ‚ΡŒ глобально, Π° Π½Π°Π±ΠΎΡ€Ρ‹ страниц ΠΈ ΠΊΡ€ΡƒΠΏΠ½Ρ‹Ρ… ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚ΠΎΠ² β€” Π² ΠΎΡ‚Π΄Π΅Π»ΡŒΠ½Ρ‹Ρ… спрайтах, Π·Π°Π³Ρ€ΡƒΠΆΠ°Π΅ΠΌΡ‹Ρ… вмСстС с Π½ΠΈΠΌΠΈ. +**Solution:** keep shared icons globally, and place icon sets for pages and large components in separate sprites that load alongside them. ```text -global β†’ GlobalIcon β†’ ΠΎΠ±Ρ‰ΠΈΠ΅ ΠΈΠΊΠΎΠ½ΠΊΠΈ прилоТСния -analytics-page β†’ AnalyticsPageIcon β†’ ΠΈΠΊΠΎΠ½ΠΊΠΈ ΠΎΡ‚Π΄Π΅Π»ΡŒΠ½ΠΎΠΉ страницы -file-manager β†’ FileManagerIcon β†’ ΠΈΠΊΠΎΠ½ΠΊΠΈ ΠΊΡ€ΡƒΠΏΠ½ΠΎΠ³ΠΎ ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Π° +global -> GlobalIcon -> shared application icons +analytics-page -> AnalyticsPageIcon -> icons for a specific page +file-manager -> FileManagerIcon -> icons for a large component ``` -- **Π“Π»ΠΎΠ±Π°Π»ΡŒΠ½Ρ‹ΠΉ спрайт** содСрТит нСбольшиС ΠΎΠ±Ρ‰ΠΈΠ΅ ΠΈΠΊΠΎΠ½ΠΊΠΈ, ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅ΠΌΡ‹Π΅ Π² Ρ€Π°Π·Π½Ρ‹Ρ… частях прилоТСния: Π½Π°Π²ΠΈΠ³Π°Ρ†ΠΈΡŽ, состояния ΠΈ Π±Π°Π·ΠΎΠ²Ρ‹Π΅ дСйствия. -- **Π‘ΠΏΡ€Π°ΠΉΡ‚ страницы** загруТаСтся вмСстС с ΠΊΠΎΠ½ΠΊΡ€Π΅Ρ‚Π½Ρ‹ΠΌ Ρ€Π°Π·Π΄Π΅Π»ΠΎΠΌ ΠΈ Π½Π΅ ΡƒΠ²Π΅Π»ΠΈΡ‡ΠΈΠ²Π°Π΅Ρ‚ ΠΎΠ±Ρ‰ΠΈΠΉ спрайт ΠΈΠΊΠΎΠ½ΠΊΠ°ΠΌΠΈ, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ большС Π½ΠΈΠ³Π΄Π΅ Π½Π΅ Π½ΡƒΠΆΠ½Ρ‹. -- **Π‘ΠΏΡ€Π°ΠΉΡ‚ ΠΊΡ€ΡƒΠΏΠ½ΠΎΠ³ΠΎ ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Π°** инкапсулируСт собствСнный Π½Π°Π±ΠΎΡ€ ΠΈΠΊΠΎΠ½ΠΎΠΊ слоТного UI-модуля, Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€ Ρ„Π°ΠΉΠ»ΠΎΠ²ΠΎΠ³ΠΎ ΠΌΠ΅Π½Π΅Π΄ΠΆΠ΅Ρ€Π° ΠΈΠ»ΠΈ Ρ€Π΅Π΄Π°ΠΊΡ‚ΠΎΡ€Π°. +- **Global sprite** contains a small set of shared icons used in different parts of the application: navigation, states, and basic actions. +- **Page sprite** loads with a specific section and does not increase the shared sprite with icons that are not needed anywhere else. +- **Large component sprite** encapsulates the icon set of a complex UI module, such as a file manager or editor. -КаТдая Π³Ρ€ΡƒΠΏΠΏΠ° ΠΏΠΎΠ»ΡƒΡ‡Π°Π΅Ρ‚: +Each group gets: -- собствСнный SVG asset; -- собствСнный Ρ‚ΠΈΠΏΠΈΠ·ΠΈΡ€ΠΎΠ²Π°Π½Π½Ρ‹ΠΉ ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚; -- ΠΎΡ‚Π΄Π΅Π»ΡŒΠ½Ρ‹ΠΉ список ΠΈΠΌΡ‘Π½ ΠΈΠΊΠΎΠ½ΠΎΠΊ; -- ΠΎΡ‚Π΄Π΅Π»ΡŒΠ½Ρ‹ΠΉ debug-манифСст; -- нСзависимый cache lifecycle. +- its own SVG asset; +- its own typed component; +- a separate list of icon names; +- a separate debug manifest; +- an independent cache lifecycle. ## TypeScript -Главная Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎΡΡ‚ΡŒ TypeScript API β€” Π°Π²Ρ‚ΠΎΠ΄ΠΎΠΏΠΎΠ»Π½Π΅Π½ΠΈΠ΅ ΠΈΠΌΡ‘Π½ ΠΈΠΊΠΎΠ½ΠΎΠΊ нСпосрСдствСнно Π² prop `icon`: +The main feature of the TypeScript API is icon name autocomplete directly in the `icon` prop: ```tsx -// ↑ Ρ€Π΅Π΄Π°ΠΊΡ‚ΠΎΡ€ ΠΏΡ€Π΅Π΄Π»Π°Π³Π°Π΅Ρ‚ всС ΠΈΠΊΠΎΠ½ΠΊΠΈ спрайта +// ^ the editor suggests every icon in the sprite ``` -ИмСна SVG-Ρ„Π°ΠΉΠ»ΠΎΠ² становятся допустимыми значСниями `icon`. ΠžΠΏΠ΅Ρ‡Π°Ρ‚ΠΊΠ° ΠΈΠ»ΠΈ нСизвСстноС имя сразу становятся ошибкой TypeScript: +SVG file names become valid `icon` values. A typo or unknown name immediately becomes a TypeScript error: ```tsx - // ошибка TypeScript + // TypeScript error ``` -Для ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠ½ΠΎΠ³ΠΎ доступа generated-ΠΌΠΎΠ΄ΡƒΠ»ΡŒ экспортируСт readonly-массив всСх доступных ΠΈΠΊΠΎΠ½ΠΎΠΊ ΠΊΠΎΠ½ΠΊΡ€Π΅Ρ‚Π½ΠΎΠ³ΠΎ спрайта: +For programmatic access, the generated module exports a readonly array of all icons available in a specific sprite: ```ts import { fileManagerIconNames } from './svg-sprite' @@ -173,39 +176,39 @@ import { fileManagerIconNames } from './svg-sprite' // readonly ['check', 'folder', ...] ``` -Π­Ρ‚ΠΎΡ‚ список ΠΌΠΎΠΆΠ½ΠΎ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ Π² собствСнных ΠΊΠ°Ρ‚Π°Π»ΠΎΠ³Π°Ρ…, select-ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Π°Ρ…, тСстах ΠΈ Π΄Ρ€ΡƒΠ³ΠΈΡ… runtime-сцСнариях. Из Π½Π΅Π³ΠΎ Ρ‚Π°ΠΊΠΆΠ΅ выводится union-Ρ‚ΠΈΠΏ `FileManagerIconName`. +You can use this list in custom catalogs, select components, tests, and other runtime scenarios. The `FileManagerIconName` union type is also derived from it. -ИмСна Ρ„Π°ΠΉΠ»ΠΎΠ² с ΠΏΡ€ΠΎΠ±Π΅Π»Π°ΠΌΠΈ ΠΈ Π΄Ρ€ΡƒΠ³ΠΈΠΌΠΈ нСбСзопасными для SVG ID символами ΠΎΡΡ‚Π°ΡŽΡ‚ΡΡ Ρ‡Π°ΡΡ‚ΡŒΡŽ ΠΏΡƒΠ±Π»ΠΈΡ‡Π½ΠΎΠ³ΠΎ TypeScript API. Для Π²Π½ΡƒΡ‚Ρ€Π΅Π½Π½Π΅Π³ΠΎ `` Π³Π΅Π½Π΅Ρ€Π°Ρ‚ΠΎΡ€ создаёт ΡΡ‚Π°Π±ΠΈΠ»ΡŒΠ½Ρ‹ΠΉ hash ID. +File names containing spaces and other characters unsafe for SVG IDs remain part of the public TypeScript API. For the internal ``, the generator creates a stable hash ID. ```text -folder open.svg β†’ icon="folder open" β†’ id="icon-" +folder open.svg -> icon="folder open" -> id="icon-" ``` -Для Ρ‚Π°ΠΊΠΈΡ… ΠΈΠΌΡ‘Π½ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠΉΡ‚Π΅ generated-ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚ ΠΈΠ»ΠΈ `id` ΠΈΠ· debug-манифСста. Π ΡƒΡ‡Π½Ρ‹Π΅ ΠΏΡ€ΠΈΠΌΠ΅Ρ€Ρ‹ Π½ΠΈΠΆΠ΅ с `#<имя>` подходят Ρ‚ΠΎΠ»ΡŒΠΊΠΎ для ΠΈΠΌΡ‘Π½, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ ΡƒΠΆΠ΅ ΡΠ²Π»ΡΡŽΡ‚ΡΡ бСзопасными SVG ID. +For such names, use the generated component or the `id` from the debug manifest. The manual examples below using `#` are suitable only for names that are already safe SVG IDs. -## Π€ΠΎΡ€ΠΌΠ°Ρ‚Ρ‹ спрайтов +## Sprite formats -`stack` β€” Π±ΠΎΠ»Π΅Π΅ соврСмСнный Ρ„ΠΎΡ€ΠΌΠ°Ρ‚, поэтому ΠΎΠ½ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ΡΡ ΠΏΠΎ ΡƒΠΌΠΎΠ»Ρ‡Π°Π½ΠΈΡŽ. Иконки ΠΌΠΎΠΆΠ½ΠΎ ΠΎΡ‚ΠΎΠ±Ρ€Π°ΠΆΠ°Ρ‚ΡŒ Ρ‡Π΅Ρ€Π΅Π· ``, `` ΠΈ CSS `background-image`. +`stack` is the more modern format, so it is used by default. Icons can be rendered through ``, ``, and CSS `background-image`. -`symbol` сохраняСтся для совмСстимости с ΡΡƒΡ‰Π΅ΡΡ‚Π²ΡƒΡŽΡ‰ΠΈΠΌΠΈ интСграциями ΠΈ ΠΏΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΈΠ²Π°Π΅Ρ‚ ΠΎΡ‚ΠΎΠ±Ρ€Π°ΠΆΠ΅Π½ΠΈΠ΅ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ Ρ‡Π΅Ρ€Π΅Π· ``. +`symbol` is retained for compatibility with existing integrations and supports rendering only through ``. -## Бпособы отобраТСния +## Rendering methods -### React-ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚ β€” рСкомСндуСтся +### React component - recommended -Generated-ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚ прСдоставляСт Ρ‚ΠΈΠΏΠΈΠ·Π°Ρ†ΠΈΡŽ, Π°Π²Ρ‚ΠΎΠ΄ΠΎΠΏΠΎΠ»Π½Π΅Π½ΠΈΠ΅ ΠΈΠΌΡ‘Π½ ΠΈΠΊΠΎΠ½ΠΎΠΊ ΠΈ сам Ρ„ΠΎΡ€ΠΌΠΈΡ€ΡƒΠ΅Ρ‚ URL SVG asset. +The generated component provides type safety and icon name autocomplete, and constructs the SVG asset URL itself. ```tsx ``` -Π§Π΅Ρ€Π΅Π· `color` ΠΈ `--icon-color-N` доступны ΠΎΠ΄Π½ΠΎΡ†Π²Π΅Ρ‚Π½Ρ‹Π΅ ΠΈ ΠΌΠ½ΠΎΠ³ΠΎΡ†Π²Π΅Ρ‚Π½Ρ‹Π΅ ΠΈΠΊΠΎΠ½ΠΊΠΈ. +Monochrome and multicolor icons are supported through `color` and `--icon-color-N`. -### Π‘Π°ΠΌΠΎΡΡ‚ΠΎΡΡ‚Π΅Π»ΡŒΠ½ΠΎ Ρ‡Π΅Ρ€Π΅Π· `` +### Manually with `` -Π₯ΠΎΡ€ΠΎΡˆΠΈΠΉ Π½ΠΈΠ·ΠΊΠΎΡƒΡ€ΠΎΠ²Π½Π΅Π²Ρ‹ΠΉ способ с ΠΏΠΎΠ»Π½Ρ‹ΠΌ ΡƒΠΏΡ€Π°Π²Π»Π΅Π½ΠΈΠ΅ΠΌ Ρ€Π°Π·ΠΌΠ΅Ρ€Π°ΠΌΠΈ ΠΈ Ρ†Π²Π΅Ρ‚Π°ΠΌΠΈ. React-ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚ ΠΏΠΎΠ΄ ΠΊΠ°ΠΏΠΎΡ‚ΠΎΠΌ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ ΠΈΠΌΠ΅Π½Π½ΠΎ Π΅Π³ΠΎ. +A good low-level method that provides full control over dimensions and colors. This is exactly what the React component uses under the hood. -Бпособ получСния `spriteUrl` зависит ΠΎΡ‚ сборщика. +How you obtain `spriteUrl` depends on the bundler. **Vite:** @@ -222,7 +225,7 @@ const spriteUrl = new URL( ).href ``` -**Next.js с Webpack 5 ΠΈΠ»ΠΈ Turbopack:** +**Next.js with Webpack 5 or Turbopack:** ```tsx const spriteUrl = new URL( @@ -231,7 +234,7 @@ const spriteUrl = new URL( ).href ``` -ПослС получСния URL ΠΈΠΊΠΎΠ½ΠΊΠ° отобраТаСтся ΠΎΠ΄ΠΈΠ½Π°ΠΊΠΎΠ²ΠΎ: +After obtaining the URL, the icon is rendered the same way: ```tsx @@ -239,17 +242,17 @@ const spriteUrl = new URL( ``` -Vite, Webpack 5 ΠΈ Next.js сами Π·Π°ΠΌΠ΅Π½ΡΡŽΡ‚ исходный ΠΏΡƒΡ‚ΡŒ Π½Π° ΠΈΡ‚ΠΎΠ³ΠΎΠ²Ρ‹ΠΉ URL asset с hash. +Vite, Webpack 5, and Next.js replace the source path with the final hashed asset URL automatically. -### Π§Π΅Ρ€Π΅Π· `` β€” ΠΌΠ΅Π½Π΅Π΅ эффСктивно +### With `` - less efficient ```tsx -Π“ΠΎΡ‚ΠΎΠ²ΠΎ +Done ``` -SVG загруТаСтся ΠΊΠ°ΠΊ ΠΈΠ·ΠΎΠ»ΠΈΡ€ΠΎΠ²Π°Π½Π½ΠΎΠ΅ ΠΈΠ·ΠΎΠ±Ρ€Π°ΠΆΠ΅Π½ΠΈΠ΅: ΠΈΠ·ΠΌΠ΅Π½ΠΈΡ‚ΡŒ Π΅Π³ΠΎ Ρ†Π²Π΅Ρ‚Π° Ρ‡Π΅Ρ€Π΅Π· `color` ΠΈΠ»ΠΈ `--icon-color-N` нСльзя. +The SVG loads as an isolated image: its colors cannot be changed through `color` or `--icon-color-N`. -### Π§Π΅Ρ€Π΅Π· CSS `background-image` β€” ΠΌΠ΅Π½Π΅Π΅ эффСктивно +### With CSS `background-image` - less efficient ```css .icon { @@ -257,9 +260,9 @@ SVG загруТаСтся ΠΊΠ°ΠΊ ΠΈΠ·ΠΎΠ»ΠΈΡ€ΠΎΠ²Π°Π½Π½ΠΎΠ΅ ΠΈΠ·ΠΎΠ±Ρ€Π°ΠΆΠ΅Π½ } ``` -Как ΠΈ ``, этот способ Π½Π΅ позволяСт ΡƒΠΏΡ€Π°Π²Π»ΡΡ‚ΡŒ Π²Π½ΡƒΡ‚Ρ€Π΅Π½Π½ΠΈΠΌΠΈ Ρ†Π²Π΅Ρ‚Π°ΠΌΠΈ SVG. ΠŸΡƒΡ‚ΡŒ указываСтся ΠΎΡ‚Π½ΠΎΡΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎ CSS-Ρ„Π°ΠΉΠ»Π°, Π° Vite/Webpack замСняСт Π΅Π³ΠΎ Π½Π° ΠΈΡ‚ΠΎΠ³ΠΎΠ²Ρ‹ΠΉ URL с hash ΠΏΡ€ΠΈ сборкС. +Like ``, this method does not allow you to control internal SVG colors. The path is specified relative to the CSS file, and Vite/Webpack replaces it with the final hashed URL during the build. -### Π§Π΅Ρ€Π΅Π· CSS mask β€” ΠΌΠ΅Π½Π΅Π΅ эффСктивно +### With CSS mask - less efficient ```css .icon { @@ -268,37 +271,37 @@ SVG загруТаСтся ΠΊΠ°ΠΊ ΠΈΠ·ΠΎΠ»ΠΈΡ€ΠΎΠ²Π°Π½Π½ΠΎΠ΅ ΠΈΠ·ΠΎΠ±Ρ€Π°ΠΆΠ΅Π½ } ``` -Mask оставляСт Ρ‚ΠΎΠ»ΡŒΠΊΠΎ силуэт ΠΈ ΠΎΠΊΡ€Π°ΡˆΠΈΠ²Π°Π΅Ρ‚ Π΅Π³ΠΎ ΠΎΠ΄Π½ΠΈΠΌ Ρ†Π²Π΅Ρ‚ΠΎΠΌ. Π˜ΡΡ…ΠΎΠ΄Π½Ρ‹Π΅ Ρ†Π²Π΅Ρ‚Π°, gradients ΠΈ различия ΠΌΠ΅ΠΆΠ΄Ρƒ `fill` ΠΈ `stroke` Ρ‚Π΅Ρ€ΡΡŽΡ‚ΡΡ. +A mask retains only the silhouette and colors it with a single color. The original colors, gradients, and distinctions between `fill` and `stroke` are lost. -## Врансформации +## Transformations -ВсС трансформации Π²ΠΊΠ»ΡŽΡ‡Π΅Π½Ρ‹ ΠΏΠΎ ΡƒΠΌΠΎΠ»Ρ‡Π°Π½ΠΈΡŽ ΠΈ Π½Π°ΡΡ‚Ρ€Π°ΠΈΠ²Π°ΡŽΡ‚ΡΡ нСзависимо Ρ‡Π΅Ρ€Π΅Π· `transform`. +All transformations are enabled by default and configured independently through `transform`. -| ΠžΠΏΡ†ΠΈΡ | По ΡƒΠΌΠΎΠ»Ρ‡Π°Π½ΠΈΡŽ | Π§Ρ‚ΠΎ Π΄Π΅Π»Π°Π΅Ρ‚ | +| Option | Default | What it does | |---|---|---| -| `removeSize` | `true` | УдаляСт `width` ΠΈ `height` с ΠΊΠΎΡ€Π½Π΅Π²ΠΎΠ³ΠΎ ``, сохраняя ΡΡƒΡ‰Π΅ΡΡ‚Π²ΡƒΡŽΡ‰ΠΈΠΉ `viewBox`. Π Π°Π·ΠΌΠ΅Ρ€ ΠΈΠΊΠΎΠ½ΠΊΠΈ послС этого задаётся снаруТи. | -| `replaceColors` | `true` | ЗамСняСт Ρ†Π²Π΅Ρ‚Π° `fill` ΠΈ `stroke` Π½Π° `--icon-color-N`. Для ΠΎΠ΄Π½ΠΎΡ†Π²Π΅Ρ‚Π½ΠΎΠΉ ΠΈΠΊΠΎΠ½ΠΊΠΈ fallback становится `currentColor`, для ΠΌΠ½ΠΎΠ³ΠΎΡ†Π²Π΅Ρ‚Π½ΠΎΠΉ ΡΠΎΡ…Ρ€Π°Π½ΡΡŽΡ‚ΡΡ исходныС Ρ†Π²Π΅Ρ‚Π°. | -| `addTransition` | `true` | ДобавляСт `style="transition:fill 0.3s,stroke 0.3s;"` нСпосрСдствСнно Ρ†Π²Π΅Ρ‚Π½Ρ‹ΠΌ элСмСнтам SVG. Π‘ΡƒΡ‰Π΅ΡΡ‚Π²ΡƒΡŽΡ‰ΠΈΠΉ `transition` Π½Π΅ пСрСзаписываСтся. | +| `removeSize` | `true` | Removes `width` and `height` from the root `` while preserving the existing `viewBox`. The icon size is then set externally. | +| `replaceColors` | `true` | Replaces `fill` and `stroke` colors with `--icon-color-N`. For a monochrome icon, the fallback becomes `currentColor`; for a multicolor icon, the original colors are preserved. | +| `addTransition` | `true` | Adds `style="transition:fill 0.3s,stroke 0.3s;"` directly to colored SVG elements. An existing `transition` is not overwritten. | -Π§Ρ‚ΠΎΠ±Ρ‹ ΠΎΡ‚ΠΊΠ»ΡŽΡ‡ΠΈΡ‚ΡŒ ΠΏΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΠΎΠ²Π°Π½ΠΈΠ΅, ΠΏΠ΅Ρ€Π΅Π΄Π°ΠΉΡ‚Π΅ для ΡΠΎΠΎΡ‚Π²Π΅Ρ‚ΡΡ‚Π²ΡƒΡŽΡ‰Π΅ΠΉ ΠΎΠΏΡ†ΠΈΠΈ `false`. ΠŸΠΎΠ΄Ρ€ΠΎΠ±Π½Π΅Π΅ ΠΎ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Π΅ `replaceColors` β€” Π² Ρ€Π°Π·Π΄Π΅Π»Π΅ [Β«Π£ΠΏΡ€Π°Π²Π»Π΅Π½ΠΈΠ΅ Ρ†Π²Π΅Ρ‚ΠΎΠΌ ΠΈΠΊΠΎΠ½ΠΎΠΊΒ»](#ΡƒΠΏΡ€Π°Π²Π»Π΅Π½ΠΈΠ΅-Ρ†Π²Π΅Ρ‚ΠΎΠΌ-ΠΈΠΊΠΎΠ½ΠΎΠΊ). +To disable a transformation, pass `false` for the corresponding option. For more details about the result of `replaceColors`, see [Icon color management](#icon-color-management). -## Π£ΠΏΡ€Π°Π²Π»Π΅Π½ΠΈΠ΅ Ρ†Π²Π΅Ρ‚ΠΎΠΌ ΠΈΠΊΠΎΠ½ΠΎΠΊ +## Icon color management -ΠŸΡ€ΠΈ Π²ΠΊΠ»ΡŽΡ‡Ρ‘Π½Π½ΠΎΠΉ Π·Π°ΠΌΠ΅Π½Π΅ Ρ†Π²Π΅Ρ‚ΠΎΠ² Π³Π΅Π½Π΅Ρ€Π°Ρ‚ΠΎΡ€ Π°Π½Π°Π»ΠΈΠ·ΠΈΡ€ΡƒΠ΅Ρ‚ `fill` ΠΈ `stroke` ΠΈ ΠΏΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΡƒΠ΅Ρ‚ ΠΈΡ… Π² CSS custom properties. +When color replacement is enabled, the generator analyzes `fill` and `stroke` and converts them to CSS custom properties. -### ΠœΠΎΠ½ΠΎΡ…Ρ€ΠΎΠΌΠ½Ρ‹Π΅ ΠΈΠΊΠΎΠ½ΠΊΠΈ +### Monochrome icons -Если Π½Π°ΠΉΠ΄Π΅Π½ ΠΎΠ΄ΠΈΠ½ Ρ†Π²Π΅Ρ‚, fallback замСняСтся Π½Π° `currentColor`: +If one color is found, the fallback is replaced with `currentColor`: ```svg stroke="var(--icon-color-1, currentColor)" ``` -Π¦Π²Π΅Ρ‚ΠΎΠΌ управляСт CSS-свойство `color` внСшнСго `` ΠΈΠ»ΠΈ Π΅Π³ΠΎ родитСля. +The color is controlled by the CSS `color` property of the outer `` or its parent. -### ΠœΠ½ΠΎΠ³ΠΎΡ†Π²Π΅Ρ‚Π½Ρ‹Π΅ ΠΈΠΊΠΎΠ½ΠΊΠΈ +### Multicolor icons -ΠšΠ°ΠΆΠ΄Ρ‹ΠΉ ΡƒΠ½ΠΈΠΊΠ°Π»ΡŒΠ½Ρ‹ΠΉ Ρ†Π²Π΅Ρ‚ ΠΏΠΎΠ»ΡƒΡ‡Π°Π΅Ρ‚ ΠΎΡ‚Π΄Π΅Π»ΡŒΠ½ΡƒΡŽ ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½ΡƒΡŽ с исходным fallback: +Each unique color gets a separate variable with the original fallback: ```svg fill="var(--icon-color-1, #798198)" @@ -306,7 +309,7 @@ fill="var(--icon-color-2, #ffffff)" fill="var(--icon-color-3, #129d9d)" ``` -Π‘Ρ‚Ρ€Π°Π½ΠΈΡ†Π° ΠΌΠΎΠΆΠ΅Ρ‚ Π·Π°ΠΌΠ΅Π½ΠΈΡ‚ΡŒ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΡ‹Π΅ Ρ†Π²Π΅Ρ‚Π°: +The page can override only the required colors: ```css .icon { @@ -315,62 +318,62 @@ fill="var(--icon-color-3, #129d9d)" } ``` -### ΠžΠ³Ρ€Π°Π½ΠΈΡ‡Π΅Π½ΠΈΡ Ρ†Π²Π΅Ρ‚ΠΎΠ² +### Color limitations -- `none`, `transparent`, `inherit`, `unset` ΠΈ `initial` Π½Π΅ Π·Π°ΠΌΠ΅Π½ΡΡŽΡ‚ΡΡ; -- Ρ†Π²Π΅Ρ‚Π° Π² Π°Ρ‚Ρ€ΠΈΠ±ΡƒΡ‚Π°Ρ… `fill`, `stroke` ΠΈ inline `style` ΠΎΠ±Ρ€Π°Π±Π°Ρ‚Ρ‹Π²Π°ΡŽΡ‚ΡΡ Π½Π°Π΄Ρ‘ΠΆΠ½Π΅Π΅ всСго; -- CSS-классы ΠΈ внСшниС stylesheets Π²Π½ΡƒΡ‚Ρ€ΠΈ исходного SVG Π½Π΅ ΡΠ²Π»ΡΡŽΡ‚ΡΡ основным сцСнариСм трансформации; -- gradients, patterns, filters ΠΈ значСния `url(#...)` Ρ‚Ρ€Π΅Π±ΡƒΡŽΡ‚ ΠΎΡ‚Π΄Π΅Π»ΡŒΠ½ΠΎΠΉ ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΊΠΈ ΠΈ ΠΌΠΎΠ³ΡƒΡ‚ Π±Ρ‹Ρ‚ΡŒ нСсовмСстимы с автоматичСской Π·Π°ΠΌΠ΅Π½ΠΎΠΉ Ρ†Π²Π΅Ρ‚ΠΎΠ²; -- CSS-ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½Ρ‹Π΅ страницы доступны ΠΏΡ€ΠΈ ``, Π½ΠΎ нСдоступны Π²Π½ΡƒΡ‚Ρ€ΠΈ `` ΠΈ `background-image`. +- `none`, `transparent`, `inherit`, `unset`, and `initial` are not replaced; +- colors in `fill`, `stroke`, and inline `style` attributes are handled most reliably; +- CSS classes and external stylesheets inside the source SVG are not the primary transformation use case; +- gradients, patterns, filters, and `url(#...)` values require separate verification and may be incompatible with automatic color replacement; +- page CSS variables are available with ``, but are not available inside `` and `background-image`. -## ΠšΠ΅ΡˆΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠ΅ +## Caching -Vite, Webpack ΠΈ Next.js target Π²Ρ‹ΠΏΡƒΡΠΊΠ°ΡŽΡ‚ спрайт ΠΎΡ‚Π΄Π΅Π»ΡŒΠ½Ρ‹ΠΌ asset с content hash: +The Vite, Webpack, and Next.js targets emit the sprite as a separate asset with a content hash: ```text /assets/sprite-.svg ``` -Π­Ρ‚ΠΎ Π΄Π°Ρ‘Ρ‚ ΡΠ»Π΅Π΄ΡƒΡŽΡ‰ΠΈΠ΅ свойства: +This provides the following properties: -- SVG ΠΊΠ΅ΡˆΠΈΡ€ΡƒΠ΅Ρ‚ΡΡ нСзависимо ΠΎΡ‚ JavaScript; -- ΠΈΠ·ΠΌΠ΅Π½Π΅Π½ΠΈΠ΅ React-ΠΊΠΎΠ΄Π° Π½Π΅ мСняСт содСрТимоС спрайта; -- ΠΈΠ·ΠΌΠ΅Π½Π΅Π½ΠΈΠ΅ ΠΈΠΊΠΎΠ½ΠΎΠΊ создаёт Π½ΠΎΠ²Ρ‹ΠΉ hash asset; -- ΠΎΠ΄ΠΈΠ½ Ρ„Π°ΠΉΠ» ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ΡΡ всСми экзСмплярами generated-ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Π°; -- SVG path-Π΄Π°Π½Π½Ρ‹Π΅ ΠΎΡ‚ΡΡƒΡ‚ΡΡ‚Π²ΡƒΡŽΡ‚ Π² JavaScript chunks. +- the SVG is cached independently of JavaScript; +- changes to React code do not alter the sprite contents; +- icon changes produce a new hashed asset; +- one file is used by every instance of the generated component; +- SVG path data is absent from JavaScript chunks. -Vite target Π·Π°ΠΏΡ€Π΅Ρ‰Π°Π΅Ρ‚ inline Ρ‡Π΅Ρ€Π΅Π· `?no-inline`. Webpack 5 target ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ Asset Modules Ρ‡Π΅Ρ€Π΅Π· `new URL(..., import.meta.url)`. +The Vite target prevents inlining through `?no-inline`. The Webpack 5 target uses Asset Modules through `new URL(..., import.meta.url)`. ## SpriteViewer -`SpriteViewer` β€” React-ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚ для просмотра generated-спрайтов Π²Π½ΡƒΡ‚Ρ€ΠΈ debug-ΠΌΠ°Ρ€ΡˆΡ€ΡƒΡ‚Π° прилоТСния. +`SpriteViewer` is a React component for viewing generated sprites inside an application's debug route. -Он ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ ΠΎΡ‚Π΄Π΅Π»ΡŒΠ½Ρ‹Π΅ манифСсты ΠΈ ΠΏΠΎΠΊΠ°Π·Ρ‹Π²Π°Π΅Ρ‚: +It uses separate manifests and displays: -- Π³Ρ€ΡƒΠΏΠΏΡ‹ спрайтов; -- список ΠΈ количСство ΠΈΠΊΠΎΠ½ΠΎΠΊ; -- поиск ΠΈ ΡΠΈΡΡ‚Π΅ΠΌΠ½ΡƒΡŽ ΡΠ²Π΅Ρ‚Π»ΡƒΡŽ/Ρ‚Ρ‘ΠΌΠ½ΡƒΡŽ Ρ‚Π΅ΠΌΡƒ; -- модальноС ΠΏΡ€Π΅Π²ΡŒΡŽ с `viewBox` ΠΈ настройкой Ρ†Π²Π΅Ρ‚ΠΎΠ²Ρ‹Ρ… ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½Ρ‹Ρ…; -- ΠΏΡ€ΠΈΠΌΠ΅Ρ€Ρ‹ React, SVG, IMG ΠΈ CSS с ΠΊΠΎΠΏΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠ΅ΠΌ ΠΊΠΎΠ΄Π°. +- sprite groups; +- the icon list and count; +- search and the system light/dark theme; +- a preview modal with the `viewBox` and color variable controls; +- React, SVG, IMG, and CSS examples with code copying. -Production-ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Ρ‹ Π½Π΅ ΠΈΠΌΠΏΠΎΡ€Ρ‚ΠΈΡ€ΡƒΡŽΡ‚ debug-манифСсты. Бпособ ΠΏΠΎΠ΄ΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΡ Viewer зависит ΠΎΡ‚ сборщика: +Production components do not import debug manifests. How you integrate the Viewer depends on the bundler: -- [React + Vite: автоматичСский `import.meta.glob`](docs/ru/react-vite.md#6-Π΄ΠΎΠ±Π°Π²ΡŒΡ‚Π΅-debug-страницу); -- [React + Webpack 5: статичСскиС `import()`](docs/ru/react-webpack.md#6-Π΄ΠΎΠ±Π°Π²ΡŒΡ‚Π΅-debug-страницу); -- [Next.js App Router](docs/ru/next-app.md#5-Π΄ΠΎΠ±Π°Π²ΡŒΡ‚Π΅-spriteviewer); -- [Next.js Pages Router](docs/ru/next-pages.md#5-Π΄ΠΎΠ±Π°Π²ΡŒΡ‚Π΅-spriteviewer). +- [React + Vite: automatic `import.meta.glob`](docs/en/react-vite.md#6-add-a-debug-page); +- [React + Webpack 5: static `import()`](docs/en/react-webpack.md#6-add-a-debug-page); +- [Next.js App Router](docs/en/next-app.md#5-add-spriteviewer); +- [Next.js Pages Router](docs/en/next-pages.md#5-add-spriteviewer). -Viewer ΠΏΠΎΠ΄ΠΊΠ»ΡŽΡ‡Π°Π΅Ρ‚ΡΡ ΠΈΠ· ΠΎΡ‚Π΄Π΅Π»ΡŒΠ½ΠΎΠΉ клиСнтской Ρ‚ΠΎΡ‡ΠΊΠΈ Π²Ρ…ΠΎΠ΄Π° `@gromlab/svg-sprites/react` ΠΈ Π½Π΅ ΠΏΠΎΠΏΠ°Π΄Π°Π΅Ρ‚ Π² production-ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Ρ‹ ΠΈΠΊΠΎΠ½ΠΎΠΊ. +The Viewer is imported from the separate `@gromlab/svg-sprites/react` client entry point and is not included in production icon components. -### Π’Π΅ΠΌΠ° Viewer +### Viewer theme -По ΡƒΠΌΠΎΠ»Ρ‡Π°Π½ΠΈΡŽ `colorTheme="auto"`: Viewer слСдуСт `prefers-color-scheme` ΠΈ Ρ€Π΅Π°Π³ΠΈΡ€ΡƒΠ΅Ρ‚ Π½Π° смСну систСмной Ρ‚Π΅ΠΌΡ‹. Π’Π΅ΠΌΡƒ прилоТСния ΠΌΠΎΠΆΠ½ΠΎ ΠΏΠ΅Ρ€Π΅Π΄Π°Ρ‚ΡŒ явно: +By default, `colorTheme="auto"`: the Viewer follows `prefers-color-scheme` and responds to system theme changes. The application theme can be passed explicitly: ```tsx ``` -ДопустимыС значСния `colorTheme`: `auto`, `light`, `dark`. ΠŸΡ€ΠΈ ΡƒΠΏΡ€Π°Π²Π»Π΅Π½ΠΈΠΈ Ρ‚Π΅ΠΌΠΎΠΉ ΠΈΠ·Π²Π½Π΅ встроСнный ΠΏΠ΅Ρ€Π΅ΠΊΠ»ΡŽΡ‡Π°Ρ‚Π΅Π»ΡŒ скрываСтся. Π§Ρ‚ΠΎΠ±Ρ‹ ΠΎΡΡ‚Π°Π²ΠΈΡ‚ΡŒ Π΅Π³ΠΎ ΠΈ ΠΎΠ±Π½ΠΎΠ²Π»ΡΡ‚ΡŒ Ρ‚Π΅ΠΌΡƒ прилоТСния Ρ‡Π΅Ρ€Π΅Π· Viewer, ΠΏΠ΅Ρ€Π΅Π΄Π°ΠΉΡ‚Π΅ callback: +Valid `colorTheme` values are `auto`, `light`, and `dark`. When the theme is controlled externally, the built-in switch is hidden. To keep it and update the application theme through the Viewer, pass a callback: ```tsx ``` -## ДокумСнтация +## Documentation -- [React + Vite](docs/ru/react-vite.md) -- [React + Webpack 5](docs/ru/react-webpack.md) -- [Next.js App Router](docs/ru/next-app.md) -- [Next.js Pages Router](docs/ru/next-pages.md) -- [Legacy mode](docs/ru/legacy.md) -- [ΠœΠΈΠ³Ρ€Π°Ρ†ΠΈΡ с 0.1.x](docs/ru/migration-1.md) -- [ΠŸΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠ½Ρ‹ΠΉ API](docs/ru/programmatic-api.md) +- [React + Vite](docs/en/react-vite.md) +- [React + Webpack 5](docs/en/react-webpack.md) +- [Next.js App Router](docs/en/next-app.md) +- [Next.js Pages Router](docs/en/next-pages.md) +- [Legacy mode](docs/en/legacy.md) +- [Migrating from 0.1.x](docs/en/migration-1.md) +- [Programmatic API](docs/en/programmatic-api.md) -## ЛицСнзия +## License MIT diff --git a/README_RU.md b/README_RU.md new file mode 100644 index 0000000..8ac80c5 --- /dev/null +++ b/README_RU.md @@ -0,0 +1,398 @@ +# @gromlab/svg-sprites + +[πŸ‡¬πŸ‡§ English](README.md) | πŸ‡·πŸ‡Ί Русский + +![npm](https://img.shields.io/npm/v/@gromlab/svg-sprites) ![license](https://img.shields.io/npm/l/@gromlab/svg-sprites) + +CLI для Π³Π΅Π½Π΅Ρ€Π°Ρ†ΠΈΠΈ SVG-спрайтов ΠΈ Ρ‚ΠΈΠΏΠΈΠ·ΠΈΡ€ΠΎΠ²Π°Π½Π½Ρ‹Ρ… ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚ΠΎΠ² ΠΈΠΊΠΎΠ½ΠΎΠΊ для React ΠΈ Next.js. + +![Preview](https://gromlab.ru/gromov/svg-sprites/media/branch/master/preview-image.png) + +## Навигация + +- [ВозмоТности](#возмоТности) +- [Π’Π°Π±Π»ΠΈΡ†Π° ΠΏΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΊΠΈ](#Ρ‚Π°Π±Π»ΠΈΡ†Π°-ΠΏΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΊΠΈ) +- [ВрСбования](#трСбования) +- [Быстрый старт](#быстрый-старт) + - [React + Vite](docs/ru/react-vite.md) + - [React + Webpack 5](docs/ru/react-webpack.md) + - [Next.js App Router](docs/ru/next-app.md) + - [Next.js Pages Router](docs/ru/next-pages.md) +- [ΠšΠΎΠ½Ρ„ΠΈΠ³ΡƒΡ€Π°Ρ†ΠΈΡ](#конфигурация) + - [React](#react) + - [Next.js](#nextjs) +- [ΠœΠ½ΠΎΠΆΠ΅ΡΡ‚Π²Π΅Π½Π½Ρ‹Π΅ спрайты](#мноТСствСнныС-спрайты) +- [TypeScript](#typescript) +- [Π€ΠΎΡ€ΠΌΠ°Ρ‚Ρ‹ спрайтов](#Ρ„ΠΎΡ€ΠΌΠ°Ρ‚Ρ‹-спрайтов) +- [Бпособы отобраТСния](#способы-отобраТСния) +- [Врансформации](#трансформации) +- [Π£ΠΏΡ€Π°Π²Π»Π΅Π½ΠΈΠ΅ Ρ†Π²Π΅Ρ‚ΠΎΠΌ ΠΈΠΊΠΎΠ½ΠΎΠΊ](#ΡƒΠΏΡ€Π°Π²Π»Π΅Π½ΠΈΠ΅-Ρ†Π²Π΅Ρ‚ΠΎΠΌ-ΠΈΠΊΠΎΠ½ΠΎΠΊ) +- [ΠšΠ΅ΡˆΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠ΅](#ΠΊΠ΅ΡˆΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠ΅) +- [SpriteViewer](#spriteviewer) +- [ΠœΠΈΠ³Ρ€Π°Ρ†ΠΈΡ с 0.1.x](docs/ru/migration-1.md) +- [ДокумСнтация](#докумСнтация) + +## ВозмоТности + +- **AI-agent friendly** β€” Ρ€Π΅ΠΏΠΎΠ·ΠΈΡ‚ΠΎΡ€ΠΈΠΉ содСрТит Π³ΠΎΡ‚ΠΎΠ²Ρ‹ΠΉ skill с Π°ΠΊΡ‚ΡƒΠ°Π»ΡŒΠ½ΠΎΠΉ Π΄ΠΎΠΊΡƒΠΌΠ΅Π½Ρ‚Π°Ρ†ΠΈΠ΅ΠΉ для настройки, ΠΌΠΈΠ³Ρ€Π°Ρ†ΠΈΠΈ ΠΈ диагностики `@gromlab/svg-sprites`. +- **TypeScript-friendly** β€” Ρ‚ΠΈΠΏΠΈΠ·ΠΈΡ€ΠΎΠ²Π°Π½Π½Ρ‹Π΅ React-ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Ρ‹, union-Ρ‚ΠΈΠΏΡ‹ ΠΈ runtime-списки доступных ΠΈΠΊΠΎΠ½ΠΎΠΊ. +- **Чистая гСнСрация** β€” generated-Ρ„Π°ΠΉΠ»Ρ‹ автоматичСски ΠΈΡΠΊΠ»ΡŽΡ‡Π°ΡŽΡ‚ΡΡ ΠΈΠ· Git, спрайт Π½Π΅ Π½ΡƒΠΆΠ½ΠΎ Π²Ρ€ΡƒΡ‡Π½ΡƒΡŽ Ρ€Π°Π·ΠΌΠ΅Ρ‰Π°Ρ‚ΡŒ Π² `public`, Π° Π³Π΅Π½Π΅Ρ€Π°Ρ‚ΠΎΡ€ обновляСт Ρ‚ΠΎΠ»ΡŒΠΊΠΎ ΠΏΡ€ΠΈΠ½Π°Π΄Π»Π΅ΠΆΠ°Ρ‰ΠΈΠ΅ Π΅ΠΌΡƒ Ρ„Π°ΠΉΠ»Ρ‹. +- **ΠžΠ±Ρ‰ΠΈΠ΅ ΠΈΠΊΠΎΠ½ΠΊΠΈ Π±Π΅Π· копирования** β€” SVG ΠΈΠ· локальной ΠΏΠ°ΠΏΠΊΠΈ ΠΈ `inputFiles` ΠΎΠ±ΡŠΠ΅Π΄ΠΈΠ½ΡΡŽΡ‚ΡΡ Π² ΠΎΠ΄ΠΈΠ½ спрайт; ΠΎΠ΄ΠΈΠ½ Ρ„Π°ΠΉΠ» ΠΌΠΎΠΆΠ½ΠΎ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ Π² Π½Π΅ΡΠΊΠΎΠ»ΡŒΠΊΠΈΡ… спрайтах. +- **ВстроСнноС ΠΈΠ½Ρ‚Π΅Ρ€Π°ΠΊΡ‚ΠΈΠ²Π½ΠΎΠ΅ ΠΏΡ€Π΅Π²ΡŒΡŽ** β€” `` ΠΏΠΎΠ΄ΠΊΠ»ΡŽΡ‡Π°Π΅Ρ‚ΡΡ ΠΊΠ°ΠΊ страница прилоТСния ΠΈ ΠΏΠΎΠΊΠ°Π·Ρ‹Π²Π°Π΅Ρ‚ ΠΏΠ΅Ρ€Π΅Π΄Π°Π½Π½Ρ‹Π΅ React- ΠΈ Next.js-спрайты с поиском, настройкой Ρ†Π²Π΅Ρ‚ΠΎΠ² ΠΈ ΠΏΡ€ΠΈΠΌΠ΅Ρ€Π°ΠΌΠΈ использования. +- **НастраиваСмыС трансформации SVG** β€” ΡƒΠ΄Π°Π»Π΅Π½ΠΈΠ΅ `width` ΠΈ `height` с сохранСниСм `viewBox`, Π·Π°ΠΌΠ΅Π½Π° исходных Ρ†Π²Π΅Ρ‚ΠΎΠ² Π½Π° CSS-ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½Ρ‹Π΅ ΠΈ transitions для `fill` ΠΈ `stroke`. +- **ΠžΡ‚Π΄Π΅Π»ΡŒΠ½Ρ‹ΠΉ ΠΊΠ΅ΡˆΠΈΡ€ΡƒΠ΅ΠΌΡ‹ΠΉ SVG asset** β€” SVG path-Π΄Π°Π½Π½Ρ‹Π΅ Π½Π΅ ΠΏΠΎΠΏΠ°Π΄Π°ΡŽΡ‚ Π² JavaScript chunks, Π° сборщик выпускаСт Ρ„Π°ΠΉΠ» с content hash. +- **ΠœΠ½ΠΎΠΆΠ΅ΡΡ‚Π²Π΅Π½Π½Ρ‹Π΅ спрайты** β€” нСзависимыС React- ΠΈ Next.js-ΠΌΠΎΠ΄ΡƒΠ»ΠΈ со своими ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Π°ΠΌΠΈ, Ρ‚ΠΈΠΏΠ°ΠΌΠΈ ΠΈ SVG assets. +- **Server-first Next.js** β€” generated-ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Ρ‹ Ρ€Π°Π±ΠΎΡ‚Π°ΡŽΡ‚ Π² Server Components, SSR ΠΈ SSG Π±Π΅Π· Π΄ΠΈΡ€Π΅ΠΊΡ‚ΠΈΠ²Ρ‹ `'use client'`. +- **Π€ΠΎΡ€ΠΌΠ°Ρ‚Ρ‹ ΠΏΠΎΠ΄ Ρ€Π°Π·Π½Ρ‹Π΅ сцСнарии** β€” React ΠΈ Next.js ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΡŽΡ‚ `stack`, legacy-Ρ€Π΅ΠΆΠΈΠΌ Ρ‚Π°ΠΊΠΆΠ΅ ΠΏΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΈΠ²Π°Π΅Ρ‚ `symbol` для ΡΡƒΡ‰Π΅ΡΡ‚Π²ΡƒΡŽΡ‰ΠΈΡ… ΠΈΠ½Ρ‚Π΅Π³Ρ€Π°Ρ†ΠΈΠΉ. + +## Π’Π°Π±Π»ΠΈΡ†Π° ΠΏΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΊΠΈ + +| Π‘Ρ€Π΅Π΄Π° | ΠšΠ»ΡŽΡ‡ ΠΌΠΎΠ΄Π° API | Бтатус | +|---|---|---| +| React + Vite | `react@vite` | Π“ΠΎΡ‚ΠΎΠ²ΠΎ | +| React + Webpack 5 | `react@webpack` | Π“ΠΎΡ‚ΠΎΠ²ΠΎ | +| Next.js 16.2+ App Router + Turbopack | `next@app/turbopack` | Π“ΠΎΡ‚ΠΎΠ²ΠΎ | +| Next.js 13.4+ App Router + Webpack 5 | `next@app/webpack` | Π“ΠΎΡ‚ΠΎΠ²ΠΎ | +| Next.js 16.2+ Pages Router + Turbopack | `next@pages/turbopack` | Π“ΠΎΡ‚ΠΎΠ²ΠΎ | +| Next.js 12.2+ Pages Router + Webpack 5 | `next@pages/webpack` | Π“ΠΎΡ‚ΠΎΠ²ΠΎ | +| Vue | β€” | Π‘ΠΊΠΎΡ€ΠΎ | +| Standalone | β€” | Π‘ΠΊΠΎΡ€ΠΎ | + +## ВрСбования + +- Node.js 18 ΠΈΠ»ΠΈ Π½ΠΎΠ²Π΅Π΅; +- ΠΏΠ°ΠΊΠ΅Ρ‚ распространяСтся Ρ‚ΠΎΠ»ΡŒΠΊΠΎ ΠΊΠ°ΠΊ ESM ΠΈ ΠΏΠΎΠ΄ΠΊΠ»ΡŽΡ‡Π°Π΅Ρ‚ΡΡ Ρ‡Π΅Ρ€Π΅Π· `import`; +- React 18 ΠΈΠ»ΠΈ 19 трСбуСтся Ρ‚ΠΎΠ»ΡŒΠΊΠΎ для generated-ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚ΠΎΠ² ΠΈ Ρ‚ΠΎΡ‡ΠΊΠΈ Π²Ρ…ΠΎΠ΄Π° `@gromlab/svg-sprites/react`; +- для Ρ‚ΠΈΠΏΠΈΠ·Π°Ρ†ΠΈΠΈ subpath exports ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠΉΡ‚Π΅ TypeScript 5+ с `moduleResolution: "bundler"`, `"node16"` ΠΈΠ»ΠΈ `"nodenext"`. + +## Быстрый старт + +Для быстрого старта Π²ΠΎΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠΉΡ‚Π΅ΡΡŒ инструкциСй для вашСго стСка: + +- [React + Vite](docs/ru/react-vite.md) +- [React + Webpack 5](docs/ru/react-webpack.md) +- [Next.js App Router](docs/ru/next-app.md) +- [Next.js Pages Router](docs/ru/next-pages.md) + +## ΠšΠΎΠ½Ρ„ΠΈΠ³ΡƒΡ€Π°Ρ†ΠΈΡ + +### React + +```ts +import { defineReactSpriteConfig } from '@gromlab/svg-sprites' + +export default defineReactSpriteConfig({ + name: 'file-manager', + description: 'Иконки Ρ„Π°ΠΉΠ»ΠΎΠ²ΠΎΠ³ΠΎ ΠΌΠ΅Π½Π΅Π΄ΠΆΠ΅Ρ€Π°', + inputFolder: './icons', + inputFiles: [ + '../../shared/icons/check.svg', + ], + transform: { + removeSize: true, + replaceColors: true, + addTransition: true, + }, + generatedNotice: true, +}) +``` + +| ΠžΠΏΡ†ΠΈΡ | Π’ΠΈΠΏ | По ΡƒΠΌΠΎΠ»Ρ‡Π°Π½ΠΈΡŽ | НазначСниС | +|---|---|---|---| +| `name` | `string` | Имя ΠΏΠ°ΠΏΠΊΠΈ | Имя спрайта, ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Π° ΠΈ ΠΏΡƒΠ±Π»ΠΈΡ‡Π½Ρ‹Ρ… Ρ‚ΠΈΠΏΠΎΠ² | +| `description` | `string` | НСт | ОписаниС для Ρ‚ΠΈΠΏΠΎΠ² ΠΈ debug-манифСста | +| `inputFolder` | `string` | `./icons` | Папка с исходными SVG ΠΎΡ‚Π½ΠΎΡΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎ ΠΊΠΎΠ½Ρ„ΠΈΠ³Π° | +| `inputFiles` | `string[]` | `[]` | Π”ΠΎΠΏΠΎΠ»Π½ΠΈΡ‚Π΅Π»ΡŒΠ½Ρ‹Π΅ SVG-Ρ„Π°ΠΉΠ»Ρ‹ ΠΎΡ‚Π½ΠΎΡΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎ ΠΊΠΎΠ½Ρ„ΠΈΠ³Π° | +| `transform` | `TransformOptions` | ВсС Π²ΠΊΠ»ΡŽΡ‡Π΅Π½Ρ‹ | [Настройки трансформации](#трансформации) исходных SVG | +| `generatedNotice` | `boolean` | `true` | ПолноС Π»ΠΈΠ±ΠΎ ΠΊΠΎΡ€ΠΎΡ‚ΠΊΠΎΠ΅ ΠΏΡ€Π΅Π΄ΡƒΠΏΡ€Π΅ΠΆΠ΄Π΅Π½ΠΈΠ΅ Π² generated-Ρ„Π°ΠΉΠ»Π°Ρ… | + +`inputFolder` ΠΈ `inputFiles` ΠΎΠ±ΡŠΠ΅Π΄ΠΈΠ½ΡΡŽΡ‚ΡΡ Π² ΠΎΠ΄ΠΈΠ½ спрайт, поэтому ΠΎΠ΄ΠΈΠ½ SVG-Ρ„Π°ΠΉΠ» ΠΌΠΎΠΆΠ½ΠΎ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ Π² Π½Π΅ΡΠΊΠΎΠ»ΡŒΠΊΠΈΡ… спрайтах Π±Π΅Π· копирования. Если нСявной ΠΏΠ°ΠΏΠΊΠΈ `./icons` Π½Π΅Ρ‚, Π½ΠΎ `inputFiles` Π·Π°ΠΏΠΎΠ»Π½Π΅Π½, гСнСрация продолТаСтся Ρ‚ΠΎΠ»ΡŒΠΊΠΎ ΠΏΠΎ списку. Π―Π²Π½ΠΎ указанная ΠΎΡ‚ΡΡƒΡ‚ΡΡ‚Π²ΡƒΡŽΡ‰Π°Ρ ΠΏΠ°ΠΏΠΊΠ° считаСтся ошибкой. ΠžΠ΄ΠΈΠ½Π°ΠΊΠΎΠ²Ρ‹Π΅ ΠΏΡƒΡ‚ΠΈ Π΄Π΅Π΄ΡƒΠΏΠ»ΠΈΡ†ΠΈΡ€ΡƒΡŽΡ‚ΡΡ, Π° Ρ€Π°Π·Π½Ρ‹Π΅ Ρ„Π°ΠΉΠ»Ρ‹ с ΠΎΠ΄ΠΈΠ½Π°ΠΊΠΎΠ²Ρ‹ΠΌ ΠΈΠΌΠ΅Π½Π΅ΠΌ ΠΈΠΊΠΎΠ½ΠΊΠΈ ΡΡ‡ΠΈΡ‚Π°ΡŽΡ‚ΡΡ ошибкой. + +`name` записываСтся Π² kebab-case ΠΈ Π΄ΠΎΠ»ΠΆΠ½ΠΎ Π½Π°Ρ‡ΠΈΠ½Π°Ρ‚ΡŒΡΡ с латинской Π±ΡƒΠΊΠ²Ρ‹. React ΠΈ Next.js presets ΡΠΎΠ·Π΄Π°ΡŽΡ‚ Ρ„ΠΎΡ€ΠΌΠ°Ρ‚ `stack`. + +### Next.js + +Next.js ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ Ρ‚ΠΎΡ‚ ΠΆΠ΅ `svg-sprite.config.ts` ΠΈ Π½Π°Π±ΠΎΡ€ ΠΎΠΏΡ†ΠΈΠΉ. Для Ρ‚ΠΈΠΏΠΈΠ·Π°Ρ†ΠΈΠΈ ΠΌΠΎΠΆΠ½ΠΎ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ ΠΎΡ‚Π΄Π΅Π»ΡŒΠ½Ρ‹ΠΉ Ρ…Π΅Π»ΠΏΠ΅Ρ€: + +```ts +import { defineNextSpriteConfig } from '@gromlab/svg-sprites' + +export default defineNextSpriteConfig({ + name: 'file-manager', + description: 'Иконки Ρ„Π°ΠΉΠ»ΠΎΠ²ΠΎΠ³ΠΎ ΠΌΠ΅Π½Π΅Π΄ΠΆΠ΅Ρ€Π°', + inputFolder: './icons', +}) +``` + +Π ΠΎΡƒΡ‚Π΅Ρ€ ΠΈ сборщик Π²Ρ‹Π±ΠΈΡ€Π°ΡŽΡ‚ΡΡ Ρ‡Π΅Ρ€Π΅Π· mode key, поэтому ΠΏΠ΅Ρ€Π΅ΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅ ΠΌΠ΅ΠΆΠ΄Ρƒ Turbopack ΠΈ Webpack всСгда явно ΠΎΡ‚Ρ€Π°ΠΆΠ΅Π½ΠΎ Π² ΠΊΠΎΠΌΠ°Π½Π΄Π΅ Π³Π΅Π½Π΅Ρ€Π°Ρ†ΠΈΠΈ. + +## ΠœΠ½ΠΎΠΆΠ΅ΡΡ‚Π²Π΅Π½Π½Ρ‹Π΅ спрайты + +ΠŸΡ€ΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅ ΠΌΠΎΠΆΠ΅Ρ‚ ΡΠΎΠ΄Π΅Ρ€ΠΆΠ°Ρ‚ΡŒ нСсколько нСзависимых спрайтов с Ρ€Π°Π·Π½ΠΎΠΉ ΠΎΠ±Π»Π°ΡΡ‚ΡŒΡŽ использования: + +**ΠŸΡ€ΠΎΠ±Π»Π΅ΠΌΠ°:** ΠΎΠ΄ΠΈΠ½ Π³Π»ΠΎΠ±Π°Π»ΡŒΠ½Ρ‹ΠΉ спрайт Π·Π°Π³Ρ€ΡƒΠΆΠ°Π΅Ρ‚ ΠΈΠΊΠΎΠ½ΠΊΠΈ, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ Ρ‚Π΅ΠΊΡƒΡ‰Π΅ΠΌΡƒ экрану Π½Π΅ Π½ΡƒΠΆΠ½Ρ‹. + +**РСшСниС:** ΠΎΠ±Ρ‰ΠΈΠ΅ ΠΈΠΊΠΎΠ½ΠΊΠΈ Ρ…Ρ€Π°Π½ΠΈΡ‚ΡŒ глобально, Π° Π½Π°Π±ΠΎΡ€Ρ‹ страниц ΠΈ ΠΊΡ€ΡƒΠΏΠ½Ρ‹Ρ… ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚ΠΎΠ² β€” Π² ΠΎΡ‚Π΄Π΅Π»ΡŒΠ½Ρ‹Ρ… спрайтах, Π·Π°Π³Ρ€ΡƒΠΆΠ°Π΅ΠΌΡ‹Ρ… вмСстС с Π½ΠΈΠΌΠΈ. + +```text +global β†’ GlobalIcon β†’ ΠΎΠ±Ρ‰ΠΈΠ΅ ΠΈΠΊΠΎΠ½ΠΊΠΈ прилоТСния +analytics-page β†’ AnalyticsPageIcon β†’ ΠΈΠΊΠΎΠ½ΠΊΠΈ ΠΎΡ‚Π΄Π΅Π»ΡŒΠ½ΠΎΠΉ страницы +file-manager β†’ FileManagerIcon β†’ ΠΈΠΊΠΎΠ½ΠΊΠΈ ΠΊΡ€ΡƒΠΏΠ½ΠΎΠ³ΠΎ ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Π° +``` + +- **Π“Π»ΠΎΠ±Π°Π»ΡŒΠ½Ρ‹ΠΉ спрайт** содСрТит нСбольшиС ΠΎΠ±Ρ‰ΠΈΠ΅ ΠΈΠΊΠΎΠ½ΠΊΠΈ, ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅ΠΌΡ‹Π΅ Π² Ρ€Π°Π·Π½Ρ‹Ρ… частях прилоТСния: Π½Π°Π²ΠΈΠ³Π°Ρ†ΠΈΡŽ, состояния ΠΈ Π±Π°Π·ΠΎΠ²Ρ‹Π΅ дСйствия. +- **Π‘ΠΏΡ€Π°ΠΉΡ‚ страницы** загруТаСтся вмСстС с ΠΊΠΎΠ½ΠΊΡ€Π΅Ρ‚Π½Ρ‹ΠΌ Ρ€Π°Π·Π΄Π΅Π»ΠΎΠΌ ΠΈ Π½Π΅ ΡƒΠ²Π΅Π»ΠΈΡ‡ΠΈΠ²Π°Π΅Ρ‚ ΠΎΠ±Ρ‰ΠΈΠΉ спрайт ΠΈΠΊΠΎΠ½ΠΊΠ°ΠΌΠΈ, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ большС Π½ΠΈΠ³Π΄Π΅ Π½Π΅ Π½ΡƒΠΆΠ½Ρ‹. +- **Π‘ΠΏΡ€Π°ΠΉΡ‚ ΠΊΡ€ΡƒΠΏΠ½ΠΎΠ³ΠΎ ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Π°** инкапсулируСт собствСнный Π½Π°Π±ΠΎΡ€ ΠΈΠΊΠΎΠ½ΠΎΠΊ слоТного UI-модуля, Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€ Ρ„Π°ΠΉΠ»ΠΎΠ²ΠΎΠ³ΠΎ ΠΌΠ΅Π½Π΅Π΄ΠΆΠ΅Ρ€Π° ΠΈΠ»ΠΈ Ρ€Π΅Π΄Π°ΠΊΡ‚ΠΎΡ€Π°. + +КаТдая Π³Ρ€ΡƒΠΏΠΏΠ° ΠΏΠΎΠ»ΡƒΡ‡Π°Π΅Ρ‚: + +- собствСнный SVG asset; +- собствСнный Ρ‚ΠΈΠΏΠΈΠ·ΠΈΡ€ΠΎΠ²Π°Π½Π½Ρ‹ΠΉ ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚; +- ΠΎΡ‚Π΄Π΅Π»ΡŒΠ½Ρ‹ΠΉ список ΠΈΠΌΡ‘Π½ ΠΈΠΊΠΎΠ½ΠΎΠΊ; +- ΠΎΡ‚Π΄Π΅Π»ΡŒΠ½Ρ‹ΠΉ debug-манифСст; +- нСзависимый cache lifecycle. + + +## TypeScript + +Главная Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎΡΡ‚ΡŒ TypeScript API β€” Π°Π²Ρ‚ΠΎΠ΄ΠΎΠΏΠΎΠ»Π½Π΅Π½ΠΈΠ΅ ΠΈΠΌΡ‘Π½ ΠΈΠΊΠΎΠ½ΠΎΠΊ нСпосрСдствСнно Π² prop `icon`: + +```tsx + +// ↑ Ρ€Π΅Π΄Π°ΠΊΡ‚ΠΎΡ€ ΠΏΡ€Π΅Π΄Π»Π°Π³Π°Π΅Ρ‚ всС ΠΈΠΊΠΎΠ½ΠΊΠΈ спрайта +``` + +ИмСна SVG-Ρ„Π°ΠΉΠ»ΠΎΠ² становятся допустимыми значСниями `icon`. ΠžΠΏΠ΅Ρ‡Π°Ρ‚ΠΊΠ° ΠΈΠ»ΠΈ нСизвСстноС имя сразу становятся ошибкой TypeScript: + +```tsx + // ошибка TypeScript +``` + +Для ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠ½ΠΎΠ³ΠΎ доступа generated-ΠΌΠΎΠ΄ΡƒΠ»ΡŒ экспортируСт readonly-массив всСх доступных ΠΈΠΊΠΎΠ½ΠΎΠΊ ΠΊΠΎΠ½ΠΊΡ€Π΅Ρ‚Π½ΠΎΠ³ΠΎ спрайта: + +```ts +import { fileManagerIconNames } from './svg-sprite' + +// readonly ['check', 'folder', ...] +``` + +Π­Ρ‚ΠΎΡ‚ список ΠΌΠΎΠΆΠ½ΠΎ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ Π² собствСнных ΠΊΠ°Ρ‚Π°Π»ΠΎΠ³Π°Ρ…, select-ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Π°Ρ…, тСстах ΠΈ Π΄Ρ€ΡƒΠ³ΠΈΡ… runtime-сцСнариях. Из Π½Π΅Π³ΠΎ Ρ‚Π°ΠΊΠΆΠ΅ выводится union-Ρ‚ΠΈΠΏ `FileManagerIconName`. + +ИмСна Ρ„Π°ΠΉΠ»ΠΎΠ² с ΠΏΡ€ΠΎΠ±Π΅Π»Π°ΠΌΠΈ ΠΈ Π΄Ρ€ΡƒΠ³ΠΈΠΌΠΈ нСбСзопасными для SVG ID символами ΠΎΡΡ‚Π°ΡŽΡ‚ΡΡ Ρ‡Π°ΡΡ‚ΡŒΡŽ ΠΏΡƒΠ±Π»ΠΈΡ‡Π½ΠΎΠ³ΠΎ TypeScript API. Для Π²Π½ΡƒΡ‚Ρ€Π΅Π½Π½Π΅Π³ΠΎ `` Π³Π΅Π½Π΅Ρ€Π°Ρ‚ΠΎΡ€ создаёт ΡΡ‚Π°Π±ΠΈΠ»ΡŒΠ½Ρ‹ΠΉ hash ID. + +```text +folder open.svg β†’ icon="folder open" β†’ id="icon-" +``` + +Для Ρ‚Π°ΠΊΠΈΡ… ΠΈΠΌΡ‘Π½ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠΉΡ‚Π΅ generated-ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚ ΠΈΠ»ΠΈ `id` ΠΈΠ· debug-манифСста. Π ΡƒΡ‡Π½Ρ‹Π΅ ΠΏΡ€ΠΈΠΌΠ΅Ρ€Ρ‹ Π½ΠΈΠΆΠ΅ с `#<имя>` подходят Ρ‚ΠΎΠ»ΡŒΠΊΠΎ для ΠΈΠΌΡ‘Π½, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ ΡƒΠΆΠ΅ ΡΠ²Π»ΡΡŽΡ‚ΡΡ бСзопасными SVG ID. + +## Π€ΠΎΡ€ΠΌΠ°Ρ‚Ρ‹ спрайтов + +`stack` β€” Π±ΠΎΠ»Π΅Π΅ соврСмСнный Ρ„ΠΎΡ€ΠΌΠ°Ρ‚, поэтому ΠΎΠ½ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ΡΡ ΠΏΠΎ ΡƒΠΌΠΎΠ»Ρ‡Π°Π½ΠΈΡŽ. Иконки ΠΌΠΎΠΆΠ½ΠΎ ΠΎΡ‚ΠΎΠ±Ρ€Π°ΠΆΠ°Ρ‚ΡŒ Ρ‡Π΅Ρ€Π΅Π· ``, `` ΠΈ CSS `background-image`. + +`symbol` сохраняСтся для совмСстимости с ΡΡƒΡ‰Π΅ΡΡ‚Π²ΡƒΡŽΡ‰ΠΈΠΌΠΈ интСграциями ΠΈ ΠΏΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΈΠ²Π°Π΅Ρ‚ ΠΎΡ‚ΠΎΠ±Ρ€Π°ΠΆΠ΅Π½ΠΈΠ΅ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ Ρ‡Π΅Ρ€Π΅Π· ``. + +## Бпособы отобраТСния + +### React-ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚ β€” рСкомСндуСтся + +Generated-ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚ прСдоставляСт Ρ‚ΠΈΠΏΠΈΠ·Π°Ρ†ΠΈΡŽ, Π°Π²Ρ‚ΠΎΠ΄ΠΎΠΏΠΎΠ»Π½Π΅Π½ΠΈΠ΅ ΠΈΠΌΡ‘Π½ ΠΈΠΊΠΎΠ½ΠΎΠΊ ΠΈ сам Ρ„ΠΎΡ€ΠΌΠΈΡ€ΡƒΠ΅Ρ‚ URL SVG asset. + +```tsx + +``` + +Π§Π΅Ρ€Π΅Π· `color` ΠΈ `--icon-color-N` доступны ΠΎΠ΄Π½ΠΎΡ†Π²Π΅Ρ‚Π½Ρ‹Π΅ ΠΈ ΠΌΠ½ΠΎΠ³ΠΎΡ†Π²Π΅Ρ‚Π½Ρ‹Π΅ ΠΈΠΊΠΎΠ½ΠΊΠΈ. + +### Π‘Π°ΠΌΠΎΡΡ‚ΠΎΡΡ‚Π΅Π»ΡŒΠ½ΠΎ Ρ‡Π΅Ρ€Π΅Π· `` + +Π₯ΠΎΡ€ΠΎΡˆΠΈΠΉ Π½ΠΈΠ·ΠΊΠΎΡƒΡ€ΠΎΠ²Π½Π΅Π²Ρ‹ΠΉ способ с ΠΏΠΎΠ»Π½Ρ‹ΠΌ ΡƒΠΏΡ€Π°Π²Π»Π΅Π½ΠΈΠ΅ΠΌ Ρ€Π°Π·ΠΌΠ΅Ρ€Π°ΠΌΠΈ ΠΈ Ρ†Π²Π΅Ρ‚Π°ΠΌΠΈ. React-ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚ ΠΏΠΎΠ΄ ΠΊΠ°ΠΏΠΎΡ‚ΠΎΠΌ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ ΠΈΠΌΠ΅Π½Π½ΠΎ Π΅Π³ΠΎ. + +Бпособ получСния `spriteUrl` зависит ΠΎΡ‚ сборщика. + +**Vite:** + +```tsx +import spriteUrl from './svg-sprite/generated/sprite.svg?no-inline' +``` + +**Webpack 5:** + +```tsx +const spriteUrl = new URL( + './svg-sprite/generated/sprite.svg', + import.meta.url, +).href +``` + +**Next.js с Webpack 5 ΠΈΠ»ΠΈ Turbopack:** + +```tsx +const spriteUrl = new URL( + './svg-sprite/generated/sprite.svg', + import.meta.url, +).href +``` + +ПослС получСния URL ΠΈΠΊΠΎΠ½ΠΊΠ° отобраТаСтся ΠΎΠ΄ΠΈΠ½Π°ΠΊΠΎΠ²ΠΎ: + +```tsx + + + +``` + +Vite, Webpack 5 ΠΈ Next.js сами Π·Π°ΠΌΠ΅Π½ΡΡŽΡ‚ исходный ΠΏΡƒΡ‚ΡŒ Π½Π° ΠΈΡ‚ΠΎΠ³ΠΎΠ²Ρ‹ΠΉ URL asset с hash. + +### Π§Π΅Ρ€Π΅Π· `` β€” ΠΌΠ΅Π½Π΅Π΅ эффСктивно + +```tsx +Π“ΠΎΡ‚ΠΎΠ²ΠΎ +``` + +SVG загруТаСтся ΠΊΠ°ΠΊ ΠΈΠ·ΠΎΠ»ΠΈΡ€ΠΎΠ²Π°Π½Π½ΠΎΠ΅ ΠΈΠ·ΠΎΠ±Ρ€Π°ΠΆΠ΅Π½ΠΈΠ΅: ΠΈΠ·ΠΌΠ΅Π½ΠΈΡ‚ΡŒ Π΅Π³ΠΎ Ρ†Π²Π΅Ρ‚Π° Ρ‡Π΅Ρ€Π΅Π· `color` ΠΈΠ»ΠΈ `--icon-color-N` нСльзя. + +### Π§Π΅Ρ€Π΅Π· CSS `background-image` β€” ΠΌΠ΅Π½Π΅Π΅ эффСктивно + +```css +.icon { + background: url('./svg-sprite/generated/sprite.svg#check') center / contain no-repeat; +} +``` + +Как ΠΈ ``, этот способ Π½Π΅ позволяСт ΡƒΠΏΡ€Π°Π²Π»ΡΡ‚ΡŒ Π²Π½ΡƒΡ‚Ρ€Π΅Π½Π½ΠΈΠΌΠΈ Ρ†Π²Π΅Ρ‚Π°ΠΌΠΈ SVG. ΠŸΡƒΡ‚ΡŒ указываСтся ΠΎΡ‚Π½ΠΎΡΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎ CSS-Ρ„Π°ΠΉΠ»Π°, Π° Vite/Webpack замСняСт Π΅Π³ΠΎ Π½Π° ΠΈΡ‚ΠΎΠ³ΠΎΠ²Ρ‹ΠΉ URL с hash ΠΏΡ€ΠΈ сборкС. + +### Π§Π΅Ρ€Π΅Π· CSS mask β€” ΠΌΠ΅Π½Π΅Π΅ эффСктивно + +```css +.icon { + background-color: currentColor; + mask: url('./svg-sprite/generated/sprite.svg#check') center / contain no-repeat; +} +``` + +Mask оставляСт Ρ‚ΠΎΠ»ΡŒΠΊΠΎ силуэт ΠΈ ΠΎΠΊΡ€Π°ΡˆΠΈΠ²Π°Π΅Ρ‚ Π΅Π³ΠΎ ΠΎΠ΄Π½ΠΈΠΌ Ρ†Π²Π΅Ρ‚ΠΎΠΌ. Π˜ΡΡ…ΠΎΠ΄Π½Ρ‹Π΅ Ρ†Π²Π΅Ρ‚Π°, gradients ΠΈ различия ΠΌΠ΅ΠΆΠ΄Ρƒ `fill` ΠΈ `stroke` Ρ‚Π΅Ρ€ΡΡŽΡ‚ΡΡ. + +## Врансформации + +ВсС трансформации Π²ΠΊΠ»ΡŽΡ‡Π΅Π½Ρ‹ ΠΏΠΎ ΡƒΠΌΠΎΠ»Ρ‡Π°Π½ΠΈΡŽ ΠΈ Π½Π°ΡΡ‚Ρ€Π°ΠΈΠ²Π°ΡŽΡ‚ΡΡ нСзависимо Ρ‡Π΅Ρ€Π΅Π· `transform`. + +| ΠžΠΏΡ†ΠΈΡ | По ΡƒΠΌΠΎΠ»Ρ‡Π°Π½ΠΈΡŽ | Π§Ρ‚ΠΎ Π΄Π΅Π»Π°Π΅Ρ‚ | +|---|---|---| +| `removeSize` | `true` | УдаляСт `width` ΠΈ `height` с ΠΊΠΎΡ€Π½Π΅Π²ΠΎΠ³ΠΎ ``, сохраняя ΡΡƒΡ‰Π΅ΡΡ‚Π²ΡƒΡŽΡ‰ΠΈΠΉ `viewBox`. Π Π°Π·ΠΌΠ΅Ρ€ ΠΈΠΊΠΎΠ½ΠΊΠΈ послС этого задаётся снаруТи. | +| `replaceColors` | `true` | ЗамСняСт Ρ†Π²Π΅Ρ‚Π° `fill` ΠΈ `stroke` Π½Π° `--icon-color-N`. Для ΠΎΠ΄Π½ΠΎΡ†Π²Π΅Ρ‚Π½ΠΎΠΉ ΠΈΠΊΠΎΠ½ΠΊΠΈ fallback становится `currentColor`, для ΠΌΠ½ΠΎΠ³ΠΎΡ†Π²Π΅Ρ‚Π½ΠΎΠΉ ΡΠΎΡ…Ρ€Π°Π½ΡΡŽΡ‚ΡΡ исходныС Ρ†Π²Π΅Ρ‚Π°. | +| `addTransition` | `true` | ДобавляСт `style="transition:fill 0.3s,stroke 0.3s;"` нСпосрСдствСнно Ρ†Π²Π΅Ρ‚Π½Ρ‹ΠΌ элСмСнтам SVG. Π‘ΡƒΡ‰Π΅ΡΡ‚Π²ΡƒΡŽΡ‰ΠΈΠΉ `transition` Π½Π΅ пСрСзаписываСтся. | + +Π§Ρ‚ΠΎΠ±Ρ‹ ΠΎΡ‚ΠΊΠ»ΡŽΡ‡ΠΈΡ‚ΡŒ ΠΏΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΠΎΠ²Π°Π½ΠΈΠ΅, ΠΏΠ΅Ρ€Π΅Π΄Π°ΠΉΡ‚Π΅ для ΡΠΎΠΎΡ‚Π²Π΅Ρ‚ΡΡ‚Π²ΡƒΡŽΡ‰Π΅ΠΉ ΠΎΠΏΡ†ΠΈΠΈ `false`. ΠŸΠΎΠ΄Ρ€ΠΎΠ±Π½Π΅Π΅ ΠΎ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Π΅ `replaceColors` β€” Π² Ρ€Π°Π·Π΄Π΅Π»Π΅ [Β«Π£ΠΏΡ€Π°Π²Π»Π΅Π½ΠΈΠ΅ Ρ†Π²Π΅Ρ‚ΠΎΠΌ ΠΈΠΊΠΎΠ½ΠΎΠΊΒ»](#ΡƒΠΏΡ€Π°Π²Π»Π΅Π½ΠΈΠ΅-Ρ†Π²Π΅Ρ‚ΠΎΠΌ-ΠΈΠΊΠΎΠ½ΠΎΠΊ). + +## Π£ΠΏΡ€Π°Π²Π»Π΅Π½ΠΈΠ΅ Ρ†Π²Π΅Ρ‚ΠΎΠΌ ΠΈΠΊΠΎΠ½ΠΎΠΊ + +ΠŸΡ€ΠΈ Π²ΠΊΠ»ΡŽΡ‡Ρ‘Π½Π½ΠΎΠΉ Π·Π°ΠΌΠ΅Π½Π΅ Ρ†Π²Π΅Ρ‚ΠΎΠ² Π³Π΅Π½Π΅Ρ€Π°Ρ‚ΠΎΡ€ Π°Π½Π°Π»ΠΈΠ·ΠΈΡ€ΡƒΠ΅Ρ‚ `fill` ΠΈ `stroke` ΠΈ ΠΏΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΡƒΠ΅Ρ‚ ΠΈΡ… Π² CSS custom properties. + +### ΠœΠΎΠ½ΠΎΡ…Ρ€ΠΎΠΌΠ½Ρ‹Π΅ ΠΈΠΊΠΎΠ½ΠΊΠΈ + +Если Π½Π°ΠΉΠ΄Π΅Π½ ΠΎΠ΄ΠΈΠ½ Ρ†Π²Π΅Ρ‚, fallback замСняСтся Π½Π° `currentColor`: + +```svg +stroke="var(--icon-color-1, currentColor)" +``` + +Π¦Π²Π΅Ρ‚ΠΎΠΌ управляСт CSS-свойство `color` внСшнСго `` ΠΈΠ»ΠΈ Π΅Π³ΠΎ родитСля. + +### ΠœΠ½ΠΎΠ³ΠΎΡ†Π²Π΅Ρ‚Π½Ρ‹Π΅ ΠΈΠΊΠΎΠ½ΠΊΠΈ + +ΠšΠ°ΠΆΠ΄Ρ‹ΠΉ ΡƒΠ½ΠΈΠΊΠ°Π»ΡŒΠ½Ρ‹ΠΉ Ρ†Π²Π΅Ρ‚ ΠΏΠΎΠ»ΡƒΡ‡Π°Π΅Ρ‚ ΠΎΡ‚Π΄Π΅Π»ΡŒΠ½ΡƒΡŽ ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½ΡƒΡŽ с исходным fallback: + +```svg +fill="var(--icon-color-1, #798198)" +fill="var(--icon-color-2, #ffffff)" +fill="var(--icon-color-3, #129d9d)" +``` + +Π‘Ρ‚Ρ€Π°Π½ΠΈΡ†Π° ΠΌΠΎΠΆΠ΅Ρ‚ Π·Π°ΠΌΠ΅Π½ΠΈΡ‚ΡŒ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΡ‹Π΅ Ρ†Π²Π΅Ρ‚Π°: + +```css +.icon { + --icon-color-1: #4b5563; + --icon-color-3: #14b8a6; +} +``` + +### ΠžΠ³Ρ€Π°Π½ΠΈΡ‡Π΅Π½ΠΈΡ Ρ†Π²Π΅Ρ‚ΠΎΠ² + +- `none`, `transparent`, `inherit`, `unset` ΠΈ `initial` Π½Π΅ Π·Π°ΠΌΠ΅Π½ΡΡŽΡ‚ΡΡ; +- Ρ†Π²Π΅Ρ‚Π° Π² Π°Ρ‚Ρ€ΠΈΠ±ΡƒΡ‚Π°Ρ… `fill`, `stroke` ΠΈ inline `style` ΠΎΠ±Ρ€Π°Π±Π°Ρ‚Ρ‹Π²Π°ΡŽΡ‚ΡΡ Π½Π°Π΄Ρ‘ΠΆΠ½Π΅Π΅ всСго; +- CSS-классы ΠΈ внСшниС stylesheets Π²Π½ΡƒΡ‚Ρ€ΠΈ исходного SVG Π½Π΅ ΡΠ²Π»ΡΡŽΡ‚ΡΡ основным сцСнариСм трансформации; +- gradients, patterns, filters ΠΈ значСния `url(#...)` Ρ‚Ρ€Π΅Π±ΡƒΡŽΡ‚ ΠΎΡ‚Π΄Π΅Π»ΡŒΠ½ΠΎΠΉ ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΊΠΈ ΠΈ ΠΌΠΎΠ³ΡƒΡ‚ Π±Ρ‹Ρ‚ΡŒ нСсовмСстимы с автоматичСской Π·Π°ΠΌΠ΅Π½ΠΎΠΉ Ρ†Π²Π΅Ρ‚ΠΎΠ²; +- CSS-ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½Ρ‹Π΅ страницы доступны ΠΏΡ€ΠΈ ``, Π½ΠΎ нСдоступны Π²Π½ΡƒΡ‚Ρ€ΠΈ `` ΠΈ `background-image`. + +## ΠšΠ΅ΡˆΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠ΅ + +Vite, Webpack ΠΈ Next.js target Π²Ρ‹ΠΏΡƒΡΠΊΠ°ΡŽΡ‚ спрайт ΠΎΡ‚Π΄Π΅Π»ΡŒΠ½Ρ‹ΠΌ asset с content hash: + +```text +/assets/sprite-.svg +``` + +Π­Ρ‚ΠΎ Π΄Π°Ρ‘Ρ‚ ΡΠ»Π΅Π΄ΡƒΡŽΡ‰ΠΈΠ΅ свойства: + +- SVG ΠΊΠ΅ΡˆΠΈΡ€ΡƒΠ΅Ρ‚ΡΡ нСзависимо ΠΎΡ‚ JavaScript; +- ΠΈΠ·ΠΌΠ΅Π½Π΅Π½ΠΈΠ΅ React-ΠΊΠΎΠ΄Π° Π½Π΅ мСняСт содСрТимоС спрайта; +- ΠΈΠ·ΠΌΠ΅Π½Π΅Π½ΠΈΠ΅ ΠΈΠΊΠΎΠ½ΠΎΠΊ создаёт Π½ΠΎΠ²Ρ‹ΠΉ hash asset; +- ΠΎΠ΄ΠΈΠ½ Ρ„Π°ΠΉΠ» ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ΡΡ всСми экзСмплярами generated-ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Π°; +- SVG path-Π΄Π°Π½Π½Ρ‹Π΅ ΠΎΡ‚ΡΡƒΡ‚ΡΡ‚Π²ΡƒΡŽΡ‚ Π² JavaScript chunks. + +Vite target Π·Π°ΠΏΡ€Π΅Ρ‰Π°Π΅Ρ‚ inline Ρ‡Π΅Ρ€Π΅Π· `?no-inline`. Webpack 5 target ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ Asset Modules Ρ‡Π΅Ρ€Π΅Π· `new URL(..., import.meta.url)`. + +## SpriteViewer + +`SpriteViewer` β€” React-ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚ для просмотра generated-спрайтов Π²Π½ΡƒΡ‚Ρ€ΠΈ debug-ΠΌΠ°Ρ€ΡˆΡ€ΡƒΡ‚Π° прилоТСния. + +Он ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ ΠΎΡ‚Π΄Π΅Π»ΡŒΠ½Ρ‹Π΅ манифСсты ΠΈ ΠΏΠΎΠΊΠ°Π·Ρ‹Π²Π°Π΅Ρ‚: + +- Π³Ρ€ΡƒΠΏΠΏΡ‹ спрайтов; +- список ΠΈ количСство ΠΈΠΊΠΎΠ½ΠΎΠΊ; +- поиск ΠΈ ΡΠΈΡΡ‚Π΅ΠΌΠ½ΡƒΡŽ ΡΠ²Π΅Ρ‚Π»ΡƒΡŽ/Ρ‚Ρ‘ΠΌΠ½ΡƒΡŽ Ρ‚Π΅ΠΌΡƒ; +- модальноС ΠΏΡ€Π΅Π²ΡŒΡŽ с `viewBox` ΠΈ настройкой Ρ†Π²Π΅Ρ‚ΠΎΠ²Ρ‹Ρ… ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½Ρ‹Ρ…; +- ΠΏΡ€ΠΈΠΌΠ΅Ρ€Ρ‹ React, SVG, IMG ΠΈ CSS с ΠΊΠΎΠΏΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠ΅ΠΌ ΠΊΠΎΠ΄Π°. + +Production-ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Ρ‹ Π½Π΅ ΠΈΠΌΠΏΠΎΡ€Ρ‚ΠΈΡ€ΡƒΡŽΡ‚ debug-манифСсты. Бпособ ΠΏΠΎΠ΄ΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΡ Viewer зависит ΠΎΡ‚ сборщика: + +- [React + Vite: автоматичСский `import.meta.glob`](docs/ru/react-vite.md#6-Π΄ΠΎΠ±Π°Π²ΡŒΡ‚Π΅-debug-страницу); +- [React + Webpack 5: статичСскиС `import()`](docs/ru/react-webpack.md#6-Π΄ΠΎΠ±Π°Π²ΡŒΡ‚Π΅-debug-страницу); +- [Next.js App Router](docs/ru/next-app.md#5-Π΄ΠΎΠ±Π°Π²ΡŒΡ‚Π΅-spriteviewer); +- [Next.js Pages Router](docs/ru/next-pages.md#5-Π΄ΠΎΠ±Π°Π²ΡŒΡ‚Π΅-spriteviewer). + +Viewer ΠΏΠΎΠ΄ΠΊΠ»ΡŽΡ‡Π°Π΅Ρ‚ΡΡ ΠΈΠ· ΠΎΡ‚Π΄Π΅Π»ΡŒΠ½ΠΎΠΉ клиСнтской Ρ‚ΠΎΡ‡ΠΊΠΈ Π²Ρ…ΠΎΠ΄Π° `@gromlab/svg-sprites/react` ΠΈ Π½Π΅ ΠΏΠΎΠΏΠ°Π΄Π°Π΅Ρ‚ Π² production-ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Ρ‹ ΠΈΠΊΠΎΠ½ΠΎΠΊ. + +### Π’Π΅ΠΌΠ° Viewer + +По ΡƒΠΌΠΎΠ»Ρ‡Π°Π½ΠΈΡŽ `colorTheme="auto"`: Viewer слСдуСт `prefers-color-scheme` ΠΈ Ρ€Π΅Π°Π³ΠΈΡ€ΡƒΠ΅Ρ‚ Π½Π° смСну систСмной Ρ‚Π΅ΠΌΡ‹. Π’Π΅ΠΌΡƒ прилоТСния ΠΌΠΎΠΆΠ½ΠΎ ΠΏΠ΅Ρ€Π΅Π΄Π°Ρ‚ΡŒ явно: + +```tsx + +``` + +ДопустимыС значСния `colorTheme`: `auto`, `light`, `dark`. ΠŸΡ€ΠΈ ΡƒΠΏΡ€Π°Π²Π»Π΅Π½ΠΈΠΈ Ρ‚Π΅ΠΌΠΎΠΉ ΠΈΠ·Π²Π½Π΅ встроСнный ΠΏΠ΅Ρ€Π΅ΠΊΠ»ΡŽΡ‡Π°Ρ‚Π΅Π»ΡŒ скрываСтся. Π§Ρ‚ΠΎΠ±Ρ‹ ΠΎΡΡ‚Π°Π²ΠΈΡ‚ΡŒ Π΅Π³ΠΎ ΠΈ ΠΎΠ±Π½ΠΎΠ²Π»ΡΡ‚ΡŒ Ρ‚Π΅ΠΌΡƒ прилоТСния Ρ‡Π΅Ρ€Π΅Π· Viewer, ΠΏΠ΅Ρ€Π΅Π΄Π°ΠΉΡ‚Π΅ callback: + +```tsx + +``` + +## ДокумСнтация + +- [React + Vite](docs/ru/react-vite.md) +- [React + Webpack 5](docs/ru/react-webpack.md) +- [Next.js App Router](docs/ru/next-app.md) +- [Next.js Pages Router](docs/ru/next-pages.md) +- [Legacy mode](docs/ru/legacy.md) +- [ΠœΠΈΠ³Ρ€Π°Ρ†ΠΈΡ с 0.1.x](docs/ru/migration-1.md) +- [ΠŸΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠ½Ρ‹ΠΉ API](docs/ru/programmatic-api.md) + +## ЛицСнзия + +MIT diff --git a/docs/en/legacy.md b/docs/en/legacy.md new file mode 100644 index 0000000..10b6ea1 --- /dev/null +++ b/docs/en/legacy.md @@ -0,0 +1,102 @@ +# Legacy mode + +[← Back to home](../../README.md) + +A quick guide to generating centralized SVG sprites in `symbol` and `stack` formats, with an optional HTML preview. + +## 1. Install the package + +```bash +npm install @gromlab/svg-sprites +``` + +## 2. Prepare the icons and config + +```text +project/ +β”œβ”€β”€ src/assets/icons/ +β”‚ β”œβ”€β”€ check.svg +β”‚ └── folder.svg +└── svg-sprites.config.ts +``` + +```ts +// svg-sprites.config.ts +import { defineLegacyConfig } from '@gromlab/svg-sprites' + +export default defineLegacyConfig({ + output: 'public/sprites', + preview: true, + sprites: [ + { + name: 'icons', + input: 'src/assets/icons', + format: 'symbol', + }, + ], +}) +``` + +## 3. Run generation + +```bash +npx svg-sprites --mode legacy . +``` + +Result: + +```text +public/sprites/ +β”œβ”€β”€ icons.sprite.svg +└── preview.html +``` + +With `preview: false`, the HTML file is not created. For the `stack` format, specify `format: 'stack'`. + +## 4. Use the symbol sprite + +```html + + + +``` + +## 5. Add a package script + +```json +{ + "scripts": { + "sprites": "svg-sprites --mode legacy .", + "prebuild": "npm run sprites" + } +} +``` + +## Multiple sprites + +Add multiple entries to `sprites`: + +```ts +sprites: [ + { + name: 'icons', + input: 'src/assets/icons', + format: 'symbol', + }, + { + name: 'logos', + input: 'src/assets/logos', + format: 'stack', + }, +] +``` + +All output files and the shared `preview.html` will be written to `output`. + +## Troubleshooting + +- Config not found: make sure `svg-sprites.config.ts` is located in the specified root directory. +- No icons: check `sprites[].input` and the `.svg` extension. +- Preview not needed: set `preview: false`. + +For programmatic use, see [`generateLegacy`](programmatic-api.md#generatelegacy). diff --git a/docs/en/migration-1.md b/docs/en/migration-1.md new file mode 100644 index 0000000..b53b915 --- /dev/null +++ b/docs/en/migration-1.md @@ -0,0 +1,96 @@ +# Migrating from 0.1.x to 1.0 + +[← Back to home](../../README.md) + +Version 1.0 separates local generation for React and Next.js from the centralized legacy mode. The old config cannot be mixed with the new API in a single CLI invocation. + +## CLI + +The CLI now always requires an explicit `--mode` and a path to the configuration directory: + +```text +svg-sprites +β†’ svg-sprites --mode +``` + +Choose a mode based on your environment: + +| Environment | Mode | +|---|---| +| 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` | +| Centralized legacy setup | `legacy` | + +## React and Next.js + +Instead of a root-level `svg-sprites.config.ts`, create a local `svg-sprite.config.ts` next to the icon set: + +```ts +import { defineNextSpriteConfig } from '@gromlab/svg-sprites' + +export default defineNextSpriteConfig({ + name: 'global', + inputFolder: './icons', +}) +``` + +For regular React, use `defineReactSpriteConfig`. A folder and an explicit list of shared SVG files can be combined using `inputFolder` and `inputFiles`. + +The old `publicPath` and `react` options are no longer needed. The generated module is created next to the config and adds its own `.gitignore`, while Vite, Webpack, or Next.js emits the SVG as a separate asset with a content hash. + +The `` component is replaced by a component whose name is derived from `name`: + +```tsx + +``` + +To browse the icons, add `` as a debug page in the application. A separate `preview.html` is available only in legacy mode. + +## Legacy mode + +If you need to preserve the centralized structure, rename the helper and the format fields: + +```ts +import { defineLegacyConfig } from '@gromlab/svg-sprites' + +export default defineLegacyConfig({ + output: 'public/sprites', + preview: true, + sprites: [ + { + name: 'icons', + input: 'src/assets/icons', + format: 'stack', + }, + ], +}) +``` + +- `defineConfig` has been replaced with `defineLegacyConfig`; +- `sprites[].mode` has been renamed to `sprites[].format`; +- `generate` has been replaced with `generateLegacy`; +- `loadConfig` has been replaced with `loadLegacyConfig`; +- `publicPath` and generation of the old shared React component have been removed. + +Run: + +```bash +svg-sprites --mode legacy . +``` + +## Programmatic API + +The package is distributed as ESM only. Replace `require()` with `import`. + +`compileSpriteContent` now returns `Promise` so that the public declarations do not require `@types/node` to be installed. In Node.js, the actual result is compatible with APIs that accept `Uint8Array`. + +## After migration + +1. Remove the old generated files and rules that ignored the entire directory containing the source icons. +2. Add an explicit generation command before `dev`, `build`, and `typecheck`. +3. Run generation and type checking. +4. Check all icons and color variables using `SpriteViewer` or the legacy `preview.html`. diff --git a/docs/en/next-app.md b/docs/en/next-app.md new file mode 100644 index 0000000..1e334ce --- /dev/null +++ b/docs/en/next-app.md @@ -0,0 +1,102 @@ +# Next.js App Router + +[← Back to home](../../README.md) + +Two explicit modes are supported: + +| Bundler | Mode key | Next.js version | +|---|---|---| +| Turbopack | `next@app/turbopack` | 16.2+ | +| Webpack 5 | `next@app/webpack` | 13.4+ | + +## 1. Install the package + +```bash +npm install @gromlab/svg-sprites +``` + +## 2. Create a sprite module + +```text +src/ui/file-manager/svg-sprite/ +β”œβ”€β”€ icons/ +β”‚ β”œβ”€β”€ check.svg +β”‚ └── folder.svg +└── svg-sprite.config.ts +``` + +```ts +// src/ui/file-manager/svg-sprite/svg-sprite.config.ts +import { defineNextSpriteConfig } from '@gromlab/svg-sprites' + +export default defineNextSpriteConfig({ + name: 'file-manager', + description: 'File manager icons', +}) +``` + +## 3. Add generation + +For Turbopack: + +```json +{ + "scripts": { + "sprite:file-manager": "svg-sprites --mode next@app/turbopack src/ui/file-manager/svg-sprite", + "predev": "npm run sprite:file-manager", + "prebuild": "npm run sprite:file-manager" + } +} +``` + +For Webpack, replace the mode key with `next@app/webpack`. In Next 13–15, Webpack is used with the regular `next build` command; in Next 16, use `next build --webpack`. + +## 4. Use it in a Server Component + +The generated component does not contain `'use client'`, so it can be imported directly into `page.tsx` or `layout.tsx`: + +```tsx +import { FileManagerIcon } from '@/ui/file-manager/svg-sprite' + +export default function Page() { + return ( +
+ +
+ ) +} +``` + +Next.js emits a separate SVG asset with a content hash. The same generated code is used during SSR and in the browser, with no URL mismatch. + +## 5. Add SpriteViewer + +The viewer is interactive, so it requires a separate Client Component boundary: + +```tsx +'use client' + +import { SpriteViewer } from '@gromlab/svg-sprites/react' + +const sources = [ + () => import('@/ui/file-manager/svg-sprite/manifest'), +] + +export default function SpritesPage() { + return +} +``` + +## Verify the bundler + +```bash +# Turbopack +npx next build --turbopack + +# Webpack 5 +npx next build --webpack +``` + +For Next 13–15 with Webpack, use `npx next build` without the flag. + +The Next.js command and the generator mode key must target the same bundler. diff --git a/docs/en/next-pages.md b/docs/en/next-pages.md new file mode 100644 index 0000000..0de0136 --- /dev/null +++ b/docs/en/next-pages.md @@ -0,0 +1,96 @@ +# Next.js Pages Router + +[← Back to home](../../README.md) + +Two explicit modes are supported: + +| Bundler | Mode key | Next.js version | +|---|---|---| +| Turbopack | `next@pages/turbopack` | 16.2+ | +| Webpack 5 | `next@pages/webpack` | 12.2+ | + +Next.js 12.2 requires React 18. + +## 1. Install the package + +```bash +npm install @gromlab/svg-sprites +``` + +## 2. Create a sprite module + +```text +src/ui/file-manager/svg-sprite/ +β”œβ”€β”€ icons/ +β”‚ β”œβ”€β”€ check.svg +β”‚ └── folder.svg +└── svg-sprite.config.ts +``` + +```ts +// src/ui/file-manager/svg-sprite/svg-sprite.config.ts +import { defineNextSpriteConfig } from '@gromlab/svg-sprites' + +export default defineNextSpriteConfig({ + name: 'file-manager', + description: 'File manager icons', +}) +``` + +## 3. Add generation + +```json +{ + "scripts": { + "sprite:file-manager": "svg-sprites --mode next@pages/webpack src/ui/file-manager/svg-sprite", + "predev": "npm run sprite:file-manager", + "prebuild": "npm run sprite:file-manager" + } +} +``` + +For Next.js 16.2 with Turbopack, replace the mode key with `next@pages/turbopack`. + +## 4. Use it on a page + +```tsx +import { FileManagerIcon } from '@/ui/file-manager/svg-sprite' + +export default function FilesPage() { + return +} + +export function getServerSideProps() { + return { props: {} } +} +``` + +The component works the same way with SSR, SSG, and client-side navigation. Next.js emits a separate SVG asset with a content hash. + +## 5. Add SpriteViewer + +```tsx +import { SpriteViewer } from '@gromlab/svg-sprites/react' + +const sources = [ + () => import('@/ui/file-manager/svg-sprite/manifest'), +] + +export default function SpritesPage() { + return +} +``` + +## Verify the bundler + +```bash +# Turbopack +npx next build --turbopack + +# Webpack 5 +npx next build --webpack +``` + +For Next 12–15 with Webpack, use `npx next build` without the flag. + +The Next.js command and the generator mode key must target the same bundler. diff --git a/docs/en/programmatic-api.md b/docs/en/programmatic-api.md new file mode 100644 index 0000000..7a4d44b --- /dev/null +++ b/docs/en/programmatic-api.md @@ -0,0 +1,203 @@ +# Programmatic API + +[← Back to home](../../README.md) + +The package provides a main Node.js entry point and a separate React runtime entry point. Both are distributed as ESM only and must be loaded with `import`. + +To resolve `@gromlab/svg-sprites/react` in TypeScript, use `moduleResolution: "bundler"`, `"node16"`, or `"nodenext"`. + +## Main entry point + +```ts +import { + defineNextSpriteConfig, + defineReactSpriteConfig, + generateNextSprite, + generateReactSprite, +} from '@gromlab/svg-sprites' +``` + +The main entry point does not import React and can be used in CLIs, build scripts, and Node.js tools. + +## `generateReactSprite` + +```ts +import { generateReactSprite } from '@gromlab/svg-sprites' + +const result = await generateReactSprite( + 'src/ui/file-manager/svg-sprite', + 'vite', +) +``` + +The second argument is required: + +```ts +type ReactAssetTarget = 'vite' | 'webpack' +``` + +Result: + +```ts +type ReactSpriteGenerationResult = { + name: string + rootDir: string + generatedDir: string + spritePath: string + manifestPath: string + iconCount: number + target: 'vite' | 'webpack' +} +``` + +```ts +console.log(result.name) +console.log(result.iconCount) +console.log(result.spritePath) +console.log(result.manifestPath) +``` + +The function loads `svg-sprite.config.ts` from the specified root, compiles the SVG files, and safely updates managed files. + +## `generateNextSprite` + +```ts +import { generateNextSprite } from '@gromlab/svg-sprites' + +const result = await generateNextSprite( + 'src/ui/file-manager/svg-sprite', + { + router: 'app', + bundler: 'turbopack', + }, +) +``` + +Available values: + +```ts +type NextSpriteGenerationOptions = { + router: 'app' | 'pages' + bundler: 'turbopack' | 'webpack' +} +``` + +The result also contains the selected `router`, `bundler`, and the full target in the form `next@app/turbopack`. + +## `defineReactSpriteConfig` + +```ts +import { defineReactSpriteConfig } from '@gromlab/svg-sprites' + +export default defineReactSpriteConfig({ + name: 'file-manager', + description: 'File manager icons', + inputFolder: './icons', + inputFiles: [ + '../../shared/icons/check.svg', + ], + transform: { + removeSize: true, + replaceColors: true, + addTransition: true, + }, + generatedNotice: true, +}) +``` + +`inputFolder` and `inputFiles` are combined. The helper returns the configuration without runtime transformations and provides TypeScript autocomplete. + +## `defineNextSpriteConfig` + +```ts +import { defineNextSpriteConfig } from '@gromlab/svg-sprites' + +export default defineNextSpriteConfig({ + name: 'file-manager', + description: 'File manager icons', + inputFolder: './icons', +}) +``` + +Next.js uses the same configuration contract as the React presets. + +## `generateLegacy` + +```ts +import { generateLegacy } from '@gromlab/svg-sprites' + +const results = await generateLegacy({ + output: 'public/sprites', + preview: false, + sprites: [ + { + name: 'icons', + input: 'src/assets/icons', + format: 'symbol', + }, + ], +}) +``` + +Returns an array: + +```ts +type SpriteResult = { + name: string + format: 'symbol' | 'stack' + spritePath: string + iconCount: number +} +``` + +For details, see [Legacy mode](legacy.md). + +## Low-level functions + +The main entry point also exports: + +```ts +import { + compileSprite, + compileSpriteContent, + createShapeTransform, + generatePreview, + loadLegacyConfig, + loadReactSpriteConfig, + resolveSpriteEntry, + resolveSprites, +} from '@gromlab/svg-sprites' +``` + +These functions are intended for custom orchestration built on top of the existing compiler and writer. For standard usage, prefer `generateReactSprite` and `generateLegacy`. + +## React runtime entry point + +```tsx +import { SpriteViewer } from '@gromlab/svg-sprites/react' +``` + +Types: + +```ts +import type { + SpriteManifest, + SpriteManifestColor, + SpriteManifestIcon, + SpriteManifestLoader, + SpriteManifestModule, + SpriteViewerColorTheme, + SpriteViewerProps, + SpriteViewerSource, + SpriteViewerSources, +} from '@gromlab/svg-sprites/react' +``` + +The React entry point contains `'use client'` and is intended for debug tools. Generated production components are imported from the application's local sprite modules, not from the package's React entry point. + +`SpriteViewerProps.colorTheme` accepts `auto | light | dark`. The default is `auto`, which follows `prefers-color-scheme`; to synchronize it with the application theme, pass the computed `light` or `dark` value. + +## Related guides + +- [React + Vite](react-vite.md) +- [React + Webpack 5](react-webpack.md) diff --git a/docs/en/react-vite.md b/docs/en/react-vite.md new file mode 100644 index 0000000..1e37cc4 --- /dev/null +++ b/docs/en/react-vite.md @@ -0,0 +1,116 @@ +# React + Vite + +[← Back to home](../../README.md) + +A quick guide to installing and using SVG sprites in a React and Vite project. + +The result is a typed React component and a separate cacheable SVG asset. + +## 1. Install the package + +```bash +npm install @gromlab/svg-sprites +``` + +## 2. Create the sprite directory + +```text +src/ui/file-manager/svg-sprite/ +β”œβ”€β”€ icons/ +β”‚ β”œβ”€β”€ check.svg +β”‚ └── folder.svg +└── svg-sprite.config.ts +``` + +Place the source SVG files in `icons/`. + +## 3. Add the configuration + +```ts +// src/ui/file-manager/svg-sprite/svg-sprite.config.ts +import { defineReactSpriteConfig } from '@gromlab/svg-sprites' + +export default defineReactSpriteConfig({ + name: 'file-manager', + description: 'File manager icons', +}) +``` + +By default, SVG files are loaded from `./icons`. You can add shared icons from other directories through `inputFiles`: the directory and file list are combined into a single sprite. + +The complete list of options is available under [Configuration β†’ React](../../README.md#react). + +## 4. Add generation to package.json + +```json +{ + "scripts": { + "sprite:file-manager": "svg-sprites --mode react@vite src/ui/file-manager/svg-sprite", + "predev": "npm run sprite:file-manager", + "prebuild": "npm run sprite:file-manager", + "pretypecheck": "npm run sprite:file-manager" + } +} +``` + +Generated files are excluded from Git, so generation must run before `dev`, `build`, and `typecheck`. + +First run: + +```bash +npm run sprite:file-manager +``` + +## 5. Use the component + +The name `file-manager` is converted to `FileManagerIcon`: + +```tsx +import { FileManagerIcon } from './svg-sprite' + +export const OpenFolderButton = () => ( + +) +``` + +TypeScript checks the `icon` value against the file names: + +```tsx + // valid + // TypeScript error +``` + +Types, display methods, and color controls are described in the [main documentation](../../README.md#display-methods). + +Vite emits the sprite as a separate file named like `assets/sprite-.svg`. SVG path data is not included in JavaScript. + +## 6. Add a debug page + +After integrating the icons, you can display all React sprites with `SpriteViewer`: + +```tsx +import { SpriteViewer } from '@gromlab/svg-sprites/react' +import type { SpriteManifestModule } from '@gromlab/svg-sprites/react' + +const sources = import.meta.glob( + '/src/**/svg-sprite/manifest.ts', +) + +export const IconsDebugPage = () => ( + +) +``` + +Vite automatically finds the generated `manifest.ts` for each React sprite. The `import.meta.glob` pattern must be a string literal, and generation must run before Vite starts. + +Only include the Viewer on a debug route or in an internal tool. + +## Troubleshooting + +- Missing `index.ts`: run `npm run sprite:file-manager`. +- The Viewer cannot find the sprite: check the glob path and make sure `manifest.ts` exists. +- `Refusing to overwrite a user file` error: there is a user file at a generated path. +- The icon does not change color: use `color` or `--icon-color-N`. diff --git a/docs/en/react-webpack.md b/docs/en/react-webpack.md new file mode 100644 index 0000000..15383db --- /dev/null +++ b/docs/en/react-webpack.md @@ -0,0 +1,118 @@ +# React + Webpack 5 + +[← Back to home](../../README.md) + +A quick guide to installing and using SVG sprites in a React and Webpack 5 project. + +The result is a typed React component and a separate SVG asset emitted through Webpack Asset Modules. + +## 1. Install the package + +```bash +npm install @gromlab/svg-sprites +``` + +## 2. Create the sprite directory + +```text +src/ui/file-manager/svg-sprite/ +β”œβ”€β”€ icons/ +β”‚ β”œβ”€β”€ check.svg +β”‚ └── folder.svg +└── svg-sprite.config.ts +``` + +Place the source SVG files in `icons/`. + +## 3. Add the configuration + +```ts +// src/ui/file-manager/svg-sprite/svg-sprite.config.ts +import { defineReactSpriteConfig } from '@gromlab/svg-sprites' + +export default defineReactSpriteConfig({ + name: 'file-manager', + description: 'File manager icons', +}) +``` + +By default, SVG files are loaded from `./icons`. You can add shared icons from other directories through `inputFiles`: the directory and file list are combined into a single sprite. + +The complete list of options is available under [Configuration β†’ React](../../README.md#react). + +## 4. Add generation to package.json + +```json +{ + "scripts": { + "sprite:file-manager": "svg-sprites --mode react@webpack src/ui/file-manager/svg-sprite", + "predev": "npm run sprite:file-manager", + "prebuild": "npm run sprite:file-manager", + "pretypecheck": "npm run sprite:file-manager" + } +} +``` + +Generated files are excluded from Git, so generation must run before `dev`, `build`, and `typecheck`. + +First run: + +```bash +npm run sprite:file-manager +``` + +## 5. Use the component + +```tsx +import { FileManagerIcon } from './svg-sprite' + +export const OpenFolderButton = () => ( + +) +``` + +TypeScript checks the `icon` value against the file names: + +```tsx + // valid + // TypeScript error +``` + +Types, display methods, and color controls are described in the [main documentation](../../README.md#display-methods). + +Webpack processes the generated `new URL('./sprite.svg', import.meta.url)` through Asset Modules and emits a separate SVG asset. + +If the project already uses a custom SVG loader, make sure it does not intercept the generated `sprite.svg` instead of Asset Modules. + +## 6. Add a debug page + +Webpack does not support Vite's `import.meta.glob` API, so provide static loaders: + +```tsx +import { SpriteViewer } from '@gromlab/svg-sprites/react' + +const sources = [ + () => import('./ui/file-manager/svg-sprite/manifest'), + () => import('./ui/navigation/svg-sprite/manifest'), +] + +export const IconsDebugPage = () => ( + +) +``` + +The paths in `import()` must be string literals. Webpack creates chunks for the manifests and associates them with the SVG assets. + +Only include the Viewer on a debug route or in an internal tool. + +## Troubleshooting + +- Missing `index.ts`: run `npm run sprite:file-manager`. +- The Viewer does not load the sprite: check the path in `import()` and make sure `manifest.ts` exists. +- Incorrect asset URL: check `output.publicPath`. +- Another loader intercepts the SVG: exclude the generated sprite from the incompatible rule. + +For Next.js, use the separate mode keys described in the [App Router](next-app.md) and [Pages Router](next-pages.md) guides. diff --git a/docs/ru/legacy.md b/docs/ru/legacy.md index 5efd0cf..3d722b8 100644 --- a/docs/ru/legacy.md +++ b/docs/ru/legacy.md @@ -1,6 +1,6 @@ # Legacy mode -[← Главная](../../README.md) +[← Главная](../../README_RU.md) ΠšΡ€Π°Ρ‚ΠΊΠ°Ρ инструкция ΠΏΠΎ Π³Π΅Π½Π΅Ρ€Π°Ρ†ΠΈΠΈ Ρ†Π΅Π½Ρ‚Ρ€Π°Π»ΠΈΠ·ΠΎΠ²Π°Π½Π½Ρ‹Ρ… SVG-спрайтов Ρ„ΠΎΡ€ΠΌΠ°Ρ‚ΠΎΠ² `symbol` ΠΈ `stack` с optional HTML preview. diff --git a/docs/ru/migration-1.md b/docs/ru/migration-1.md index a41d3d9..39b15d8 100644 --- a/docs/ru/migration-1.md +++ b/docs/ru/migration-1.md @@ -1,6 +1,6 @@ # ΠœΠΈΠ³Ρ€Π°Ρ†ΠΈΡ с 0.1.x Π½Π° 1.0 -[← Главная](../../README.md) +[← Главная](../../README_RU.md) ВСрсия 1.0 раздСляСт Π»ΠΎΠΊΠ°Π»ΡŒΠ½ΡƒΡŽ Π³Π΅Π½Π΅Ρ€Π°Ρ†ΠΈΡŽ для React ΠΈ Next.js ΠΈ Ρ†Π΅Π½Ρ‚Ρ€Π°Π»ΠΈΠ·ΠΎΠ²Π°Π½Π½Ρ‹ΠΉ legacy-Ρ€Π΅ΠΆΠΈΠΌ. Π‘Ρ‚Π°Ρ€Ρ‹ΠΉ config нСльзя ΡΠΌΠ΅ΡˆΠΈΠ²Π°Ρ‚ΡŒ с Π½ΠΎΠ²Ρ‹ΠΌ API Π² ΠΎΠ΄Π½ΠΎΠΌ Π²Ρ‹Π·ΠΎΠ²Π΅ CLI. diff --git a/docs/ru/next-app.md b/docs/ru/next-app.md index 593d02d..06049c6 100644 --- a/docs/ru/next-app.md +++ b/docs/ru/next-app.md @@ -1,6 +1,6 @@ # Next.js App Router -[← Главная](../../README.md) +[← Главная](../../README_RU.md) ΠŸΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΈΠ²Π°ΡŽΡ‚ΡΡ Π΄Π²Π° явных Ρ€Π΅ΠΆΠΈΠΌΠ°: diff --git a/docs/ru/next-pages.md b/docs/ru/next-pages.md index d52750b..926f0ef 100644 --- a/docs/ru/next-pages.md +++ b/docs/ru/next-pages.md @@ -1,6 +1,6 @@ # Next.js Pages Router -[← Главная](../../README.md) +[← Главная](../../README_RU.md) ΠŸΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΈΠ²Π°ΡŽΡ‚ΡΡ Π΄Π²Π° явных Ρ€Π΅ΠΆΠΈΠΌΠ°: diff --git a/docs/ru/programmatic-api.md b/docs/ru/programmatic-api.md index 510b5fc..999cd01 100644 --- a/docs/ru/programmatic-api.md +++ b/docs/ru/programmatic-api.md @@ -1,6 +1,6 @@ # ΠŸΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠ½Ρ‹ΠΉ API -[← Главная](../../README.md) +[← Главная](../../README_RU.md) ΠŸΠ°ΠΊΠ΅Ρ‚ прСдоставляСт ΠΎΡΠ½ΠΎΠ²Π½ΡƒΡŽ Node.js Ρ‚ΠΎΡ‡ΠΊΡƒ Π²Ρ…ΠΎΠ΄Π° ΠΈ ΠΎΡ‚Π΄Π΅Π»ΡŒΠ½Ρ‹ΠΉ React runtime entry. ОбС Ρ‚ΠΎΡ‡ΠΊΠΈ Ρ€Π°ΡΠΏΡ€ΠΎΡΡ‚Ρ€Π°Π½ΡΡŽΡ‚ΡΡ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ ΠΊΠ°ΠΊ ESM ΠΈ ΠΏΠΎΠ΄ΠΊΠ»ΡŽΡ‡Π°ΡŽΡ‚ΡΡ Ρ‡Π΅Ρ€Π΅Π· `import`. diff --git a/docs/ru/react-vite.md b/docs/ru/react-vite.md index 1aa146e..2ae3b39 100644 --- a/docs/ru/react-vite.md +++ b/docs/ru/react-vite.md @@ -1,6 +1,6 @@ # React + Vite -[← Главная](../../README.md) +[← Главная](../../README_RU.md) ΠšΡ€Π°Ρ‚ΠΊΠ°Ρ инструкция ΠΏΠΎ установкС ΠΈ использованию SVG-спрайтов Π² ΠΏΡ€ΠΎΠ΅ΠΊΡ‚Π΅ Π½Π° React ΠΈ Vite. @@ -38,7 +38,7 @@ export default defineReactSpriteConfig({ По ΡƒΠΌΠΎΠ»Ρ‡Π°Π½ΠΈΡŽ SVG бСрутся ΠΈΠ· `./icons`. ΠžΠ±Ρ‰ΠΈΠ΅ ΠΈΠΊΠΎΠ½ΠΊΠΈ ΠΈΠ· Π΄Ρ€ΡƒΠ³ΠΈΡ… ΠΏΠ°ΠΏΠΎΠΊ ΠΌΠΎΠΆΠ½ΠΎ Π΄ΠΎΠ±Π°Π²ΠΈΡ‚ΡŒ Ρ‡Π΅Ρ€Π΅Π· `inputFiles`: ΠΏΠ°ΠΏΠΊΠ° ΠΈ список ΠΎΠ±ΡŠΠ΅Π΄ΠΈΠ½ΡΡŽΡ‚ΡΡ Π² ΠΎΠ΄ΠΈΠ½ спрайт. -ΠŸΠΎΠ»Π½Ρ‹ΠΉ список ΠΎΠΏΡ†ΠΈΠΉ находится Π² Ρ€Π°Π·Π΄Π΅Π»Π΅ [ΠšΠΎΠ½Ρ„ΠΈΠ³ΡƒΡ€Π°Ρ†ΠΈΡ β†’ React](../../README.md#react). +ΠŸΠΎΠ»Π½Ρ‹ΠΉ список ΠΎΠΏΡ†ΠΈΠΉ находится Π² Ρ€Π°Π·Π΄Π΅Π»Π΅ [ΠšΠΎΠ½Ρ„ΠΈΠ³ΡƒΡ€Π°Ρ†ΠΈΡ β†’ React](../../README_RU.md#react). ## 4. Π”ΠΎΠ±Π°Π²ΡŒΡ‚Π΅ Π³Π΅Π½Π΅Ρ€Π°Ρ†ΠΈΡŽ Π² package.json @@ -83,7 +83,7 @@ export const OpenFolderButton = () => ( // ошибка TypeScript ``` -Π’ΠΈΠΏΡ‹, способы отобраТСния ΠΈ ΡƒΠΏΡ€Π°Π²Π»Π΅Π½ΠΈΠ΅ Ρ†Π²Π΅Ρ‚Π°ΠΌΠΈ описаны Π² [основной Π΄ΠΎΠΊΡƒΠΌΠ΅Π½Ρ‚Π°Ρ†ΠΈΠΈ](../../README.md#способы-отобраТСния). +Π’ΠΈΠΏΡ‹, способы отобраТСния ΠΈ ΡƒΠΏΡ€Π°Π²Π»Π΅Π½ΠΈΠ΅ Ρ†Π²Π΅Ρ‚Π°ΠΌΠΈ описаны Π² [основной Π΄ΠΎΠΊΡƒΠΌΠ΅Π½Ρ‚Π°Ρ†ΠΈΠΈ](../../README_RU.md#способы-отобраТСния). Vite выпустит спрайт ΠΎΡ‚Π΄Π΅Π»ΡŒΠ½Ρ‹ΠΌ Ρ„Π°ΠΉΠ»ΠΎΠΌ Π²ΠΈΠ΄Π° `assets/sprite-.svg`. SVG path-Π΄Π°Π½Π½Ρ‹Π΅ Π½Π΅ ΠΏΠΎΠΏΠ°Π΄ΡƒΡ‚ Π² JavaScript. diff --git a/docs/ru/react-webpack.md b/docs/ru/react-webpack.md index bd4ccd9..2a3c015 100644 --- a/docs/ru/react-webpack.md +++ b/docs/ru/react-webpack.md @@ -1,6 +1,6 @@ # React + Webpack 5 -[← Главная](../../README.md) +[← Главная](../../README_RU.md) ΠšΡ€Π°Ρ‚ΠΊΠ°Ρ инструкция ΠΏΠΎ установкС ΠΈ использованию SVG-спрайтов Π² ΠΏΡ€ΠΎΠ΅ΠΊΡ‚Π΅ Π½Π° React ΠΈ Webpack 5. @@ -38,7 +38,7 @@ export default defineReactSpriteConfig({ По ΡƒΠΌΠΎΠ»Ρ‡Π°Π½ΠΈΡŽ SVG бСрутся ΠΈΠ· `./icons`. ΠžΠ±Ρ‰ΠΈΠ΅ ΠΈΠΊΠΎΠ½ΠΊΠΈ ΠΈΠ· Π΄Ρ€ΡƒΠ³ΠΈΡ… ΠΏΠ°ΠΏΠΎΠΊ ΠΌΠΎΠΆΠ½ΠΎ Π΄ΠΎΠ±Π°Π²ΠΈΡ‚ΡŒ Ρ‡Π΅Ρ€Π΅Π· `inputFiles`: ΠΏΠ°ΠΏΠΊΠ° ΠΈ список ΠΎΠ±ΡŠΠ΅Π΄ΠΈΠ½ΡΡŽΡ‚ΡΡ Π² ΠΎΠ΄ΠΈΠ½ спрайт. -ΠŸΠΎΠ»Π½Ρ‹ΠΉ список ΠΎΠΏΡ†ΠΈΠΉ находится Π² Ρ€Π°Π·Π΄Π΅Π»Π΅ [ΠšΠΎΠ½Ρ„ΠΈΠ³ΡƒΡ€Π°Ρ†ΠΈΡ β†’ React](../../README.md#react). +ΠŸΠΎΠ»Π½Ρ‹ΠΉ список ΠΎΠΏΡ†ΠΈΠΉ находится Π² Ρ€Π°Π·Π΄Π΅Π»Π΅ [ΠšΠΎΠ½Ρ„ΠΈΠ³ΡƒΡ€Π°Ρ†ΠΈΡ β†’ React](../../README_RU.md#react). ## 4. Π”ΠΎΠ±Π°Π²ΡŒΡ‚Π΅ Π³Π΅Π½Π΅Ρ€Π°Ρ†ΠΈΡŽ Π² package.json @@ -81,7 +81,7 @@ export const OpenFolderButton = () => ( // ошибка TypeScript ``` -Π’ΠΈΠΏΡ‹, способы отобраТСния ΠΈ ΡƒΠΏΡ€Π°Π²Π»Π΅Π½ΠΈΠ΅ Ρ†Π²Π΅Ρ‚Π°ΠΌΠΈ описаны Π² [основной Π΄ΠΎΠΊΡƒΠΌΠ΅Π½Ρ‚Π°Ρ†ΠΈΠΈ](../../README.md#способы-отобраТСния). +Π’ΠΈΠΏΡ‹, способы отобраТСния ΠΈ ΡƒΠΏΡ€Π°Π²Π»Π΅Π½ΠΈΠ΅ Ρ†Π²Π΅Ρ‚Π°ΠΌΠΈ описаны Π² [основной Π΄ΠΎΠΊΡƒΠΌΠ΅Π½Ρ‚Π°Ρ†ΠΈΠΈ](../../README_RU.md#способы-отобраТСния). Webpack ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Π°Π΅Ρ‚ generated `new URL('./sprite.svg', import.meta.url)` Ρ‡Π΅Ρ€Π΅Π· Asset Modules ΠΈ выпустит ΠΎΡ‚Π΄Π΅Π»ΡŒΠ½Ρ‹ΠΉ SVG asset. diff --git a/package.json b/package.json index 0459e55..7d67ed2 100644 --- a/package.json +++ b/package.json @@ -32,6 +32,8 @@ "dist/chunk-*.js", "dist/chunk-*.js.map", "dist/preview-template.html", + "README_RU.md", + "docs/en/*.md", "docs/ru/*.md", "LICENSE", "THIRD_PARTY_NOTICES.md" diff --git a/skills/README.md b/skills/README.md index 8d74059..1b8676e 100644 --- a/skills/README.md +++ b/skills/README.md @@ -1,12 +1,12 @@ # AI skills -Π˜ΡΡ…ΠΎΠ΄Π½ΠΈΠΊΠΈ скила `svg-sprites` находятся Π² `skills/svg-sprites/`. Π“ΠΎΡ‚ΠΎΠ²Ρ‹ΠΉ самодостаточный Π°Ρ€Ρ‚Π΅Ρ„Π°ΠΊΡ‚ записываСтся Π² `skills/artifacts/svg-sprites/` ΠΈ коммитится Π² Git. +Π˜ΡΡ…ΠΎΠ΄Π½ΠΈΠΊΠΈ скилов `svg-sprites` ΠΈ `svg-sprites-ru` находятся Π² `skills/svg-sprites/`. Π“ΠΎΡ‚ΠΎΠ²Ρ‹Π΅ самодостаточныС Π°Ρ€Ρ‚Π΅Ρ„Π°ΠΊΡ‚Ρ‹ Π·Π°ΠΏΠΈΡΡ‹Π²Π°ΡŽΡ‚ΡΡ Π² `skills/artifacts/svg-sprites/` ΠΈ `skills/artifacts/svg-sprites-ru/` ΠΈ коммитятся Π² Git. -ΠžΡΠ½ΠΎΠ²Π½Ρ‹Π΅ `README.md` ΠΈ `docs/ru/*.md` ΡΠ²Π»ΡΡŽΡ‚ΡΡ источником истины. Π‘Π±ΠΎΡ€ΠΊΠ° ΠΊΠΎΠΏΠΈΡ€ΡƒΠ΅Ρ‚ ΠΈΡ… Π² `references/` Π³ΠΎΡ‚ΠΎΠ²ΠΎΠ³ΠΎ скила, поэтому Π²Ρ€ΡƒΡ‡Π½ΡƒΡŽ Ρ€Π΅Π΄Π°ΠΊΡ‚ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ Ρ„Π°ΠΉΠ»Ρ‹ Π²Π½ΡƒΡ‚Ρ€ΠΈ `skills/artifacts/` нСльзя. +ΠžΡΠ½ΠΎΠ²Π½Ρ‹Π΅ `README.md`, `README_RU.md` ΠΈ Ρ„Π°ΠΉΠ»Ρ‹ `docs/{en,ru}/*.md` ΡΠ²Π»ΡΡŽΡ‚ΡΡ источником истины. Π‘Π±ΠΎΡ€ΠΊΠ° ΠΊΠΎΠΏΠΈΡ€ΡƒΠ΅Ρ‚ ΠΈΡ… Π² `references/` Π³ΠΎΡ‚ΠΎΠ²ΠΎΠ³ΠΎ скила, поэтому Π²Ρ€ΡƒΡ‡Π½ΡƒΡŽ Ρ€Π΅Π΄Π°ΠΊΡ‚ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ Ρ„Π°ΠΉΠ»Ρ‹ Π²Π½ΡƒΡ‚Ρ€ΠΈ `skills/artifacts/` нСльзя. ```bash npm run build:skill npm run check:skill ``` -`build:skill` обновляСт Π°Ρ€Ρ‚Π΅Ρ„Π°ΠΊΡ‚, Π° `check:skill` Π±Π΅Π· измСнСния Ρ„Π°ΠΉΠ»ΠΎΠ² провСряСт Π΅Π³ΠΎ содСрТимоС ΠΈ ΡΠΈΠ½Ρ…Ρ€ΠΎΠ½Π½ΠΎΡΡ‚ΡŒ с Π΄ΠΎΠΊΡƒΠΌΠ΅Π½Ρ‚Π°Ρ†ΠΈΠ΅ΠΉ. +`build:skill` обновляСт ΠΎΠ±Π° Π°Ρ€Ρ‚Π΅Ρ„Π°ΠΊΡ‚Π°, Π° `check:skill` Π±Π΅Π· измСнСния Ρ„Π°ΠΉΠ»ΠΎΠ² провСряСт ΠΈΡ… содСрТимоС ΠΈ ΡΠΈΠ½Ρ…Ρ€ΠΎΠ½Π½ΠΎΡΡ‚ΡŒ с Π΄ΠΎΠΊΡƒΠΌΠ΅Π½Ρ‚Π°Ρ†ΠΈΠ΅ΠΉ. ВСрсия Π±Π΅Π· суффикса ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ английский язык, вСрсия с суффиксом `-ru` β€” русский. diff --git a/skills/artifacts/svg-sprites-ru/SKILL.md b/skills/artifacts/svg-sprites-ru/SKILL.md new file mode 100644 index 0000000..b5ff569 --- /dev/null +++ b/skills/artifacts/svg-sprites-ru/SKILL.md @@ -0,0 +1,64 @@ +--- +name: svg-sprites-ru +description: "Π˜ΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠΉ ΠΏΡ€ΠΈ настройкС, Π³Π΅Π½Π΅Ρ€Π°Ρ†ΠΈΠΈ, ΠΌΠΈΠ³Ρ€Π°Ρ†ΠΈΠΈ ΠΈΠ»ΠΈ диагностикС SVG-спрайтов Ρ‡Π΅Ρ€Π΅Π· @gromlab/svg-sprites. Π’Ρ€ΠΈΠ³Π³Π΅Ρ€Ρ‹: SVG sprite, SVG-спрайт, svg-sprites, svg-sprite.config.ts, svg-sprites.config.ts, defineReactSpriteConfig, defineNextSpriteConfig, react@vite, react@webpack, next@app, next@pages, inputFiles, SpriteViewer, icon=\"...\", --icon-color-N, generated-ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚ ΠΈΠ»ΠΈ ΠΈΠΊΠΎΠ½ΠΊΠ° Π½Π΅ появилась Π² ΠΏΡ€Π΅Π²ΡŒΡŽ ΠΈ Π°Π²Ρ‚ΠΎΠ΄ΠΎΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ. НЕ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠΉ для favicon, растровых ΠΈΠ·ΠΎΠ±Ρ€Π°ΠΆΠ΅Π½ΠΈΠΉ, icon fonts, Π²Ρ‹Π±ΠΎΡ€Π° Π½Π°Π±ΠΎΡ€Π° ΠΈΠΊΠΎΠ½ΠΎΠΊ ΠΈΠ»ΠΈ inline SVG Π±Π΅Π· спрайтов." +--- + + + +# SVG Sprites + +## НазначСниС + +Π˜ΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠΉ этот скил для Ρ€Π°Π±ΠΎΡ‚Ρ‹ с `@gromlab/svg-sprites`: ΠΏΠ΅Ρ€Π²ΠΈΡ‡Π½ΠΎΠΉ настройки, добавлСния ΠΈ ΠΏΠ΅Ρ€Π΅ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Π½ΠΈΡ ΠΈΠΊΠΎΠ½ΠΎΠΊ, Π³Π΅Π½Π΅Ρ€Π°Ρ†ΠΈΠΈ React-ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚ΠΎΠ², ΠΏΠΎΠ΄ΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΡ `SpriteViewer`, ΠΌΠΈΠ³Ρ€Π°Ρ†ΠΈΠΈ legacy-ΠΊΠΎΠ½Ρ„ΠΈΠ³ΡƒΡ€Π°Ρ†ΠΈΠΈ ΠΈ диагностики ошибок. + +НС навязывай ΠΏΡ€ΠΎΠ΅ΠΊΡ‚Ρƒ ΠΊΠΎΠ½ΠΊΡ€Π΅Ρ‚Π½ΡƒΡŽ Π°Ρ€Ρ…ΠΈΡ‚Π΅ΠΊΡ‚ΡƒΡ€Ρƒ ΠΊΠ°Ρ‚Π°Π»ΠΎΠ³ΠΎΠ². Π‘Π½Π°Ρ‡Π°Π»Π° ΠΈΠ·ΡƒΡ‡ΠΈ ΡΡƒΡ‰Π΅ΡΡ‚Π²ΡƒΡŽΡ‰ΠΈΠ΅ `package.json`, ΠΊΠΎΠ½Ρ„ΠΈΠ³ΡƒΡ€Π°Ρ†ΠΈΡŽ спрайта, ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅ΠΌΡ‹ΠΉ Ρ„Ρ€Π΅ΠΉΠΌΠ²ΠΎΡ€ΠΊ, Ρ€ΠΎΡƒΡ‚Π΅Ρ€ ΠΈ сборщик. + +## Π Π°Π±ΠΎΡ‡ΠΈΠΉ Π°Π»Π³ΠΎΡ€ΠΈΡ‚ΠΌ + +1. ΠžΠΏΡ€Π΅Π΄Π΅Π»ΠΈ ΡΡƒΡ‰Π΅ΡΡ‚Π²ΡƒΡŽΡ‰ΠΈΠΉ Ρ€Π΅ΠΆΠΈΠΌ ΠΈ Π½Π΅ смСшивай Π΅Π³ΠΎ API с Π΄Ρ€ΡƒΠ³ΠΈΠΌ Ρ€Π΅ΠΆΠΈΠΌΠΎΠΌ. +2. Для React Π²Ρ‹Π±Π΅Ρ€ΠΈ `react@vite` ΠΈΠ»ΠΈ `react@webpack` ΠΈ ΠΎΡ‚ΠΊΡ€ΠΎΠΉ ΡΠΎΠΎΡ‚Π²Π΅Ρ‚ΡΡ‚Π²ΡƒΡŽΡ‰ΠΈΠΉ reference. +3. Для Next.js ΠΎΠΏΡ€Π΅Π΄Π΅Π»ΠΈ App Router ΠΈΠ»ΠΈ Pages Router, Π·Π°Ρ‚Π΅ΠΌ Turbopack ΠΈΠ»ΠΈ Webpack, ΠΈ ΠΎΡ‚ΠΊΡ€ΠΎΠΉ ΡΠΎΠΎΡ‚Π²Π΅Ρ‚ΡΡ‚Π²ΡƒΡŽΡ‰ΠΈΠΉ reference. +4. Для ΡΡƒΡ‰Π΅ΡΡ‚Π²ΡƒΡŽΡ‰Π΅Π³ΠΎ `svg-sprites.config.ts` с нСсколькими спрайтами ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠΉ legacy-Π΄ΠΎΠΊΡƒΠΌΠ΅Π½Ρ‚Π°Ρ†ΠΈΡŽ. НС ΠΌΠΈΠ³Ρ€ΠΈΡ€ΡƒΠΉ Ρ‚Π°ΠΊΠΎΠΉ ΠΏΡ€ΠΎΠ΅ΠΊΡ‚ Π±Π΅Π· явного запроса. +5. Π˜Π·ΡƒΡ‡ΠΈ Π»ΠΎΠΊΠ°Π»ΡŒΠ½Ρ‹Π΅ scripts ΠΈ добавляй Π³Π΅Π½Π΅Ρ€Π°Ρ†ΠΈΡŽ ΠΏΠ΅Ρ€Π΅Π΄ `dev`, `build` ΠΈ `typecheck`, Ссли generated-Ρ„Π°ΠΉΠ»Ρ‹ Π½Π΅ хранятся Π² Git. +6. ПослС измСнСния ΠΊΠΎΠ½Ρ„ΠΈΠ³ΡƒΡ€Π°Ρ†ΠΈΠΈ ΠΈΠ»ΠΈ SVG запусти Π³Π΅Π½Π΅Ρ€Π°Ρ†ΠΈΡŽ, Π·Π°Ρ‚Π΅ΠΌ Π΄ΠΎΡΡ‚ΡƒΠΏΠ½ΡƒΡŽ ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΊΡƒ Ρ‚ΠΈΠΏΠΎΠ² ΠΈΠ»ΠΈ сборку ΠΏΡ€ΠΎΠ΅ΠΊΡ‚Π°. + +## ΠŸΡ€Π°Π²ΠΈΠ»Π° React ΠΈ Next.js + +- Π˜ΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠΉ Π»ΠΎΠΊΠ°Π»ΡŒΠ½Ρ‹ΠΉ `svg-sprite.config.ts` ΠΈ подходящий config helper: `defineReactSpriteConfig` ΠΈΠ»ΠΈ `defineNextSpriteConfig`. +- НС Ρ€Π΅Π΄Π°ΠΊΡ‚ΠΈΡ€ΡƒΠΉ `generated/`, `index.ts`, `manifest.ts` ΠΈ созданный Π³Π΅Π½Π΅Ρ€Π°Ρ‚ΠΎΡ€ΠΎΠΌ `.gitignore` Π²Ρ€ΡƒΡ‡Π½ΡƒΡŽ. +- ИмСна исходных SVG становятся допустимыми значСниями prop `icon`; ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠΉ generated-ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚ ΠΈ Π΅Π³ΠΎ ΠΏΡƒΠ±Π»ΠΈΡ‡Π½Ρ‹Π΅ Ρ‚ΠΈΠΏΡ‹ вмСсто deep imports. +- ОбъСдиняй Π»ΠΎΠΊΠ°Π»ΡŒΠ½ΡƒΡŽ ΠΏΠ°ΠΏΠΊΡƒ ΠΈ `inputFiles`, ΠΊΠΎΠ³Π΄Π° общая ΠΈΠΊΠΎΠ½ΠΊΠ° Π½ΡƒΠΆΠ½Π° нСскольким спрайтам. НС создавай ΠΊΠΎΠΏΠΈΠΈ ΠΎΠ΄Π½ΠΎΠ³ΠΎ SVG Π±Π΅Π· нСобходимости. +- Π’ Next.js generated-ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚ ΠΌΠΎΠΆΠ½ΠΎ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ Π² Server Components, SSR ΠΈ SSG. НС добавляй `'use client'` Ρ‚ΠΎΠ»ΡŒΠΊΠΎ Ρ€Π°Π΄ΠΈ ΠΈΠΊΠΎΠ½ΠΊΠΈ. +- Π‘ΠΏΡ€Π°ΠΉΡ‚ Π΄ΠΎΠ»ΠΆΠ΅Π½ ΠΎΡΡ‚Π°Π²Π°Ρ‚ΡŒΡΡ внСшним asset сборщика: Π½Π΅ ΠΏΠ΅Ρ€Π΅Π½ΠΎΡΠΈΡ‚ΡŒ SVG path-Π΄Π°Π½Π½Ρ‹Π΅ Π² JavaScript ΠΈ Π½Π΅ ΠΊΠ»Π°ΡΡ‚ΡŒ generated-Ρ„Π°ΠΉΠ» Π²Ρ€ΡƒΡ‡Π½ΡƒΡŽ Π² `public`. + +## Π¦Π²Π΅Ρ‚Π° ΠΈ трансформации + +- По ΡƒΠΌΠΎΠ»Ρ‡Π°Π½ΠΈΡŽ Π³Π΅Π½Π΅Ρ€Π°Ρ‚ΠΎΡ€ удаляСт `width` ΠΈ `height`, замСняСт ΠΏΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΈΠ²Π°Π΅ΠΌΡ‹Π΅ `fill` ΠΈ `stroke` Π½Π° CSS-ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½Ρ‹Π΅ ΠΈ добавляСт transitions. +- Для ΠΌΠΎΠ½ΠΎΡ…Ρ€ΠΎΠΌΠ½ΠΎΠΉ ΠΈΠΊΠΎΠ½ΠΊΠΈ сначала управляй `color`; для ΠΌΠ½ΠΎΠ³ΠΎΡ†Π²Π΅Ρ‚Π½ΠΎΠΉ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠΉ `--icon-color-N`. +- НС ΠΎΠ±Π΅Ρ‰Π°ΠΉ Π°Π²Ρ‚ΠΎΠΌΠ°Ρ‚ΠΈΡ‡Π΅ΡΠΊΡƒΡŽ Π·Π°ΠΌΠ΅Π½Ρƒ Ρ†Π²Π΅Ρ‚ΠΎΠ² Π²Π½ΡƒΡ‚Ρ€ΠΈ Π²Π½Π΅ΡˆΠ½ΠΈΡ… stylesheets, gradients, patterns, filters ΠΈ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠΉ `url(#...)` Π±Π΅Π· ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΊΠΈ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Π°. +- CSS-ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½Ρ‹Π΅ страницы Ρ€Π°Π±ΠΎΡ‚Π°ΡŽΡ‚ ΠΏΡ€ΠΈ ``, Π½ΠΎ Π½Π΅ ΠΏΡ€ΠΎΠ½ΠΈΠΊΠ°ΡŽΡ‚ Π²Π½ΡƒΡ‚Ρ€ΡŒ `` ΠΈ `background-image`. + +## ΠŸΡ€Π΅Π²ΡŒΡŽ + +Для React ΠΈ Next.js ΠΏΠΎΠ΄ΠΊΠ»ΡŽΡ‡Π°ΠΉ `` ΠΎΡ‚Π΄Π΅Π»ΡŒΠ½ΠΎΠΉ debug-страницСй прилоТСния. ΠŸΠ΅Ρ€Π΅Π΄Π°ΠΉ Π΅ΠΌΡƒ manifests ΠΈΠ»ΠΈ lazy loaders спрайтов. Viewer ΠΏΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΈΠ²Π°Π΅Ρ‚ поиск, ΡΠ²Π΅Ρ‚Π»ΡƒΡŽ ΠΈ Ρ‚Ρ‘ΠΌΠ½ΡƒΡŽ Ρ‚Π΅ΠΌΡ‹, настройку Ρ†Π²Π΅Ρ‚ΠΎΠ² ΠΈ ΠΏΡ€ΠΈΠΌΠ΅Ρ€Ρ‹ React, SVG, IMG ΠΈ CSS. + +`SpriteViewer` являСтся клиСнтским debug-инструмСнтом ΠΈ импортируСтся ΠΈΠ· `@gromlab/svg-sprites/react`; production-ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Ρ‹ ΠΈΠΊΠΎΠ½ΠΎΠΊ ΠΎΡ‚ Π½Π΅Π³ΠΎ Π½Π΅ зависят. + +## Диагностика + +- Если имя ΠΈΠΊΠΎΠ½ΠΊΠΈ отсутствуСт Π² Π°Π²Ρ‚ΠΎΠ΄ΠΎΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ, ΠΏΡ€ΠΎΠ²Π΅Ρ€ΡŒ Π²Ρ…ΠΎΠ΄Π½ΡƒΡŽ ΠΏΠ°ΠΏΠΊΡƒ ΠΈ `inputFiles`, Π·Π°Ρ‚Π΅ΠΌ пСрСзапусти Π³Π΅Π½Π΅Ρ€Π°Ρ†ΠΈΡŽ. +- Если Π΄Π²Π° Ρ„Π°ΠΉΠ»Π° ΠΈΠΌΠ΅ΡŽΡ‚ ΠΎΠ΄ΠΈΠ½Π°ΠΊΠΎΠ²ΠΎΠ΅ имя ΠΈΠΊΠΎΠ½ΠΊΠΈ, устрани ΠΊΠΎΠ½Ρ„Π»ΠΈΠΊΡ‚ вмСсто Π²Ρ‹Π±ΠΎΡ€Π° ΠΎΠ΄Π½ΠΎΠ³ΠΎ Ρ„Π°ΠΉΠ»Π° нСявно. +- Если Π³Π΅Π½Π΅Ρ€Π°Ρ‚ΠΎΡ€ отказываСтся ΠΏΠ΅Ρ€Π΅Π·Π°ΠΏΠΈΡΡ‹Π²Π°Ρ‚ΡŒ Ρ„Π°ΠΉΠ», Π½Π΅ удаляй Π·Π°Ρ‰ΠΈΡ‚Π½Ρ‹ΠΉ marker ΠΈ Π½Π΅ ΠΎΠ±Ρ…ΠΎΠ΄ΠΈ writer: пСрСнСси ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»ΡŒΡΠΊΠΈΠΉ Ρ„Π°ΠΉΠ» ΠΈΠ»ΠΈ Π²Ρ‹Π±Π΅Ρ€ΠΈ Π΄Ρ€ΡƒΠ³ΠΎΠΉ ΠΊΠ°Ρ‚Π°Π»ΠΎΠ³ спрайта. +- Если asset Π½Π΅ загруТаСтся, сначала ΠΏΡ€ΠΎΠ²Π΅Ρ€ΡŒ соотвСтствиС CLI mode Ρ€Π΅Π°Π»ΡŒΠ½ΠΎΠΌΡƒ сборщику ΠΏΡ€ΠΎΠ΅ΠΊΡ‚Π° ΠΈ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΡƒ generated SVG Π΅Π³ΠΎ asset pipeline. +- Если ΠΏΡ€ΠΎΠ΅ΠΊΡ‚ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ старый API, ΡΠ²Π΅Ρ€ΡŒ ΡƒΡΡ‚Π°Π½ΠΎΠ²Π»Π΅Π½Π½ΡƒΡŽ Π²Π΅Ρ€ΡΠΈΡŽ ΠΏΠ°ΠΊΠ΅Ρ‚Π° ΠΈ legacy reference ΠΏΠ΅Ρ€Π΅Π΄ измСнСниями. + +## References + +- [Основная докумСнтация ΠΈ API](./references/README_RU.md) +- [React + Vite](./references/docs/ru/react-vite.md) +- [React + Webpack 5](./references/docs/ru/react-webpack.md) +- [Next.js App Router](./references/docs/ru/next-app.md) +- [Next.js Pages Router](./references/docs/ru/next-pages.md) +- [Legacy mode](./references/docs/ru/legacy.md) +- [ΠœΠΈΠ³Ρ€Π°Ρ†ΠΈΡ с 0.1.x](./references/docs/ru/migration-1.md) +- [ΠŸΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠ½Ρ‹ΠΉ API](./references/docs/ru/programmatic-api.md) diff --git a/skills/artifacts/svg-sprites-ru/references/README.md b/skills/artifacts/svg-sprites-ru/references/README.md new file mode 100644 index 0000000..5461b0e --- /dev/null +++ b/skills/artifacts/svg-sprites-ru/references/README.md @@ -0,0 +1,398 @@ +# @gromlab/svg-sprites + +πŸ‡¬πŸ‡§ English | [πŸ‡·πŸ‡Ί Русский](README_RU.md) + +![npm](https://img.shields.io/npm/v/@gromlab/svg-sprites) ![license](https://img.shields.io/npm/l/@gromlab/svg-sprites) + +A CLI for generating SVG sprites and typed icon components for React and Next.js. + +![Preview](https://gromlab.ru/gromov/svg-sprites/media/branch/master/preview-image.png) + +## Navigation + +- [Features](#features) +- [Support matrix](#support-matrix) +- [Requirements](#requirements) +- [Quick start](#quick-start) + - [React + Vite](docs/en/react-vite.md) + - [React + Webpack 5](docs/en/react-webpack.md) + - [Next.js App Router](docs/en/next-app.md) + - [Next.js Pages Router](docs/en/next-pages.md) +- [Configuration](#configuration) + - [React](#react) + - [Next.js](#nextjs) +- [Multiple sprites](#multiple-sprites) +- [TypeScript](#typescript) +- [Sprite formats](#sprite-formats) +- [Rendering methods](#rendering-methods) +- [Transformations](#transformations) +- [Icon color management](#icon-color-management) +- [Caching](#caching) +- [SpriteViewer](#spriteviewer) +- [Migrating from 0.1.x](docs/en/migration-1.md) +- [Documentation](#documentation) + +## Features + +- **AI-agent friendly** - the repository includes a ready-to-use skill with up-to-date documentation for configuring, migrating, and troubleshooting `@gromlab/svg-sprites`. +- **TypeScript-friendly** - typed React components, union types, and runtime lists of available icons. +- **Clean generation** - generated files are automatically excluded from Git, the sprite does not need to be placed in `public` manually, and the generator updates only files it owns. +- **Shared icons without copying** - SVGs from the local folder and `inputFiles` are merged into a single sprite; one file can be used in multiple sprites. +- **Built-in interactive preview** - `` is integrated as an application page and displays the provided React and Next.js sprites with search, color controls, and usage examples. +- **Configurable SVG transformations** - remove `width` and `height` while preserving `viewBox`, replace source colors with CSS variables, and add transitions for `fill` and `stroke`. +- **Separate cacheable SVG asset** - SVG path data does not end up in JavaScript chunks, and the bundler emits a file with a content hash. +- **Multiple sprites** - independent React and Next.js modules with their own components, types, and SVG assets. +- **Server-first Next.js** - generated components work in Server Components, SSR, and SSG without the `'use client'` directive. +- **Formats for different use cases** - React and Next.js use `stack`; legacy mode also supports `symbol` for existing integrations. + +## Support matrix + +| Environment | API mode key | Status | +|---|---|---| +| React + Vite | `react@vite` | Ready | +| React + Webpack 5 | `react@webpack` | Ready | +| Next.js 16.2+ App Router + Turbopack | `next@app/turbopack` | Ready | +| Next.js 13.4+ App Router + Webpack 5 | `next@app/webpack` | Ready | +| Next.js 16.2+ Pages Router + Turbopack | `next@pages/turbopack` | Ready | +| Next.js 12.2+ Pages Router + Webpack 5 | `next@pages/webpack` | Ready | +| Vue | - | Coming soon | +| Standalone | - | Coming soon | + +## Requirements + +- Node.js 18 or newer; +- the package is distributed as ESM only and is loaded via `import`; +- React 18 or 19 is required only for generated components and the `@gromlab/svg-sprites/react` entry point; +- for subpath export typings, use TypeScript 5+ with `moduleResolution: "bundler"`, `"node16"`, or `"nodenext"`. + +## Quick start + +For a quick start, follow the guide for your stack: + +- [React + Vite](docs/en/react-vite.md) +- [React + Webpack 5](docs/en/react-webpack.md) +- [Next.js App Router](docs/en/next-app.md) +- [Next.js Pages Router](docs/en/next-pages.md) + +## Configuration + +### React + +```ts +import { defineReactSpriteConfig } from '@gromlab/svg-sprites' + +export default defineReactSpriteConfig({ + name: 'file-manager', + description: 'File manager icons', + inputFolder: './icons', + inputFiles: [ + '../../shared/icons/check.svg', + ], + transform: { + removeSize: true, + replaceColors: true, + addTransition: true, + }, + generatedNotice: true, +}) +``` + +| Option | Type | Default | Purpose | +|---|---|---|---| +| `name` | `string` | Folder name | Name of the sprite, component, and public types | +| `description` | `string` | None | Description for types and the debug manifest | +| `inputFolder` | `string` | `./icons` | Folder containing source SVGs, relative to the config | +| `inputFiles` | `string[]` | `[]` | Additional SVG files, relative to the config | +| `transform` | `TransformOptions` | All enabled | [Transformation settings](#transformations) for source SVGs | +| `generatedNotice` | `boolean` | `true` | Full or short warning in generated files | + +`inputFolder` and `inputFiles` are merged into a single sprite, so one SVG file can be used in multiple sprites without copying. If the implicit `./icons` folder does not exist but `inputFiles` is populated, generation continues using only the list. An explicitly specified missing folder is an error. Duplicate paths are deduplicated, while different files with the same icon name are treated as an error. + +`name` is stored in kebab-case and must start with a Latin letter. The React and Next.js presets produce the `stack` format. + +### Next.js + +Next.js uses the same `svg-sprite.config.ts` and set of options. For type checking, you can use a dedicated helper: + +```ts +import { defineNextSpriteConfig } from '@gromlab/svg-sprites' + +export default defineNextSpriteConfig({ + name: 'file-manager', + description: 'File manager icons', + inputFolder: './icons', +}) +``` + +The router and bundler are selected through the mode key, so switching between Turbopack and Webpack is always explicitly reflected in the generation command. + +## Multiple sprites + +An application can contain several independent sprites for different scopes: + +**Problem:** one global sprite loads icons that the current screen does not need. + +**Solution:** keep shared icons globally, and place icon sets for pages and large components in separate sprites that load alongside them. + +```text +global -> GlobalIcon -> shared application icons +analytics-page -> AnalyticsPageIcon -> icons for a specific page +file-manager -> FileManagerIcon -> icons for a large component +``` + +- **Global sprite** contains a small set of shared icons used in different parts of the application: navigation, states, and basic actions. +- **Page sprite** loads with a specific section and does not increase the shared sprite with icons that are not needed anywhere else. +- **Large component sprite** encapsulates the icon set of a complex UI module, such as a file manager or editor. + +Each group gets: + +- its own SVG asset; +- its own typed component; +- a separate list of icon names; +- a separate debug manifest; +- an independent cache lifecycle. + + +## TypeScript + +The main feature of the TypeScript API is icon name autocomplete directly in the `icon` prop: + +```tsx + +// ^ the editor suggests every icon in the sprite +``` + +SVG file names become valid `icon` values. A typo or unknown name immediately becomes a TypeScript error: + +```tsx + // TypeScript error +``` + +For programmatic access, the generated module exports a readonly array of all icons available in a specific sprite: + +```ts +import { fileManagerIconNames } from './svg-sprite' + +// readonly ['check', 'folder', ...] +``` + +You can use this list in custom catalogs, select components, tests, and other runtime scenarios. The `FileManagerIconName` union type is also derived from it. + +File names containing spaces and other characters unsafe for SVG IDs remain part of the public TypeScript API. For the internal ``, the generator creates a stable hash ID. + +```text +folder open.svg -> icon="folder open" -> id="icon-" +``` + +For such names, use the generated component or the `id` from the debug manifest. The manual examples below using `#` are suitable only for names that are already safe SVG IDs. + +## Sprite formats + +`stack` is the more modern format, so it is used by default. Icons can be rendered through ``, ``, and CSS `background-image`. + +`symbol` is retained for compatibility with existing integrations and supports rendering only through ``. + +## Rendering methods + +### React component - recommended + +The generated component provides type safety and icon name autocomplete, and constructs the SVG asset URL itself. + +```tsx + +``` + +Monochrome and multicolor icons are supported through `color` and `--icon-color-N`. + +### Manually with `` + +A good low-level method that provides full control over dimensions and colors. This is exactly what the React component uses under the hood. + +How you obtain `spriteUrl` depends on the bundler. + +**Vite:** + +```tsx +import spriteUrl from './svg-sprite/generated/sprite.svg?no-inline' +``` + +**Webpack 5:** + +```tsx +const spriteUrl = new URL( + './svg-sprite/generated/sprite.svg', + import.meta.url, +).href +``` + +**Next.js with Webpack 5 or Turbopack:** + +```tsx +const spriteUrl = new URL( + './svg-sprite/generated/sprite.svg', + import.meta.url, +).href +``` + +After obtaining the URL, the icon is rendered the same way: + +```tsx + + + +``` + +Vite, Webpack 5, and Next.js replace the source path with the final hashed asset URL automatically. + +### With `` - less efficient + +```tsx +Done +``` + +The SVG loads as an isolated image: its colors cannot be changed through `color` or `--icon-color-N`. + +### With CSS `background-image` - less efficient + +```css +.icon { + background: url('./svg-sprite/generated/sprite.svg#check') center / contain no-repeat; +} +``` + +Like ``, this method does not allow you to control internal SVG colors. The path is specified relative to the CSS file, and Vite/Webpack replaces it with the final hashed URL during the build. + +### With CSS mask - less efficient + +```css +.icon { + background-color: currentColor; + mask: url('./svg-sprite/generated/sprite.svg#check') center / contain no-repeat; +} +``` + +A mask retains only the silhouette and colors it with a single color. The original colors, gradients, and distinctions between `fill` and `stroke` are lost. + +## Transformations + +All transformations are enabled by default and configured independently through `transform`. + +| Option | Default | What it does | +|---|---|---| +| `removeSize` | `true` | Removes `width` and `height` from the root `` while preserving the existing `viewBox`. The icon size is then set externally. | +| `replaceColors` | `true` | Replaces `fill` and `stroke` colors with `--icon-color-N`. For a monochrome icon, the fallback becomes `currentColor`; for a multicolor icon, the original colors are preserved. | +| `addTransition` | `true` | Adds `style="transition:fill 0.3s,stroke 0.3s;"` directly to colored SVG elements. An existing `transition` is not overwritten. | + +To disable a transformation, pass `false` for the corresponding option. For more details about the result of `replaceColors`, see [Icon color management](#icon-color-management). + +## Icon color management + +When color replacement is enabled, the generator analyzes `fill` and `stroke` and converts them to CSS custom properties. + +### Monochrome icons + +If one color is found, the fallback is replaced with `currentColor`: + +```svg +stroke="var(--icon-color-1, currentColor)" +``` + +The color is controlled by the CSS `color` property of the outer `` or its parent. + +### Multicolor icons + +Each unique color gets a separate variable with the original fallback: + +```svg +fill="var(--icon-color-1, #798198)" +fill="var(--icon-color-2, #ffffff)" +fill="var(--icon-color-3, #129d9d)" +``` + +The page can override only the required colors: + +```css +.icon { + --icon-color-1: #4b5563; + --icon-color-3: #14b8a6; +} +``` + +### Color limitations + +- `none`, `transparent`, `inherit`, `unset`, and `initial` are not replaced; +- colors in `fill`, `stroke`, and inline `style` attributes are handled most reliably; +- CSS classes and external stylesheets inside the source SVG are not the primary transformation use case; +- gradients, patterns, filters, and `url(#...)` values require separate verification and may be incompatible with automatic color replacement; +- page CSS variables are available with ``, but are not available inside `` and `background-image`. + +## Caching + +The Vite, Webpack, and Next.js targets emit the sprite as a separate asset with a content hash: + +```text +/assets/sprite-.svg +``` + +This provides the following properties: + +- the SVG is cached independently of JavaScript; +- changes to React code do not alter the sprite contents; +- icon changes produce a new hashed asset; +- one file is used by every instance of the generated component; +- SVG path data is absent from JavaScript chunks. + +The Vite target prevents inlining through `?no-inline`. The Webpack 5 target uses Asset Modules through `new URL(..., import.meta.url)`. + +## SpriteViewer + +`SpriteViewer` is a React component for viewing generated sprites inside an application's debug route. + +It uses separate manifests and displays: + +- sprite groups; +- the icon list and count; +- search and the system light/dark theme; +- a preview modal with the `viewBox` and color variable controls; +- React, SVG, IMG, and CSS examples with code copying. + +Production components do not import debug manifests. How you integrate the Viewer depends on the bundler: + +- [React + Vite: automatic `import.meta.glob`](docs/en/react-vite.md#6-add-a-debug-page); +- [React + Webpack 5: static `import()`](docs/en/react-webpack.md#6-add-a-debug-page); +- [Next.js App Router](docs/en/next-app.md#5-add-spriteviewer); +- [Next.js Pages Router](docs/en/next-pages.md#5-add-spriteviewer). + +The Viewer is imported from the separate `@gromlab/svg-sprites/react` client entry point and is not included in production icon components. + +### Viewer theme + +By default, `colorTheme="auto"`: the Viewer follows `prefers-color-scheme` and responds to system theme changes. The application theme can be passed explicitly: + +```tsx + +``` + +Valid `colorTheme` values are `auto`, `light`, and `dark`. When the theme is controlled externally, the built-in switch is hidden. To keep it and update the application theme through the Viewer, pass a callback: + +```tsx + +``` + +## Documentation + +- [React + Vite](docs/en/react-vite.md) +- [React + Webpack 5](docs/en/react-webpack.md) +- [Next.js App Router](docs/en/next-app.md) +- [Next.js Pages Router](docs/en/next-pages.md) +- [Legacy mode](docs/en/legacy.md) +- [Migrating from 0.1.x](docs/en/migration-1.md) +- [Programmatic API](docs/en/programmatic-api.md) + +## License + +MIT diff --git a/skills/artifacts/svg-sprites-ru/references/README_RU.md b/skills/artifacts/svg-sprites-ru/references/README_RU.md new file mode 100644 index 0000000..8ac80c5 --- /dev/null +++ b/skills/artifacts/svg-sprites-ru/references/README_RU.md @@ -0,0 +1,398 @@ +# @gromlab/svg-sprites + +[πŸ‡¬πŸ‡§ English](README.md) | πŸ‡·πŸ‡Ί Русский + +![npm](https://img.shields.io/npm/v/@gromlab/svg-sprites) ![license](https://img.shields.io/npm/l/@gromlab/svg-sprites) + +CLI для Π³Π΅Π½Π΅Ρ€Π°Ρ†ΠΈΠΈ SVG-спрайтов ΠΈ Ρ‚ΠΈΠΏΠΈΠ·ΠΈΡ€ΠΎΠ²Π°Π½Π½Ρ‹Ρ… ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚ΠΎΠ² ΠΈΠΊΠΎΠ½ΠΎΠΊ для React ΠΈ Next.js. + +![Preview](https://gromlab.ru/gromov/svg-sprites/media/branch/master/preview-image.png) + +## Навигация + +- [ВозмоТности](#возмоТности) +- [Π’Π°Π±Π»ΠΈΡ†Π° ΠΏΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΊΠΈ](#Ρ‚Π°Π±Π»ΠΈΡ†Π°-ΠΏΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΊΠΈ) +- [ВрСбования](#трСбования) +- [Быстрый старт](#быстрый-старт) + - [React + Vite](docs/ru/react-vite.md) + - [React + Webpack 5](docs/ru/react-webpack.md) + - [Next.js App Router](docs/ru/next-app.md) + - [Next.js Pages Router](docs/ru/next-pages.md) +- [ΠšΠΎΠ½Ρ„ΠΈΠ³ΡƒΡ€Π°Ρ†ΠΈΡ](#конфигурация) + - [React](#react) + - [Next.js](#nextjs) +- [ΠœΠ½ΠΎΠΆΠ΅ΡΡ‚Π²Π΅Π½Π½Ρ‹Π΅ спрайты](#мноТСствСнныС-спрайты) +- [TypeScript](#typescript) +- [Π€ΠΎΡ€ΠΌΠ°Ρ‚Ρ‹ спрайтов](#Ρ„ΠΎΡ€ΠΌΠ°Ρ‚Ρ‹-спрайтов) +- [Бпособы отобраТСния](#способы-отобраТСния) +- [Врансформации](#трансформации) +- [Π£ΠΏΡ€Π°Π²Π»Π΅Π½ΠΈΠ΅ Ρ†Π²Π΅Ρ‚ΠΎΠΌ ΠΈΠΊΠΎΠ½ΠΎΠΊ](#ΡƒΠΏΡ€Π°Π²Π»Π΅Π½ΠΈΠ΅-Ρ†Π²Π΅Ρ‚ΠΎΠΌ-ΠΈΠΊΠΎΠ½ΠΎΠΊ) +- [ΠšΠ΅ΡˆΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠ΅](#ΠΊΠ΅ΡˆΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠ΅) +- [SpriteViewer](#spriteviewer) +- [ΠœΠΈΠ³Ρ€Π°Ρ†ΠΈΡ с 0.1.x](docs/ru/migration-1.md) +- [ДокумСнтация](#докумСнтация) + +## ВозмоТности + +- **AI-agent friendly** β€” Ρ€Π΅ΠΏΠΎΠ·ΠΈΡ‚ΠΎΡ€ΠΈΠΉ содСрТит Π³ΠΎΡ‚ΠΎΠ²Ρ‹ΠΉ skill с Π°ΠΊΡ‚ΡƒΠ°Π»ΡŒΠ½ΠΎΠΉ Π΄ΠΎΠΊΡƒΠΌΠ΅Π½Ρ‚Π°Ρ†ΠΈΠ΅ΠΉ для настройки, ΠΌΠΈΠ³Ρ€Π°Ρ†ΠΈΠΈ ΠΈ диагностики `@gromlab/svg-sprites`. +- **TypeScript-friendly** β€” Ρ‚ΠΈΠΏΠΈΠ·ΠΈΡ€ΠΎΠ²Π°Π½Π½Ρ‹Π΅ React-ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Ρ‹, union-Ρ‚ΠΈΠΏΡ‹ ΠΈ runtime-списки доступных ΠΈΠΊΠΎΠ½ΠΎΠΊ. +- **Чистая гСнСрация** β€” generated-Ρ„Π°ΠΉΠ»Ρ‹ автоматичСски ΠΈΡΠΊΠ»ΡŽΡ‡Π°ΡŽΡ‚ΡΡ ΠΈΠ· Git, спрайт Π½Π΅ Π½ΡƒΠΆΠ½ΠΎ Π²Ρ€ΡƒΡ‡Π½ΡƒΡŽ Ρ€Π°Π·ΠΌΠ΅Ρ‰Π°Ρ‚ΡŒ Π² `public`, Π° Π³Π΅Π½Π΅Ρ€Π°Ρ‚ΠΎΡ€ обновляСт Ρ‚ΠΎΠ»ΡŒΠΊΠΎ ΠΏΡ€ΠΈΠ½Π°Π΄Π»Π΅ΠΆΠ°Ρ‰ΠΈΠ΅ Π΅ΠΌΡƒ Ρ„Π°ΠΉΠ»Ρ‹. +- **ΠžΠ±Ρ‰ΠΈΠ΅ ΠΈΠΊΠΎΠ½ΠΊΠΈ Π±Π΅Π· копирования** β€” SVG ΠΈΠ· локальной ΠΏΠ°ΠΏΠΊΠΈ ΠΈ `inputFiles` ΠΎΠ±ΡŠΠ΅Π΄ΠΈΠ½ΡΡŽΡ‚ΡΡ Π² ΠΎΠ΄ΠΈΠ½ спрайт; ΠΎΠ΄ΠΈΠ½ Ρ„Π°ΠΉΠ» ΠΌΠΎΠΆΠ½ΠΎ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ Π² Π½Π΅ΡΠΊΠΎΠ»ΡŒΠΊΠΈΡ… спрайтах. +- **ВстроСнноС ΠΈΠ½Ρ‚Π΅Ρ€Π°ΠΊΡ‚ΠΈΠ²Π½ΠΎΠ΅ ΠΏΡ€Π΅Π²ΡŒΡŽ** β€” `` ΠΏΠΎΠ΄ΠΊΠ»ΡŽΡ‡Π°Π΅Ρ‚ΡΡ ΠΊΠ°ΠΊ страница прилоТСния ΠΈ ΠΏΠΎΠΊΠ°Π·Ρ‹Π²Π°Π΅Ρ‚ ΠΏΠ΅Ρ€Π΅Π΄Π°Π½Π½Ρ‹Π΅ React- ΠΈ Next.js-спрайты с поиском, настройкой Ρ†Π²Π΅Ρ‚ΠΎΠ² ΠΈ ΠΏΡ€ΠΈΠΌΠ΅Ρ€Π°ΠΌΠΈ использования. +- **НастраиваСмыС трансформации SVG** β€” ΡƒΠ΄Π°Π»Π΅Π½ΠΈΠ΅ `width` ΠΈ `height` с сохранСниСм `viewBox`, Π·Π°ΠΌΠ΅Π½Π° исходных Ρ†Π²Π΅Ρ‚ΠΎΠ² Π½Π° CSS-ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½Ρ‹Π΅ ΠΈ transitions для `fill` ΠΈ `stroke`. +- **ΠžΡ‚Π΄Π΅Π»ΡŒΠ½Ρ‹ΠΉ ΠΊΠ΅ΡˆΠΈΡ€ΡƒΠ΅ΠΌΡ‹ΠΉ SVG asset** β€” SVG path-Π΄Π°Π½Π½Ρ‹Π΅ Π½Π΅ ΠΏΠΎΠΏΠ°Π΄Π°ΡŽΡ‚ Π² JavaScript chunks, Π° сборщик выпускаСт Ρ„Π°ΠΉΠ» с content hash. +- **ΠœΠ½ΠΎΠΆΠ΅ΡΡ‚Π²Π΅Π½Π½Ρ‹Π΅ спрайты** β€” нСзависимыС React- ΠΈ Next.js-ΠΌΠΎΠ΄ΡƒΠ»ΠΈ со своими ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Π°ΠΌΠΈ, Ρ‚ΠΈΠΏΠ°ΠΌΠΈ ΠΈ SVG assets. +- **Server-first Next.js** β€” generated-ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Ρ‹ Ρ€Π°Π±ΠΎΡ‚Π°ΡŽΡ‚ Π² Server Components, SSR ΠΈ SSG Π±Π΅Π· Π΄ΠΈΡ€Π΅ΠΊΡ‚ΠΈΠ²Ρ‹ `'use client'`. +- **Π€ΠΎΡ€ΠΌΠ°Ρ‚Ρ‹ ΠΏΠΎΠ΄ Ρ€Π°Π·Π½Ρ‹Π΅ сцСнарии** β€” React ΠΈ Next.js ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΡŽΡ‚ `stack`, legacy-Ρ€Π΅ΠΆΠΈΠΌ Ρ‚Π°ΠΊΠΆΠ΅ ΠΏΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΈΠ²Π°Π΅Ρ‚ `symbol` для ΡΡƒΡ‰Π΅ΡΡ‚Π²ΡƒΡŽΡ‰ΠΈΡ… ΠΈΠ½Ρ‚Π΅Π³Ρ€Π°Ρ†ΠΈΠΉ. + +## Π’Π°Π±Π»ΠΈΡ†Π° ΠΏΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΊΠΈ + +| Π‘Ρ€Π΅Π΄Π° | ΠšΠ»ΡŽΡ‡ ΠΌΠΎΠ΄Π° API | Бтатус | +|---|---|---| +| React + Vite | `react@vite` | Π“ΠΎΡ‚ΠΎΠ²ΠΎ | +| React + Webpack 5 | `react@webpack` | Π“ΠΎΡ‚ΠΎΠ²ΠΎ | +| Next.js 16.2+ App Router + Turbopack | `next@app/turbopack` | Π“ΠΎΡ‚ΠΎΠ²ΠΎ | +| Next.js 13.4+ App Router + Webpack 5 | `next@app/webpack` | Π“ΠΎΡ‚ΠΎΠ²ΠΎ | +| Next.js 16.2+ Pages Router + Turbopack | `next@pages/turbopack` | Π“ΠΎΡ‚ΠΎΠ²ΠΎ | +| Next.js 12.2+ Pages Router + Webpack 5 | `next@pages/webpack` | Π“ΠΎΡ‚ΠΎΠ²ΠΎ | +| Vue | β€” | Π‘ΠΊΠΎΡ€ΠΎ | +| Standalone | β€” | Π‘ΠΊΠΎΡ€ΠΎ | + +## ВрСбования + +- Node.js 18 ΠΈΠ»ΠΈ Π½ΠΎΠ²Π΅Π΅; +- ΠΏΠ°ΠΊΠ΅Ρ‚ распространяСтся Ρ‚ΠΎΠ»ΡŒΠΊΠΎ ΠΊΠ°ΠΊ ESM ΠΈ ΠΏΠΎΠ΄ΠΊΠ»ΡŽΡ‡Π°Π΅Ρ‚ΡΡ Ρ‡Π΅Ρ€Π΅Π· `import`; +- React 18 ΠΈΠ»ΠΈ 19 трСбуСтся Ρ‚ΠΎΠ»ΡŒΠΊΠΎ для generated-ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚ΠΎΠ² ΠΈ Ρ‚ΠΎΡ‡ΠΊΠΈ Π²Ρ…ΠΎΠ΄Π° `@gromlab/svg-sprites/react`; +- для Ρ‚ΠΈΠΏΠΈΠ·Π°Ρ†ΠΈΠΈ subpath exports ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠΉΡ‚Π΅ TypeScript 5+ с `moduleResolution: "bundler"`, `"node16"` ΠΈΠ»ΠΈ `"nodenext"`. + +## Быстрый старт + +Для быстрого старта Π²ΠΎΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠΉΡ‚Π΅ΡΡŒ инструкциСй для вашСго стСка: + +- [React + Vite](docs/ru/react-vite.md) +- [React + Webpack 5](docs/ru/react-webpack.md) +- [Next.js App Router](docs/ru/next-app.md) +- [Next.js Pages Router](docs/ru/next-pages.md) + +## ΠšΠΎΠ½Ρ„ΠΈΠ³ΡƒΡ€Π°Ρ†ΠΈΡ + +### React + +```ts +import { defineReactSpriteConfig } from '@gromlab/svg-sprites' + +export default defineReactSpriteConfig({ + name: 'file-manager', + description: 'Иконки Ρ„Π°ΠΉΠ»ΠΎΠ²ΠΎΠ³ΠΎ ΠΌΠ΅Π½Π΅Π΄ΠΆΠ΅Ρ€Π°', + inputFolder: './icons', + inputFiles: [ + '../../shared/icons/check.svg', + ], + transform: { + removeSize: true, + replaceColors: true, + addTransition: true, + }, + generatedNotice: true, +}) +``` + +| ΠžΠΏΡ†ΠΈΡ | Π’ΠΈΠΏ | По ΡƒΠΌΠΎΠ»Ρ‡Π°Π½ΠΈΡŽ | НазначСниС | +|---|---|---|---| +| `name` | `string` | Имя ΠΏΠ°ΠΏΠΊΠΈ | Имя спрайта, ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Π° ΠΈ ΠΏΡƒΠ±Π»ΠΈΡ‡Π½Ρ‹Ρ… Ρ‚ΠΈΠΏΠΎΠ² | +| `description` | `string` | НСт | ОписаниС для Ρ‚ΠΈΠΏΠΎΠ² ΠΈ debug-манифСста | +| `inputFolder` | `string` | `./icons` | Папка с исходными SVG ΠΎΡ‚Π½ΠΎΡΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎ ΠΊΠΎΠ½Ρ„ΠΈΠ³Π° | +| `inputFiles` | `string[]` | `[]` | Π”ΠΎΠΏΠΎΠ»Π½ΠΈΡ‚Π΅Π»ΡŒΠ½Ρ‹Π΅ SVG-Ρ„Π°ΠΉΠ»Ρ‹ ΠΎΡ‚Π½ΠΎΡΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎ ΠΊΠΎΠ½Ρ„ΠΈΠ³Π° | +| `transform` | `TransformOptions` | ВсС Π²ΠΊΠ»ΡŽΡ‡Π΅Π½Ρ‹ | [Настройки трансформации](#трансформации) исходных SVG | +| `generatedNotice` | `boolean` | `true` | ПолноС Π»ΠΈΠ±ΠΎ ΠΊΠΎΡ€ΠΎΡ‚ΠΊΠΎΠ΅ ΠΏΡ€Π΅Π΄ΡƒΠΏΡ€Π΅ΠΆΠ΄Π΅Π½ΠΈΠ΅ Π² generated-Ρ„Π°ΠΉΠ»Π°Ρ… | + +`inputFolder` ΠΈ `inputFiles` ΠΎΠ±ΡŠΠ΅Π΄ΠΈΠ½ΡΡŽΡ‚ΡΡ Π² ΠΎΠ΄ΠΈΠ½ спрайт, поэтому ΠΎΠ΄ΠΈΠ½ SVG-Ρ„Π°ΠΉΠ» ΠΌΠΎΠΆΠ½ΠΎ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ Π² Π½Π΅ΡΠΊΠΎΠ»ΡŒΠΊΠΈΡ… спрайтах Π±Π΅Π· копирования. Если нСявной ΠΏΠ°ΠΏΠΊΠΈ `./icons` Π½Π΅Ρ‚, Π½ΠΎ `inputFiles` Π·Π°ΠΏΠΎΠ»Π½Π΅Π½, гСнСрация продолТаСтся Ρ‚ΠΎΠ»ΡŒΠΊΠΎ ΠΏΠΎ списку. Π―Π²Π½ΠΎ указанная ΠΎΡ‚ΡΡƒΡ‚ΡΡ‚Π²ΡƒΡŽΡ‰Π°Ρ ΠΏΠ°ΠΏΠΊΠ° считаСтся ошибкой. ΠžΠ΄ΠΈΠ½Π°ΠΊΠΎΠ²Ρ‹Π΅ ΠΏΡƒΡ‚ΠΈ Π΄Π΅Π΄ΡƒΠΏΠ»ΠΈΡ†ΠΈΡ€ΡƒΡŽΡ‚ΡΡ, Π° Ρ€Π°Π·Π½Ρ‹Π΅ Ρ„Π°ΠΉΠ»Ρ‹ с ΠΎΠ΄ΠΈΠ½Π°ΠΊΠΎΠ²Ρ‹ΠΌ ΠΈΠΌΠ΅Π½Π΅ΠΌ ΠΈΠΊΠΎΠ½ΠΊΠΈ ΡΡ‡ΠΈΡ‚Π°ΡŽΡ‚ΡΡ ошибкой. + +`name` записываСтся Π² kebab-case ΠΈ Π΄ΠΎΠ»ΠΆΠ½ΠΎ Π½Π°Ρ‡ΠΈΠ½Π°Ρ‚ΡŒΡΡ с латинской Π±ΡƒΠΊΠ²Ρ‹. React ΠΈ Next.js presets ΡΠΎΠ·Π΄Π°ΡŽΡ‚ Ρ„ΠΎΡ€ΠΌΠ°Ρ‚ `stack`. + +### Next.js + +Next.js ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ Ρ‚ΠΎΡ‚ ΠΆΠ΅ `svg-sprite.config.ts` ΠΈ Π½Π°Π±ΠΎΡ€ ΠΎΠΏΡ†ΠΈΠΉ. Для Ρ‚ΠΈΠΏΠΈΠ·Π°Ρ†ΠΈΠΈ ΠΌΠΎΠΆΠ½ΠΎ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ ΠΎΡ‚Π΄Π΅Π»ΡŒΠ½Ρ‹ΠΉ Ρ…Π΅Π»ΠΏΠ΅Ρ€: + +```ts +import { defineNextSpriteConfig } from '@gromlab/svg-sprites' + +export default defineNextSpriteConfig({ + name: 'file-manager', + description: 'Иконки Ρ„Π°ΠΉΠ»ΠΎΠ²ΠΎΠ³ΠΎ ΠΌΠ΅Π½Π΅Π΄ΠΆΠ΅Ρ€Π°', + inputFolder: './icons', +}) +``` + +Π ΠΎΡƒΡ‚Π΅Ρ€ ΠΈ сборщик Π²Ρ‹Π±ΠΈΡ€Π°ΡŽΡ‚ΡΡ Ρ‡Π΅Ρ€Π΅Π· mode key, поэтому ΠΏΠ΅Ρ€Π΅ΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅ ΠΌΠ΅ΠΆΠ΄Ρƒ Turbopack ΠΈ Webpack всСгда явно ΠΎΡ‚Ρ€Π°ΠΆΠ΅Π½ΠΎ Π² ΠΊΠΎΠΌΠ°Π½Π΄Π΅ Π³Π΅Π½Π΅Ρ€Π°Ρ†ΠΈΠΈ. + +## ΠœΠ½ΠΎΠΆΠ΅ΡΡ‚Π²Π΅Π½Π½Ρ‹Π΅ спрайты + +ΠŸΡ€ΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅ ΠΌΠΎΠΆΠ΅Ρ‚ ΡΠΎΠ΄Π΅Ρ€ΠΆΠ°Ρ‚ΡŒ нСсколько нСзависимых спрайтов с Ρ€Π°Π·Π½ΠΎΠΉ ΠΎΠ±Π»Π°ΡΡ‚ΡŒΡŽ использования: + +**ΠŸΡ€ΠΎΠ±Π»Π΅ΠΌΠ°:** ΠΎΠ΄ΠΈΠ½ Π³Π»ΠΎΠ±Π°Π»ΡŒΠ½Ρ‹ΠΉ спрайт Π·Π°Π³Ρ€ΡƒΠΆΠ°Π΅Ρ‚ ΠΈΠΊΠΎΠ½ΠΊΠΈ, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ Ρ‚Π΅ΠΊΡƒΡ‰Π΅ΠΌΡƒ экрану Π½Π΅ Π½ΡƒΠΆΠ½Ρ‹. + +**РСшСниС:** ΠΎΠ±Ρ‰ΠΈΠ΅ ΠΈΠΊΠΎΠ½ΠΊΠΈ Ρ…Ρ€Π°Π½ΠΈΡ‚ΡŒ глобально, Π° Π½Π°Π±ΠΎΡ€Ρ‹ страниц ΠΈ ΠΊΡ€ΡƒΠΏΠ½Ρ‹Ρ… ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚ΠΎΠ² β€” Π² ΠΎΡ‚Π΄Π΅Π»ΡŒΠ½Ρ‹Ρ… спрайтах, Π·Π°Π³Ρ€ΡƒΠΆΠ°Π΅ΠΌΡ‹Ρ… вмСстС с Π½ΠΈΠΌΠΈ. + +```text +global β†’ GlobalIcon β†’ ΠΎΠ±Ρ‰ΠΈΠ΅ ΠΈΠΊΠΎΠ½ΠΊΠΈ прилоТСния +analytics-page β†’ AnalyticsPageIcon β†’ ΠΈΠΊΠΎΠ½ΠΊΠΈ ΠΎΡ‚Π΄Π΅Π»ΡŒΠ½ΠΎΠΉ страницы +file-manager β†’ FileManagerIcon β†’ ΠΈΠΊΠΎΠ½ΠΊΠΈ ΠΊΡ€ΡƒΠΏΠ½ΠΎΠ³ΠΎ ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Π° +``` + +- **Π“Π»ΠΎΠ±Π°Π»ΡŒΠ½Ρ‹ΠΉ спрайт** содСрТит нСбольшиС ΠΎΠ±Ρ‰ΠΈΠ΅ ΠΈΠΊΠΎΠ½ΠΊΠΈ, ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅ΠΌΡ‹Π΅ Π² Ρ€Π°Π·Π½Ρ‹Ρ… частях прилоТСния: Π½Π°Π²ΠΈΠ³Π°Ρ†ΠΈΡŽ, состояния ΠΈ Π±Π°Π·ΠΎΠ²Ρ‹Π΅ дСйствия. +- **Π‘ΠΏΡ€Π°ΠΉΡ‚ страницы** загруТаСтся вмСстС с ΠΊΠΎΠ½ΠΊΡ€Π΅Ρ‚Π½Ρ‹ΠΌ Ρ€Π°Π·Π΄Π΅Π»ΠΎΠΌ ΠΈ Π½Π΅ ΡƒΠ²Π΅Π»ΠΈΡ‡ΠΈΠ²Π°Π΅Ρ‚ ΠΎΠ±Ρ‰ΠΈΠΉ спрайт ΠΈΠΊΠΎΠ½ΠΊΠ°ΠΌΠΈ, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ большС Π½ΠΈΠ³Π΄Π΅ Π½Π΅ Π½ΡƒΠΆΠ½Ρ‹. +- **Π‘ΠΏΡ€Π°ΠΉΡ‚ ΠΊΡ€ΡƒΠΏΠ½ΠΎΠ³ΠΎ ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Π°** инкапсулируСт собствСнный Π½Π°Π±ΠΎΡ€ ΠΈΠΊΠΎΠ½ΠΎΠΊ слоТного UI-модуля, Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€ Ρ„Π°ΠΉΠ»ΠΎΠ²ΠΎΠ³ΠΎ ΠΌΠ΅Π½Π΅Π΄ΠΆΠ΅Ρ€Π° ΠΈΠ»ΠΈ Ρ€Π΅Π΄Π°ΠΊΡ‚ΠΎΡ€Π°. + +КаТдая Π³Ρ€ΡƒΠΏΠΏΠ° ΠΏΠΎΠ»ΡƒΡ‡Π°Π΅Ρ‚: + +- собствСнный SVG asset; +- собствСнный Ρ‚ΠΈΠΏΠΈΠ·ΠΈΡ€ΠΎΠ²Π°Π½Π½Ρ‹ΠΉ ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚; +- ΠΎΡ‚Π΄Π΅Π»ΡŒΠ½Ρ‹ΠΉ список ΠΈΠΌΡ‘Π½ ΠΈΠΊΠΎΠ½ΠΎΠΊ; +- ΠΎΡ‚Π΄Π΅Π»ΡŒΠ½Ρ‹ΠΉ debug-манифСст; +- нСзависимый cache lifecycle. + + +## TypeScript + +Главная Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎΡΡ‚ΡŒ TypeScript API β€” Π°Π²Ρ‚ΠΎΠ΄ΠΎΠΏΠΎΠ»Π½Π΅Π½ΠΈΠ΅ ΠΈΠΌΡ‘Π½ ΠΈΠΊΠΎΠ½ΠΎΠΊ нСпосрСдствСнно Π² prop `icon`: + +```tsx + +// ↑ Ρ€Π΅Π΄Π°ΠΊΡ‚ΠΎΡ€ ΠΏΡ€Π΅Π΄Π»Π°Π³Π°Π΅Ρ‚ всС ΠΈΠΊΠΎΠ½ΠΊΠΈ спрайта +``` + +ИмСна SVG-Ρ„Π°ΠΉΠ»ΠΎΠ² становятся допустимыми значСниями `icon`. ΠžΠΏΠ΅Ρ‡Π°Ρ‚ΠΊΠ° ΠΈΠ»ΠΈ нСизвСстноС имя сразу становятся ошибкой TypeScript: + +```tsx + // ошибка TypeScript +``` + +Для ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠ½ΠΎΠ³ΠΎ доступа generated-ΠΌΠΎΠ΄ΡƒΠ»ΡŒ экспортируСт readonly-массив всСх доступных ΠΈΠΊΠΎΠ½ΠΎΠΊ ΠΊΠΎΠ½ΠΊΡ€Π΅Ρ‚Π½ΠΎΠ³ΠΎ спрайта: + +```ts +import { fileManagerIconNames } from './svg-sprite' + +// readonly ['check', 'folder', ...] +``` + +Π­Ρ‚ΠΎΡ‚ список ΠΌΠΎΠΆΠ½ΠΎ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ Π² собствСнных ΠΊΠ°Ρ‚Π°Π»ΠΎΠ³Π°Ρ…, select-ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Π°Ρ…, тСстах ΠΈ Π΄Ρ€ΡƒΠ³ΠΈΡ… runtime-сцСнариях. Из Π½Π΅Π³ΠΎ Ρ‚Π°ΠΊΠΆΠ΅ выводится union-Ρ‚ΠΈΠΏ `FileManagerIconName`. + +ИмСна Ρ„Π°ΠΉΠ»ΠΎΠ² с ΠΏΡ€ΠΎΠ±Π΅Π»Π°ΠΌΠΈ ΠΈ Π΄Ρ€ΡƒΠ³ΠΈΠΌΠΈ нСбСзопасными для SVG ID символами ΠΎΡΡ‚Π°ΡŽΡ‚ΡΡ Ρ‡Π°ΡΡ‚ΡŒΡŽ ΠΏΡƒΠ±Π»ΠΈΡ‡Π½ΠΎΠ³ΠΎ TypeScript API. Для Π²Π½ΡƒΡ‚Ρ€Π΅Π½Π½Π΅Π³ΠΎ `` Π³Π΅Π½Π΅Ρ€Π°Ρ‚ΠΎΡ€ создаёт ΡΡ‚Π°Π±ΠΈΠ»ΡŒΠ½Ρ‹ΠΉ hash ID. + +```text +folder open.svg β†’ icon="folder open" β†’ id="icon-" +``` + +Для Ρ‚Π°ΠΊΠΈΡ… ΠΈΠΌΡ‘Π½ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠΉΡ‚Π΅ generated-ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚ ΠΈΠ»ΠΈ `id` ΠΈΠ· debug-манифСста. Π ΡƒΡ‡Π½Ρ‹Π΅ ΠΏΡ€ΠΈΠΌΠ΅Ρ€Ρ‹ Π½ΠΈΠΆΠ΅ с `#<имя>` подходят Ρ‚ΠΎΠ»ΡŒΠΊΠΎ для ΠΈΠΌΡ‘Π½, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ ΡƒΠΆΠ΅ ΡΠ²Π»ΡΡŽΡ‚ΡΡ бСзопасными SVG ID. + +## Π€ΠΎΡ€ΠΌΠ°Ρ‚Ρ‹ спрайтов + +`stack` β€” Π±ΠΎΠ»Π΅Π΅ соврСмСнный Ρ„ΠΎΡ€ΠΌΠ°Ρ‚, поэтому ΠΎΠ½ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ΡΡ ΠΏΠΎ ΡƒΠΌΠΎΠ»Ρ‡Π°Π½ΠΈΡŽ. Иконки ΠΌΠΎΠΆΠ½ΠΎ ΠΎΡ‚ΠΎΠ±Ρ€Π°ΠΆΠ°Ρ‚ΡŒ Ρ‡Π΅Ρ€Π΅Π· ``, `` ΠΈ CSS `background-image`. + +`symbol` сохраняСтся для совмСстимости с ΡΡƒΡ‰Π΅ΡΡ‚Π²ΡƒΡŽΡ‰ΠΈΠΌΠΈ интСграциями ΠΈ ΠΏΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΈΠ²Π°Π΅Ρ‚ ΠΎΡ‚ΠΎΠ±Ρ€Π°ΠΆΠ΅Π½ΠΈΠ΅ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ Ρ‡Π΅Ρ€Π΅Π· ``. + +## Бпособы отобраТСния + +### React-ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚ β€” рСкомСндуСтся + +Generated-ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚ прСдоставляСт Ρ‚ΠΈΠΏΠΈΠ·Π°Ρ†ΠΈΡŽ, Π°Π²Ρ‚ΠΎΠ΄ΠΎΠΏΠΎΠ»Π½Π΅Π½ΠΈΠ΅ ΠΈΠΌΡ‘Π½ ΠΈΠΊΠΎΠ½ΠΎΠΊ ΠΈ сам Ρ„ΠΎΡ€ΠΌΠΈΡ€ΡƒΠ΅Ρ‚ URL SVG asset. + +```tsx + +``` + +Π§Π΅Ρ€Π΅Π· `color` ΠΈ `--icon-color-N` доступны ΠΎΠ΄Π½ΠΎΡ†Π²Π΅Ρ‚Π½Ρ‹Π΅ ΠΈ ΠΌΠ½ΠΎΠ³ΠΎΡ†Π²Π΅Ρ‚Π½Ρ‹Π΅ ΠΈΠΊΠΎΠ½ΠΊΠΈ. + +### Π‘Π°ΠΌΠΎΡΡ‚ΠΎΡΡ‚Π΅Π»ΡŒΠ½ΠΎ Ρ‡Π΅Ρ€Π΅Π· `` + +Π₯ΠΎΡ€ΠΎΡˆΠΈΠΉ Π½ΠΈΠ·ΠΊΠΎΡƒΡ€ΠΎΠ²Π½Π΅Π²Ρ‹ΠΉ способ с ΠΏΠΎΠ»Π½Ρ‹ΠΌ ΡƒΠΏΡ€Π°Π²Π»Π΅Π½ΠΈΠ΅ΠΌ Ρ€Π°Π·ΠΌΠ΅Ρ€Π°ΠΌΠΈ ΠΈ Ρ†Π²Π΅Ρ‚Π°ΠΌΠΈ. React-ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚ ΠΏΠΎΠ΄ ΠΊΠ°ΠΏΠΎΡ‚ΠΎΠΌ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ ΠΈΠΌΠ΅Π½Π½ΠΎ Π΅Π³ΠΎ. + +Бпособ получСния `spriteUrl` зависит ΠΎΡ‚ сборщика. + +**Vite:** + +```tsx +import spriteUrl from './svg-sprite/generated/sprite.svg?no-inline' +``` + +**Webpack 5:** + +```tsx +const spriteUrl = new URL( + './svg-sprite/generated/sprite.svg', + import.meta.url, +).href +``` + +**Next.js с Webpack 5 ΠΈΠ»ΠΈ Turbopack:** + +```tsx +const spriteUrl = new URL( + './svg-sprite/generated/sprite.svg', + import.meta.url, +).href +``` + +ПослС получСния URL ΠΈΠΊΠΎΠ½ΠΊΠ° отобраТаСтся ΠΎΠ΄ΠΈΠ½Π°ΠΊΠΎΠ²ΠΎ: + +```tsx + + + +``` + +Vite, Webpack 5 ΠΈ Next.js сами Π·Π°ΠΌΠ΅Π½ΡΡŽΡ‚ исходный ΠΏΡƒΡ‚ΡŒ Π½Π° ΠΈΡ‚ΠΎΠ³ΠΎΠ²Ρ‹ΠΉ URL asset с hash. + +### Π§Π΅Ρ€Π΅Π· `` β€” ΠΌΠ΅Π½Π΅Π΅ эффСктивно + +```tsx +Π“ΠΎΡ‚ΠΎΠ²ΠΎ +``` + +SVG загруТаСтся ΠΊΠ°ΠΊ ΠΈΠ·ΠΎΠ»ΠΈΡ€ΠΎΠ²Π°Π½Π½ΠΎΠ΅ ΠΈΠ·ΠΎΠ±Ρ€Π°ΠΆΠ΅Π½ΠΈΠ΅: ΠΈΠ·ΠΌΠ΅Π½ΠΈΡ‚ΡŒ Π΅Π³ΠΎ Ρ†Π²Π΅Ρ‚Π° Ρ‡Π΅Ρ€Π΅Π· `color` ΠΈΠ»ΠΈ `--icon-color-N` нСльзя. + +### Π§Π΅Ρ€Π΅Π· CSS `background-image` β€” ΠΌΠ΅Π½Π΅Π΅ эффСктивно + +```css +.icon { + background: url('./svg-sprite/generated/sprite.svg#check') center / contain no-repeat; +} +``` + +Как ΠΈ ``, этот способ Π½Π΅ позволяСт ΡƒΠΏΡ€Π°Π²Π»ΡΡ‚ΡŒ Π²Π½ΡƒΡ‚Ρ€Π΅Π½Π½ΠΈΠΌΠΈ Ρ†Π²Π΅Ρ‚Π°ΠΌΠΈ SVG. ΠŸΡƒΡ‚ΡŒ указываСтся ΠΎΡ‚Π½ΠΎΡΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎ CSS-Ρ„Π°ΠΉΠ»Π°, Π° Vite/Webpack замСняСт Π΅Π³ΠΎ Π½Π° ΠΈΡ‚ΠΎΠ³ΠΎΠ²Ρ‹ΠΉ URL с hash ΠΏΡ€ΠΈ сборкС. + +### Π§Π΅Ρ€Π΅Π· CSS mask β€” ΠΌΠ΅Π½Π΅Π΅ эффСктивно + +```css +.icon { + background-color: currentColor; + mask: url('./svg-sprite/generated/sprite.svg#check') center / contain no-repeat; +} +``` + +Mask оставляСт Ρ‚ΠΎΠ»ΡŒΠΊΠΎ силуэт ΠΈ ΠΎΠΊΡ€Π°ΡˆΠΈΠ²Π°Π΅Ρ‚ Π΅Π³ΠΎ ΠΎΠ΄Π½ΠΈΠΌ Ρ†Π²Π΅Ρ‚ΠΎΠΌ. Π˜ΡΡ…ΠΎΠ΄Π½Ρ‹Π΅ Ρ†Π²Π΅Ρ‚Π°, gradients ΠΈ различия ΠΌΠ΅ΠΆΠ΄Ρƒ `fill` ΠΈ `stroke` Ρ‚Π΅Ρ€ΡΡŽΡ‚ΡΡ. + +## Врансформации + +ВсС трансформации Π²ΠΊΠ»ΡŽΡ‡Π΅Π½Ρ‹ ΠΏΠΎ ΡƒΠΌΠΎΠ»Ρ‡Π°Π½ΠΈΡŽ ΠΈ Π½Π°ΡΡ‚Ρ€Π°ΠΈΠ²Π°ΡŽΡ‚ΡΡ нСзависимо Ρ‡Π΅Ρ€Π΅Π· `transform`. + +| ΠžΠΏΡ†ΠΈΡ | По ΡƒΠΌΠΎΠ»Ρ‡Π°Π½ΠΈΡŽ | Π§Ρ‚ΠΎ Π΄Π΅Π»Π°Π΅Ρ‚ | +|---|---|---| +| `removeSize` | `true` | УдаляСт `width` ΠΈ `height` с ΠΊΠΎΡ€Π½Π΅Π²ΠΎΠ³ΠΎ ``, сохраняя ΡΡƒΡ‰Π΅ΡΡ‚Π²ΡƒΡŽΡ‰ΠΈΠΉ `viewBox`. Π Π°Π·ΠΌΠ΅Ρ€ ΠΈΠΊΠΎΠ½ΠΊΠΈ послС этого задаётся снаруТи. | +| `replaceColors` | `true` | ЗамСняСт Ρ†Π²Π΅Ρ‚Π° `fill` ΠΈ `stroke` Π½Π° `--icon-color-N`. Для ΠΎΠ΄Π½ΠΎΡ†Π²Π΅Ρ‚Π½ΠΎΠΉ ΠΈΠΊΠΎΠ½ΠΊΠΈ fallback становится `currentColor`, для ΠΌΠ½ΠΎΠ³ΠΎΡ†Π²Π΅Ρ‚Π½ΠΎΠΉ ΡΠΎΡ…Ρ€Π°Π½ΡΡŽΡ‚ΡΡ исходныС Ρ†Π²Π΅Ρ‚Π°. | +| `addTransition` | `true` | ДобавляСт `style="transition:fill 0.3s,stroke 0.3s;"` нСпосрСдствСнно Ρ†Π²Π΅Ρ‚Π½Ρ‹ΠΌ элСмСнтам SVG. Π‘ΡƒΡ‰Π΅ΡΡ‚Π²ΡƒΡŽΡ‰ΠΈΠΉ `transition` Π½Π΅ пСрСзаписываСтся. | + +Π§Ρ‚ΠΎΠ±Ρ‹ ΠΎΡ‚ΠΊΠ»ΡŽΡ‡ΠΈΡ‚ΡŒ ΠΏΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΠΎΠ²Π°Π½ΠΈΠ΅, ΠΏΠ΅Ρ€Π΅Π΄Π°ΠΉΡ‚Π΅ для ΡΠΎΠΎΡ‚Π²Π΅Ρ‚ΡΡ‚Π²ΡƒΡŽΡ‰Π΅ΠΉ ΠΎΠΏΡ†ΠΈΠΈ `false`. ΠŸΠΎΠ΄Ρ€ΠΎΠ±Π½Π΅Π΅ ΠΎ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Π΅ `replaceColors` β€” Π² Ρ€Π°Π·Π΄Π΅Π»Π΅ [Β«Π£ΠΏΡ€Π°Π²Π»Π΅Π½ΠΈΠ΅ Ρ†Π²Π΅Ρ‚ΠΎΠΌ ΠΈΠΊΠΎΠ½ΠΎΠΊΒ»](#ΡƒΠΏΡ€Π°Π²Π»Π΅Π½ΠΈΠ΅-Ρ†Π²Π΅Ρ‚ΠΎΠΌ-ΠΈΠΊΠΎΠ½ΠΎΠΊ). + +## Π£ΠΏΡ€Π°Π²Π»Π΅Π½ΠΈΠ΅ Ρ†Π²Π΅Ρ‚ΠΎΠΌ ΠΈΠΊΠΎΠ½ΠΎΠΊ + +ΠŸΡ€ΠΈ Π²ΠΊΠ»ΡŽΡ‡Ρ‘Π½Π½ΠΎΠΉ Π·Π°ΠΌΠ΅Π½Π΅ Ρ†Π²Π΅Ρ‚ΠΎΠ² Π³Π΅Π½Π΅Ρ€Π°Ρ‚ΠΎΡ€ Π°Π½Π°Π»ΠΈΠ·ΠΈΡ€ΡƒΠ΅Ρ‚ `fill` ΠΈ `stroke` ΠΈ ΠΏΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΡƒΠ΅Ρ‚ ΠΈΡ… Π² CSS custom properties. + +### ΠœΠΎΠ½ΠΎΡ…Ρ€ΠΎΠΌΠ½Ρ‹Π΅ ΠΈΠΊΠΎΠ½ΠΊΠΈ + +Если Π½Π°ΠΉΠ΄Π΅Π½ ΠΎΠ΄ΠΈΠ½ Ρ†Π²Π΅Ρ‚, fallback замСняСтся Π½Π° `currentColor`: + +```svg +stroke="var(--icon-color-1, currentColor)" +``` + +Π¦Π²Π΅Ρ‚ΠΎΠΌ управляСт CSS-свойство `color` внСшнСго `` ΠΈΠ»ΠΈ Π΅Π³ΠΎ родитСля. + +### ΠœΠ½ΠΎΠ³ΠΎΡ†Π²Π΅Ρ‚Π½Ρ‹Π΅ ΠΈΠΊΠΎΠ½ΠΊΠΈ + +ΠšΠ°ΠΆΠ΄Ρ‹ΠΉ ΡƒΠ½ΠΈΠΊΠ°Π»ΡŒΠ½Ρ‹ΠΉ Ρ†Π²Π΅Ρ‚ ΠΏΠΎΠ»ΡƒΡ‡Π°Π΅Ρ‚ ΠΎΡ‚Π΄Π΅Π»ΡŒΠ½ΡƒΡŽ ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½ΡƒΡŽ с исходным fallback: + +```svg +fill="var(--icon-color-1, #798198)" +fill="var(--icon-color-2, #ffffff)" +fill="var(--icon-color-3, #129d9d)" +``` + +Π‘Ρ‚Ρ€Π°Π½ΠΈΡ†Π° ΠΌΠΎΠΆΠ΅Ρ‚ Π·Π°ΠΌΠ΅Π½ΠΈΡ‚ΡŒ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΡ‹Π΅ Ρ†Π²Π΅Ρ‚Π°: + +```css +.icon { + --icon-color-1: #4b5563; + --icon-color-3: #14b8a6; +} +``` + +### ΠžΠ³Ρ€Π°Π½ΠΈΡ‡Π΅Π½ΠΈΡ Ρ†Π²Π΅Ρ‚ΠΎΠ² + +- `none`, `transparent`, `inherit`, `unset` ΠΈ `initial` Π½Π΅ Π·Π°ΠΌΠ΅Π½ΡΡŽΡ‚ΡΡ; +- Ρ†Π²Π΅Ρ‚Π° Π² Π°Ρ‚Ρ€ΠΈΠ±ΡƒΡ‚Π°Ρ… `fill`, `stroke` ΠΈ inline `style` ΠΎΠ±Ρ€Π°Π±Π°Ρ‚Ρ‹Π²Π°ΡŽΡ‚ΡΡ Π½Π°Π΄Ρ‘ΠΆΠ½Π΅Π΅ всСго; +- CSS-классы ΠΈ внСшниС stylesheets Π²Π½ΡƒΡ‚Ρ€ΠΈ исходного SVG Π½Π΅ ΡΠ²Π»ΡΡŽΡ‚ΡΡ основным сцСнариСм трансформации; +- gradients, patterns, filters ΠΈ значСния `url(#...)` Ρ‚Ρ€Π΅Π±ΡƒΡŽΡ‚ ΠΎΡ‚Π΄Π΅Π»ΡŒΠ½ΠΎΠΉ ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΊΠΈ ΠΈ ΠΌΠΎΠ³ΡƒΡ‚ Π±Ρ‹Ρ‚ΡŒ нСсовмСстимы с автоматичСской Π·Π°ΠΌΠ΅Π½ΠΎΠΉ Ρ†Π²Π΅Ρ‚ΠΎΠ²; +- CSS-ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½Ρ‹Π΅ страницы доступны ΠΏΡ€ΠΈ ``, Π½ΠΎ нСдоступны Π²Π½ΡƒΡ‚Ρ€ΠΈ `` ΠΈ `background-image`. + +## ΠšΠ΅ΡˆΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠ΅ + +Vite, Webpack ΠΈ Next.js target Π²Ρ‹ΠΏΡƒΡΠΊΠ°ΡŽΡ‚ спрайт ΠΎΡ‚Π΄Π΅Π»ΡŒΠ½Ρ‹ΠΌ asset с content hash: + +```text +/assets/sprite-.svg +``` + +Π­Ρ‚ΠΎ Π΄Π°Ρ‘Ρ‚ ΡΠ»Π΅Π΄ΡƒΡŽΡ‰ΠΈΠ΅ свойства: + +- SVG ΠΊΠ΅ΡˆΠΈΡ€ΡƒΠ΅Ρ‚ΡΡ нСзависимо ΠΎΡ‚ JavaScript; +- ΠΈΠ·ΠΌΠ΅Π½Π΅Π½ΠΈΠ΅ React-ΠΊΠΎΠ΄Π° Π½Π΅ мСняСт содСрТимоС спрайта; +- ΠΈΠ·ΠΌΠ΅Π½Π΅Π½ΠΈΠ΅ ΠΈΠΊΠΎΠ½ΠΎΠΊ создаёт Π½ΠΎΠ²Ρ‹ΠΉ hash asset; +- ΠΎΠ΄ΠΈΠ½ Ρ„Π°ΠΉΠ» ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ΡΡ всСми экзСмплярами generated-ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Π°; +- SVG path-Π΄Π°Π½Π½Ρ‹Π΅ ΠΎΡ‚ΡΡƒΡ‚ΡΡ‚Π²ΡƒΡŽΡ‚ Π² JavaScript chunks. + +Vite target Π·Π°ΠΏΡ€Π΅Ρ‰Π°Π΅Ρ‚ inline Ρ‡Π΅Ρ€Π΅Π· `?no-inline`. Webpack 5 target ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ Asset Modules Ρ‡Π΅Ρ€Π΅Π· `new URL(..., import.meta.url)`. + +## SpriteViewer + +`SpriteViewer` β€” React-ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚ для просмотра generated-спрайтов Π²Π½ΡƒΡ‚Ρ€ΠΈ debug-ΠΌΠ°Ρ€ΡˆΡ€ΡƒΡ‚Π° прилоТСния. + +Он ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ ΠΎΡ‚Π΄Π΅Π»ΡŒΠ½Ρ‹Π΅ манифСсты ΠΈ ΠΏΠΎΠΊΠ°Π·Ρ‹Π²Π°Π΅Ρ‚: + +- Π³Ρ€ΡƒΠΏΠΏΡ‹ спрайтов; +- список ΠΈ количСство ΠΈΠΊΠΎΠ½ΠΎΠΊ; +- поиск ΠΈ ΡΠΈΡΡ‚Π΅ΠΌΠ½ΡƒΡŽ ΡΠ²Π΅Ρ‚Π»ΡƒΡŽ/Ρ‚Ρ‘ΠΌΠ½ΡƒΡŽ Ρ‚Π΅ΠΌΡƒ; +- модальноС ΠΏΡ€Π΅Π²ΡŒΡŽ с `viewBox` ΠΈ настройкой Ρ†Π²Π΅Ρ‚ΠΎΠ²Ρ‹Ρ… ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½Ρ‹Ρ…; +- ΠΏΡ€ΠΈΠΌΠ΅Ρ€Ρ‹ React, SVG, IMG ΠΈ CSS с ΠΊΠΎΠΏΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠ΅ΠΌ ΠΊΠΎΠ΄Π°. + +Production-ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Ρ‹ Π½Π΅ ΠΈΠΌΠΏΠΎΡ€Ρ‚ΠΈΡ€ΡƒΡŽΡ‚ debug-манифСсты. Бпособ ΠΏΠΎΠ΄ΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΡ Viewer зависит ΠΎΡ‚ сборщика: + +- [React + Vite: автоматичСский `import.meta.glob`](docs/ru/react-vite.md#6-Π΄ΠΎΠ±Π°Π²ΡŒΡ‚Π΅-debug-страницу); +- [React + Webpack 5: статичСскиС `import()`](docs/ru/react-webpack.md#6-Π΄ΠΎΠ±Π°Π²ΡŒΡ‚Π΅-debug-страницу); +- [Next.js App Router](docs/ru/next-app.md#5-Π΄ΠΎΠ±Π°Π²ΡŒΡ‚Π΅-spriteviewer); +- [Next.js Pages Router](docs/ru/next-pages.md#5-Π΄ΠΎΠ±Π°Π²ΡŒΡ‚Π΅-spriteviewer). + +Viewer ΠΏΠΎΠ΄ΠΊΠ»ΡŽΡ‡Π°Π΅Ρ‚ΡΡ ΠΈΠ· ΠΎΡ‚Π΄Π΅Π»ΡŒΠ½ΠΎΠΉ клиСнтской Ρ‚ΠΎΡ‡ΠΊΠΈ Π²Ρ…ΠΎΠ΄Π° `@gromlab/svg-sprites/react` ΠΈ Π½Π΅ ΠΏΠΎΠΏΠ°Π΄Π°Π΅Ρ‚ Π² production-ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Ρ‹ ΠΈΠΊΠΎΠ½ΠΎΠΊ. + +### Π’Π΅ΠΌΠ° Viewer + +По ΡƒΠΌΠΎΠ»Ρ‡Π°Π½ΠΈΡŽ `colorTheme="auto"`: Viewer слСдуСт `prefers-color-scheme` ΠΈ Ρ€Π΅Π°Π³ΠΈΡ€ΡƒΠ΅Ρ‚ Π½Π° смСну систСмной Ρ‚Π΅ΠΌΡ‹. Π’Π΅ΠΌΡƒ прилоТСния ΠΌΠΎΠΆΠ½ΠΎ ΠΏΠ΅Ρ€Π΅Π΄Π°Ρ‚ΡŒ явно: + +```tsx + +``` + +ДопустимыС значСния `colorTheme`: `auto`, `light`, `dark`. ΠŸΡ€ΠΈ ΡƒΠΏΡ€Π°Π²Π»Π΅Π½ΠΈΠΈ Ρ‚Π΅ΠΌΠΎΠΉ ΠΈΠ·Π²Π½Π΅ встроСнный ΠΏΠ΅Ρ€Π΅ΠΊΠ»ΡŽΡ‡Π°Ρ‚Π΅Π»ΡŒ скрываСтся. Π§Ρ‚ΠΎΠ±Ρ‹ ΠΎΡΡ‚Π°Π²ΠΈΡ‚ΡŒ Π΅Π³ΠΎ ΠΈ ΠΎΠ±Π½ΠΎΠ²Π»ΡΡ‚ΡŒ Ρ‚Π΅ΠΌΡƒ прилоТСния Ρ‡Π΅Ρ€Π΅Π· Viewer, ΠΏΠ΅Ρ€Π΅Π΄Π°ΠΉΡ‚Π΅ callback: + +```tsx + +``` + +## ДокумСнтация + +- [React + Vite](docs/ru/react-vite.md) +- [React + Webpack 5](docs/ru/react-webpack.md) +- [Next.js App Router](docs/ru/next-app.md) +- [Next.js Pages Router](docs/ru/next-pages.md) +- [Legacy mode](docs/ru/legacy.md) +- [ΠœΠΈΠ³Ρ€Π°Ρ†ΠΈΡ с 0.1.x](docs/ru/migration-1.md) +- [ΠŸΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠ½Ρ‹ΠΉ API](docs/ru/programmatic-api.md) + +## ЛицСнзия + +MIT diff --git a/skills/artifacts/svg-sprites-ru/references/docs/en/legacy.md b/skills/artifacts/svg-sprites-ru/references/docs/en/legacy.md new file mode 100644 index 0000000..10b6ea1 --- /dev/null +++ b/skills/artifacts/svg-sprites-ru/references/docs/en/legacy.md @@ -0,0 +1,102 @@ +# Legacy mode + +[← Back to home](../../README.md) + +A quick guide to generating centralized SVG sprites in `symbol` and `stack` formats, with an optional HTML preview. + +## 1. Install the package + +```bash +npm install @gromlab/svg-sprites +``` + +## 2. Prepare the icons and config + +```text +project/ +β”œβ”€β”€ src/assets/icons/ +β”‚ β”œβ”€β”€ check.svg +β”‚ └── folder.svg +└── svg-sprites.config.ts +``` + +```ts +// svg-sprites.config.ts +import { defineLegacyConfig } from '@gromlab/svg-sprites' + +export default defineLegacyConfig({ + output: 'public/sprites', + preview: true, + sprites: [ + { + name: 'icons', + input: 'src/assets/icons', + format: 'symbol', + }, + ], +}) +``` + +## 3. Run generation + +```bash +npx svg-sprites --mode legacy . +``` + +Result: + +```text +public/sprites/ +β”œβ”€β”€ icons.sprite.svg +└── preview.html +``` + +With `preview: false`, the HTML file is not created. For the `stack` format, specify `format: 'stack'`. + +## 4. Use the symbol sprite + +```html + + + +``` + +## 5. Add a package script + +```json +{ + "scripts": { + "sprites": "svg-sprites --mode legacy .", + "prebuild": "npm run sprites" + } +} +``` + +## Multiple sprites + +Add multiple entries to `sprites`: + +```ts +sprites: [ + { + name: 'icons', + input: 'src/assets/icons', + format: 'symbol', + }, + { + name: 'logos', + input: 'src/assets/logos', + format: 'stack', + }, +] +``` + +All output files and the shared `preview.html` will be written to `output`. + +## Troubleshooting + +- Config not found: make sure `svg-sprites.config.ts` is located in the specified root directory. +- No icons: check `sprites[].input` and the `.svg` extension. +- Preview not needed: set `preview: false`. + +For programmatic use, see [`generateLegacy`](programmatic-api.md#generatelegacy). diff --git a/skills/artifacts/svg-sprites-ru/references/docs/en/migration-1.md b/skills/artifacts/svg-sprites-ru/references/docs/en/migration-1.md new file mode 100644 index 0000000..b53b915 --- /dev/null +++ b/skills/artifacts/svg-sprites-ru/references/docs/en/migration-1.md @@ -0,0 +1,96 @@ +# Migrating from 0.1.x to 1.0 + +[← Back to home](../../README.md) + +Version 1.0 separates local generation for React and Next.js from the centralized legacy mode. The old config cannot be mixed with the new API in a single CLI invocation. + +## CLI + +The CLI now always requires an explicit `--mode` and a path to the configuration directory: + +```text +svg-sprites +β†’ svg-sprites --mode +``` + +Choose a mode based on your environment: + +| Environment | Mode | +|---|---| +| 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` | +| Centralized legacy setup | `legacy` | + +## React and Next.js + +Instead of a root-level `svg-sprites.config.ts`, create a local `svg-sprite.config.ts` next to the icon set: + +```ts +import { defineNextSpriteConfig } from '@gromlab/svg-sprites' + +export default defineNextSpriteConfig({ + name: 'global', + inputFolder: './icons', +}) +``` + +For regular React, use `defineReactSpriteConfig`. A folder and an explicit list of shared SVG files can be combined using `inputFolder` and `inputFiles`. + +The old `publicPath` and `react` options are no longer needed. The generated module is created next to the config and adds its own `.gitignore`, while Vite, Webpack, or Next.js emits the SVG as a separate asset with a content hash. + +The `` component is replaced by a component whose name is derived from `name`: + +```tsx + +``` + +To browse the icons, add `` as a debug page in the application. A separate `preview.html` is available only in legacy mode. + +## Legacy mode + +If you need to preserve the centralized structure, rename the helper and the format fields: + +```ts +import { defineLegacyConfig } from '@gromlab/svg-sprites' + +export default defineLegacyConfig({ + output: 'public/sprites', + preview: true, + sprites: [ + { + name: 'icons', + input: 'src/assets/icons', + format: 'stack', + }, + ], +}) +``` + +- `defineConfig` has been replaced with `defineLegacyConfig`; +- `sprites[].mode` has been renamed to `sprites[].format`; +- `generate` has been replaced with `generateLegacy`; +- `loadConfig` has been replaced with `loadLegacyConfig`; +- `publicPath` and generation of the old shared React component have been removed. + +Run: + +```bash +svg-sprites --mode legacy . +``` + +## Programmatic API + +The package is distributed as ESM only. Replace `require()` with `import`. + +`compileSpriteContent` now returns `Promise` so that the public declarations do not require `@types/node` to be installed. In Node.js, the actual result is compatible with APIs that accept `Uint8Array`. + +## After migration + +1. Remove the old generated files and rules that ignored the entire directory containing the source icons. +2. Add an explicit generation command before `dev`, `build`, and `typecheck`. +3. Run generation and type checking. +4. Check all icons and color variables using `SpriteViewer` or the legacy `preview.html`. diff --git a/skills/artifacts/svg-sprites-ru/references/docs/en/next-app.md b/skills/artifacts/svg-sprites-ru/references/docs/en/next-app.md new file mode 100644 index 0000000..1e334ce --- /dev/null +++ b/skills/artifacts/svg-sprites-ru/references/docs/en/next-app.md @@ -0,0 +1,102 @@ +# Next.js App Router + +[← Back to home](../../README.md) + +Two explicit modes are supported: + +| Bundler | Mode key | Next.js version | +|---|---|---| +| Turbopack | `next@app/turbopack` | 16.2+ | +| Webpack 5 | `next@app/webpack` | 13.4+ | + +## 1. Install the package + +```bash +npm install @gromlab/svg-sprites +``` + +## 2. Create a sprite module + +```text +src/ui/file-manager/svg-sprite/ +β”œβ”€β”€ icons/ +β”‚ β”œβ”€β”€ check.svg +β”‚ └── folder.svg +└── svg-sprite.config.ts +``` + +```ts +// src/ui/file-manager/svg-sprite/svg-sprite.config.ts +import { defineNextSpriteConfig } from '@gromlab/svg-sprites' + +export default defineNextSpriteConfig({ + name: 'file-manager', + description: 'File manager icons', +}) +``` + +## 3. Add generation + +For Turbopack: + +```json +{ + "scripts": { + "sprite:file-manager": "svg-sprites --mode next@app/turbopack src/ui/file-manager/svg-sprite", + "predev": "npm run sprite:file-manager", + "prebuild": "npm run sprite:file-manager" + } +} +``` + +For Webpack, replace the mode key with `next@app/webpack`. In Next 13–15, Webpack is used with the regular `next build` command; in Next 16, use `next build --webpack`. + +## 4. Use it in a Server Component + +The generated component does not contain `'use client'`, so it can be imported directly into `page.tsx` or `layout.tsx`: + +```tsx +import { FileManagerIcon } from '@/ui/file-manager/svg-sprite' + +export default function Page() { + return ( +
+ +
+ ) +} +``` + +Next.js emits a separate SVG asset with a content hash. The same generated code is used during SSR and in the browser, with no URL mismatch. + +## 5. Add SpriteViewer + +The viewer is interactive, so it requires a separate Client Component boundary: + +```tsx +'use client' + +import { SpriteViewer } from '@gromlab/svg-sprites/react' + +const sources = [ + () => import('@/ui/file-manager/svg-sprite/manifest'), +] + +export default function SpritesPage() { + return +} +``` + +## Verify the bundler + +```bash +# Turbopack +npx next build --turbopack + +# Webpack 5 +npx next build --webpack +``` + +For Next 13–15 with Webpack, use `npx next build` without the flag. + +The Next.js command and the generator mode key must target the same bundler. diff --git a/skills/artifacts/svg-sprites-ru/references/docs/en/next-pages.md b/skills/artifacts/svg-sprites-ru/references/docs/en/next-pages.md new file mode 100644 index 0000000..0de0136 --- /dev/null +++ b/skills/artifacts/svg-sprites-ru/references/docs/en/next-pages.md @@ -0,0 +1,96 @@ +# Next.js Pages Router + +[← Back to home](../../README.md) + +Two explicit modes are supported: + +| Bundler | Mode key | Next.js version | +|---|---|---| +| Turbopack | `next@pages/turbopack` | 16.2+ | +| Webpack 5 | `next@pages/webpack` | 12.2+ | + +Next.js 12.2 requires React 18. + +## 1. Install the package + +```bash +npm install @gromlab/svg-sprites +``` + +## 2. Create a sprite module + +```text +src/ui/file-manager/svg-sprite/ +β”œβ”€β”€ icons/ +β”‚ β”œβ”€β”€ check.svg +β”‚ └── folder.svg +└── svg-sprite.config.ts +``` + +```ts +// src/ui/file-manager/svg-sprite/svg-sprite.config.ts +import { defineNextSpriteConfig } from '@gromlab/svg-sprites' + +export default defineNextSpriteConfig({ + name: 'file-manager', + description: 'File manager icons', +}) +``` + +## 3. Add generation + +```json +{ + "scripts": { + "sprite:file-manager": "svg-sprites --mode next@pages/webpack src/ui/file-manager/svg-sprite", + "predev": "npm run sprite:file-manager", + "prebuild": "npm run sprite:file-manager" + } +} +``` + +For Next.js 16.2 with Turbopack, replace the mode key with `next@pages/turbopack`. + +## 4. Use it on a page + +```tsx +import { FileManagerIcon } from '@/ui/file-manager/svg-sprite' + +export default function FilesPage() { + return +} + +export function getServerSideProps() { + return { props: {} } +} +``` + +The component works the same way with SSR, SSG, and client-side navigation. Next.js emits a separate SVG asset with a content hash. + +## 5. Add SpriteViewer + +```tsx +import { SpriteViewer } from '@gromlab/svg-sprites/react' + +const sources = [ + () => import('@/ui/file-manager/svg-sprite/manifest'), +] + +export default function SpritesPage() { + return +} +``` + +## Verify the bundler + +```bash +# Turbopack +npx next build --turbopack + +# Webpack 5 +npx next build --webpack +``` + +For Next 12–15 with Webpack, use `npx next build` without the flag. + +The Next.js command and the generator mode key must target the same bundler. diff --git a/skills/artifacts/svg-sprites-ru/references/docs/en/programmatic-api.md b/skills/artifacts/svg-sprites-ru/references/docs/en/programmatic-api.md new file mode 100644 index 0000000..7a4d44b --- /dev/null +++ b/skills/artifacts/svg-sprites-ru/references/docs/en/programmatic-api.md @@ -0,0 +1,203 @@ +# Programmatic API + +[← Back to home](../../README.md) + +The package provides a main Node.js entry point and a separate React runtime entry point. Both are distributed as ESM only and must be loaded with `import`. + +To resolve `@gromlab/svg-sprites/react` in TypeScript, use `moduleResolution: "bundler"`, `"node16"`, or `"nodenext"`. + +## Main entry point + +```ts +import { + defineNextSpriteConfig, + defineReactSpriteConfig, + generateNextSprite, + generateReactSprite, +} from '@gromlab/svg-sprites' +``` + +The main entry point does not import React and can be used in CLIs, build scripts, and Node.js tools. + +## `generateReactSprite` + +```ts +import { generateReactSprite } from '@gromlab/svg-sprites' + +const result = await generateReactSprite( + 'src/ui/file-manager/svg-sprite', + 'vite', +) +``` + +The second argument is required: + +```ts +type ReactAssetTarget = 'vite' | 'webpack' +``` + +Result: + +```ts +type ReactSpriteGenerationResult = { + name: string + rootDir: string + generatedDir: string + spritePath: string + manifestPath: string + iconCount: number + target: 'vite' | 'webpack' +} +``` + +```ts +console.log(result.name) +console.log(result.iconCount) +console.log(result.spritePath) +console.log(result.manifestPath) +``` + +The function loads `svg-sprite.config.ts` from the specified root, compiles the SVG files, and safely updates managed files. + +## `generateNextSprite` + +```ts +import { generateNextSprite } from '@gromlab/svg-sprites' + +const result = await generateNextSprite( + 'src/ui/file-manager/svg-sprite', + { + router: 'app', + bundler: 'turbopack', + }, +) +``` + +Available values: + +```ts +type NextSpriteGenerationOptions = { + router: 'app' | 'pages' + bundler: 'turbopack' | 'webpack' +} +``` + +The result also contains the selected `router`, `bundler`, and the full target in the form `next@app/turbopack`. + +## `defineReactSpriteConfig` + +```ts +import { defineReactSpriteConfig } from '@gromlab/svg-sprites' + +export default defineReactSpriteConfig({ + name: 'file-manager', + description: 'File manager icons', + inputFolder: './icons', + inputFiles: [ + '../../shared/icons/check.svg', + ], + transform: { + removeSize: true, + replaceColors: true, + addTransition: true, + }, + generatedNotice: true, +}) +``` + +`inputFolder` and `inputFiles` are combined. The helper returns the configuration without runtime transformations and provides TypeScript autocomplete. + +## `defineNextSpriteConfig` + +```ts +import { defineNextSpriteConfig } from '@gromlab/svg-sprites' + +export default defineNextSpriteConfig({ + name: 'file-manager', + description: 'File manager icons', + inputFolder: './icons', +}) +``` + +Next.js uses the same configuration contract as the React presets. + +## `generateLegacy` + +```ts +import { generateLegacy } from '@gromlab/svg-sprites' + +const results = await generateLegacy({ + output: 'public/sprites', + preview: false, + sprites: [ + { + name: 'icons', + input: 'src/assets/icons', + format: 'symbol', + }, + ], +}) +``` + +Returns an array: + +```ts +type SpriteResult = { + name: string + format: 'symbol' | 'stack' + spritePath: string + iconCount: number +} +``` + +For details, see [Legacy mode](legacy.md). + +## Low-level functions + +The main entry point also exports: + +```ts +import { + compileSprite, + compileSpriteContent, + createShapeTransform, + generatePreview, + loadLegacyConfig, + loadReactSpriteConfig, + resolveSpriteEntry, + resolveSprites, +} from '@gromlab/svg-sprites' +``` + +These functions are intended for custom orchestration built on top of the existing compiler and writer. For standard usage, prefer `generateReactSprite` and `generateLegacy`. + +## React runtime entry point + +```tsx +import { SpriteViewer } from '@gromlab/svg-sprites/react' +``` + +Types: + +```ts +import type { + SpriteManifest, + SpriteManifestColor, + SpriteManifestIcon, + SpriteManifestLoader, + SpriteManifestModule, + SpriteViewerColorTheme, + SpriteViewerProps, + SpriteViewerSource, + SpriteViewerSources, +} from '@gromlab/svg-sprites/react' +``` + +The React entry point contains `'use client'` and is intended for debug tools. Generated production components are imported from the application's local sprite modules, not from the package's React entry point. + +`SpriteViewerProps.colorTheme` accepts `auto | light | dark`. The default is `auto`, which follows `prefers-color-scheme`; to synchronize it with the application theme, pass the computed `light` or `dark` value. + +## Related guides + +- [React + Vite](react-vite.md) +- [React + Webpack 5](react-webpack.md) diff --git a/skills/artifacts/svg-sprites-ru/references/docs/en/react-vite.md b/skills/artifacts/svg-sprites-ru/references/docs/en/react-vite.md new file mode 100644 index 0000000..1e37cc4 --- /dev/null +++ b/skills/artifacts/svg-sprites-ru/references/docs/en/react-vite.md @@ -0,0 +1,116 @@ +# React + Vite + +[← Back to home](../../README.md) + +A quick guide to installing and using SVG sprites in a React and Vite project. + +The result is a typed React component and a separate cacheable SVG asset. + +## 1. Install the package + +```bash +npm install @gromlab/svg-sprites +``` + +## 2. Create the sprite directory + +```text +src/ui/file-manager/svg-sprite/ +β”œβ”€β”€ icons/ +β”‚ β”œβ”€β”€ check.svg +β”‚ └── folder.svg +└── svg-sprite.config.ts +``` + +Place the source SVG files in `icons/`. + +## 3. Add the configuration + +```ts +// src/ui/file-manager/svg-sprite/svg-sprite.config.ts +import { defineReactSpriteConfig } from '@gromlab/svg-sprites' + +export default defineReactSpriteConfig({ + name: 'file-manager', + description: 'File manager icons', +}) +``` + +By default, SVG files are loaded from `./icons`. You can add shared icons from other directories through `inputFiles`: the directory and file list are combined into a single sprite. + +The complete list of options is available under [Configuration β†’ React](../../README.md#react). + +## 4. Add generation to package.json + +```json +{ + "scripts": { + "sprite:file-manager": "svg-sprites --mode react@vite src/ui/file-manager/svg-sprite", + "predev": "npm run sprite:file-manager", + "prebuild": "npm run sprite:file-manager", + "pretypecheck": "npm run sprite:file-manager" + } +} +``` + +Generated files are excluded from Git, so generation must run before `dev`, `build`, and `typecheck`. + +First run: + +```bash +npm run sprite:file-manager +``` + +## 5. Use the component + +The name `file-manager` is converted to `FileManagerIcon`: + +```tsx +import { FileManagerIcon } from './svg-sprite' + +export const OpenFolderButton = () => ( + +) +``` + +TypeScript checks the `icon` value against the file names: + +```tsx + // valid + // TypeScript error +``` + +Types, display methods, and color controls are described in the [main documentation](../../README.md#display-methods). + +Vite emits the sprite as a separate file named like `assets/sprite-.svg`. SVG path data is not included in JavaScript. + +## 6. Add a debug page + +After integrating the icons, you can display all React sprites with `SpriteViewer`: + +```tsx +import { SpriteViewer } from '@gromlab/svg-sprites/react' +import type { SpriteManifestModule } from '@gromlab/svg-sprites/react' + +const sources = import.meta.glob( + '/src/**/svg-sprite/manifest.ts', +) + +export const IconsDebugPage = () => ( + +) +``` + +Vite automatically finds the generated `manifest.ts` for each React sprite. The `import.meta.glob` pattern must be a string literal, and generation must run before Vite starts. + +Only include the Viewer on a debug route or in an internal tool. + +## Troubleshooting + +- Missing `index.ts`: run `npm run sprite:file-manager`. +- The Viewer cannot find the sprite: check the glob path and make sure `manifest.ts` exists. +- `Refusing to overwrite a user file` error: there is a user file at a generated path. +- The icon does not change color: use `color` or `--icon-color-N`. diff --git a/skills/artifacts/svg-sprites-ru/references/docs/en/react-webpack.md b/skills/artifacts/svg-sprites-ru/references/docs/en/react-webpack.md new file mode 100644 index 0000000..15383db --- /dev/null +++ b/skills/artifacts/svg-sprites-ru/references/docs/en/react-webpack.md @@ -0,0 +1,118 @@ +# React + Webpack 5 + +[← Back to home](../../README.md) + +A quick guide to installing and using SVG sprites in a React and Webpack 5 project. + +The result is a typed React component and a separate SVG asset emitted through Webpack Asset Modules. + +## 1. Install the package + +```bash +npm install @gromlab/svg-sprites +``` + +## 2. Create the sprite directory + +```text +src/ui/file-manager/svg-sprite/ +β”œβ”€β”€ icons/ +β”‚ β”œβ”€β”€ check.svg +β”‚ └── folder.svg +└── svg-sprite.config.ts +``` + +Place the source SVG files in `icons/`. + +## 3. Add the configuration + +```ts +// src/ui/file-manager/svg-sprite/svg-sprite.config.ts +import { defineReactSpriteConfig } from '@gromlab/svg-sprites' + +export default defineReactSpriteConfig({ + name: 'file-manager', + description: 'File manager icons', +}) +``` + +By default, SVG files are loaded from `./icons`. You can add shared icons from other directories through `inputFiles`: the directory and file list are combined into a single sprite. + +The complete list of options is available under [Configuration β†’ React](../../README.md#react). + +## 4. Add generation to package.json + +```json +{ + "scripts": { + "sprite:file-manager": "svg-sprites --mode react@webpack src/ui/file-manager/svg-sprite", + "predev": "npm run sprite:file-manager", + "prebuild": "npm run sprite:file-manager", + "pretypecheck": "npm run sprite:file-manager" + } +} +``` + +Generated files are excluded from Git, so generation must run before `dev`, `build`, and `typecheck`. + +First run: + +```bash +npm run sprite:file-manager +``` + +## 5. Use the component + +```tsx +import { FileManagerIcon } from './svg-sprite' + +export const OpenFolderButton = () => ( + +) +``` + +TypeScript checks the `icon` value against the file names: + +```tsx + // valid + // TypeScript error +``` + +Types, display methods, and color controls are described in the [main documentation](../../README.md#display-methods). + +Webpack processes the generated `new URL('./sprite.svg', import.meta.url)` through Asset Modules and emits a separate SVG asset. + +If the project already uses a custom SVG loader, make sure it does not intercept the generated `sprite.svg` instead of Asset Modules. + +## 6. Add a debug page + +Webpack does not support Vite's `import.meta.glob` API, so provide static loaders: + +```tsx +import { SpriteViewer } from '@gromlab/svg-sprites/react' + +const sources = [ + () => import('./ui/file-manager/svg-sprite/manifest'), + () => import('./ui/navigation/svg-sprite/manifest'), +] + +export const IconsDebugPage = () => ( + +) +``` + +The paths in `import()` must be string literals. Webpack creates chunks for the manifests and associates them with the SVG assets. + +Only include the Viewer on a debug route or in an internal tool. + +## Troubleshooting + +- Missing `index.ts`: run `npm run sprite:file-manager`. +- The Viewer does not load the sprite: check the path in `import()` and make sure `manifest.ts` exists. +- Incorrect asset URL: check `output.publicPath`. +- Another loader intercepts the SVG: exclude the generated sprite from the incompatible rule. + +For Next.js, use the separate mode keys described in the [App Router](next-app.md) and [Pages Router](next-pages.md) guides. diff --git a/skills/artifacts/svg-sprites-ru/references/docs/ru/legacy.md b/skills/artifacts/svg-sprites-ru/references/docs/ru/legacy.md new file mode 100644 index 0000000..3d722b8 --- /dev/null +++ b/skills/artifacts/svg-sprites-ru/references/docs/ru/legacy.md @@ -0,0 +1,102 @@ +# Legacy mode + +[← Главная](../../README_RU.md) + +ΠšΡ€Π°Ρ‚ΠΊΠ°Ρ инструкция ΠΏΠΎ Π³Π΅Π½Π΅Ρ€Π°Ρ†ΠΈΠΈ Ρ†Π΅Π½Ρ‚Ρ€Π°Π»ΠΈΠ·ΠΎΠ²Π°Π½Π½Ρ‹Ρ… SVG-спрайтов Ρ„ΠΎΡ€ΠΌΠ°Ρ‚ΠΎΠ² `symbol` ΠΈ `stack` с optional HTML preview. + +## 1. УстановитС ΠΏΠ°ΠΊΠ΅Ρ‚ + +```bash +npm install @gromlab/svg-sprites +``` + +## 2. ΠŸΠΎΠ΄Π³ΠΎΡ‚ΠΎΠ²ΡŒΡ‚Π΅ ΠΈΠΊΠΎΠ½ΠΊΠΈ ΠΈ ΠΊΠΎΠ½Ρ„ΠΈΠ³ + +```text +project/ +β”œβ”€β”€ src/assets/icons/ +β”‚ β”œβ”€β”€ check.svg +β”‚ └── folder.svg +└── svg-sprites.config.ts +``` + +```ts +// svg-sprites.config.ts +import { defineLegacyConfig } from '@gromlab/svg-sprites' + +export default defineLegacyConfig({ + output: 'public/sprites', + preview: true, + sprites: [ + { + name: 'icons', + input: 'src/assets/icons', + format: 'symbol', + }, + ], +}) +``` + +## 3. ЗапуститС Π³Π΅Π½Π΅Ρ€Π°Ρ†ΠΈΡŽ + +```bash +npx svg-sprites --mode legacy . +``` + +Π Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚: + +```text +public/sprites/ +β”œβ”€β”€ icons.sprite.svg +└── preview.html +``` + +ΠŸΡ€ΠΈ `preview: false` HTML-Ρ„Π°ΠΉΠ» Π½Π΅ создаётся. Для Ρ„ΠΎΡ€ΠΌΠ°Ρ‚Π° `stack` ΡƒΠΊΠ°ΠΆΠΈΡ‚Π΅ `format: 'stack'`. + +## 4. Π˜ΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠΉΡ‚Π΅ symbol-спрайт + +```html + + + +``` + +## 5. Π”ΠΎΠ±Π°Π²ΡŒΡ‚Π΅ package script + +```json +{ + "scripts": { + "sprites": "svg-sprites --mode legacy .", + "prebuild": "npm run sprites" + } +} +``` + +## НСсколько спрайтов + +Π”ΠΎΠ±Π°Π²ΡŒΡ‚Π΅ нСсколько записСй Π² `sprites`: + +```ts +sprites: [ + { + name: 'icons', + input: 'src/assets/icons', + format: 'symbol', + }, + { + name: 'logos', + input: 'src/assets/logos', + format: 'stack', + }, +] +``` + +ВсС Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Ρ‹ ΠΈ ΠΎΠ±Ρ‰ΠΈΠΉ `preview.html` Π±ΡƒΠ΄ΡƒΡ‚ записаны Π² `output`. + +## Если Ρ‡Ρ‚ΠΎ-Ρ‚ΠΎ Π½Π΅ Ρ€Π°Π±ΠΎΡ‚Π°Π΅Ρ‚ + +- НС Π½Π°ΠΉΠ΄Π΅Π½ ΠΊΠΎΠ½Ρ„ΠΈΠ³: ΡƒΠ±Π΅Π΄ΠΈΡ‚Π΅ΡΡŒ, Ρ‡Ρ‚ΠΎ `svg-sprites.config.ts` находится Π² ΠΏΠ΅Ρ€Π΅Π΄Π°Π½Π½ΠΎΠΌ ΠΊΠΎΡ€Π½Π΅. +- НСт ΠΈΠΊΠΎΠ½ΠΎΠΊ: ΠΏΡ€ΠΎΠ²Π΅Ρ€ΡŒΡ‚Π΅ `sprites[].input` ΠΈ Ρ€Π°ΡΡˆΠΈΡ€Π΅Π½ΠΈΠ΅ `.svg`. +- НС Π½ΡƒΠΆΠ΅Π½ preview: установитС `preview: false`. + +Для ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠ½ΠΎΠ³ΠΎ запуска ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠΉΡ‚Π΅ [`generateLegacy`](programmatic-api.md#generatelegacy). diff --git a/skills/artifacts/svg-sprites-ru/references/docs/ru/migration-1.md b/skills/artifacts/svg-sprites-ru/references/docs/ru/migration-1.md new file mode 100644 index 0000000..39b15d8 --- /dev/null +++ b/skills/artifacts/svg-sprites-ru/references/docs/ru/migration-1.md @@ -0,0 +1,96 @@ +# ΠœΠΈΠ³Ρ€Π°Ρ†ΠΈΡ с 0.1.x Π½Π° 1.0 + +[← Главная](../../README_RU.md) + +ВСрсия 1.0 раздСляСт Π»ΠΎΠΊΠ°Π»ΡŒΠ½ΡƒΡŽ Π³Π΅Π½Π΅Ρ€Π°Ρ†ΠΈΡŽ для React ΠΈ Next.js ΠΈ Ρ†Π΅Π½Ρ‚Ρ€Π°Π»ΠΈΠ·ΠΎΠ²Π°Π½Π½Ρ‹ΠΉ legacy-Ρ€Π΅ΠΆΠΈΠΌ. Π‘Ρ‚Π°Ρ€Ρ‹ΠΉ config нСльзя ΡΠΌΠ΅ΡˆΠΈΠ²Π°Ρ‚ΡŒ с Π½ΠΎΠ²Ρ‹ΠΌ API Π² ΠΎΠ΄Π½ΠΎΠΌ Π²Ρ‹Π·ΠΎΠ²Π΅ CLI. + +## CLI + +CLI Ρ‚Π΅ΠΏΠ΅Ρ€ΡŒ всСгда Ρ‚Ρ€Π΅Π±ΡƒΠ΅Ρ‚ явный `--mode` ΠΈ ΠΏΡƒΡ‚ΡŒ ΠΊ ΠΊΠ°Ρ‚Π°Π»ΠΎΠ³Ρƒ ΠΊΠΎΠ½Ρ„ΠΈΠ³ΡƒΡ€Π°Ρ†ΠΈΠΈ: + +```text +svg-sprites +β†’ svg-sprites --mode +``` + +Π’Ρ‹Π±Π΅Ρ€ΠΈΡ‚Π΅ mode ΠΏΠΎ ΠΎΠΊΡ€ΡƒΠΆΠ΅Π½ΠΈΡŽ: + +| ΠžΠΊΡ€ΡƒΠΆΠ΅Π½ΠΈΠ΅ | Mode | +|---|---| +| 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` | +| ЦСнтрализованная старая схСма | `legacy` | + +## React ΠΈ Next.js + +ВмСсто ΠΊΠΎΡ€Π½Π΅Π²ΠΎΠ³ΠΎ `svg-sprites.config.ts` создайтС Π»ΠΎΠΊΠ°Π»ΡŒΠ½Ρ‹ΠΉ `svg-sprite.config.ts` рядом с Π½Π°Π±ΠΎΡ€ΠΎΠΌ ΠΈΠΊΠΎΠ½ΠΎΠΊ: + +```ts +import { defineNextSpriteConfig } from '@gromlab/svg-sprites' + +export default defineNextSpriteConfig({ + name: 'global', + inputFolder: './icons', +}) +``` + +Для ΠΎΠ±Ρ‹Ρ‡Π½ΠΎΠ³ΠΎ React ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠΉΡ‚Π΅ `defineReactSpriteConfig`. ΠŸΠ°ΠΏΠΊΡƒ ΠΈ явный список ΠΎΠ±Ρ‰ΠΈΡ… SVG ΠΌΠΎΠΆΠ½ΠΎ ΠΎΠ±ΡŠΠ΅Π΄ΠΈΠ½ΠΈΡ‚ΡŒ Ρ‡Π΅Ρ€Π΅Π· `inputFolder` ΠΈ `inputFiles`. + +Π‘Ρ‚Π°Ρ€Ρ‹Π΅ `publicPath` ΠΈ `react` большС Π½Π΅ Π½ΡƒΠΆΠ½Ρ‹. Generated-ΠΌΠΎΠ΄ΡƒΠ»ΡŒ создаётся рядом с ΠΊΠΎΠ½Ρ„ΠΈΠ³ΠΎΠΌ, сам добавляСт `.gitignore`, Π° Vite, Webpack ΠΈΠ»ΠΈ Next.js выпускаСт SVG ΠΊΠ°ΠΊ ΠΎΡ‚Π΄Π΅Π»ΡŒΠ½Ρ‹ΠΉ asset с content hash. + +ΠšΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚ `` замСняСтся ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚ΠΎΠΌ, имя ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠ³ΠΎ выводится ΠΈΠ· `name`: + +```tsx + +``` + +Для просмотра ΠΈΠΊΠΎΠ½ΠΎΠΊ Π΄ΠΎΠ±Π°Π²ΡŒΡ‚Π΅ `` ΠΊΠ°ΠΊ debug-страницу прилоТСния. ΠžΡ‚Π΄Π΅Π»ΡŒΠ½Ρ‹ΠΉ `preview.html` остаётся Ρ‚ΠΎΠ»ΡŒΠΊΠΎ Π² legacy-Ρ€Π΅ΠΆΠΈΠΌΠ΅. + +## Legacy-Ρ€Π΅ΠΆΠΈΠΌ + +Если Ρ†Π΅Π½Ρ‚Ρ€Π°Π»ΠΈΠ·ΠΎΠ²Π°Π½Π½ΡƒΡŽ структуру Π½ΡƒΠΆΠ½ΠΎ ΡΠΎΡ…Ρ€Π°Π½ΠΈΡ‚ΡŒ, ΠΏΠ΅Ρ€Π΅ΠΈΠΌΠ΅Π½ΡƒΠΉΡ‚Π΅ helper ΠΈ поля Ρ„ΠΎΡ€ΠΌΠ°Ρ‚Π°: + +```ts +import { defineLegacyConfig } from '@gromlab/svg-sprites' + +export default defineLegacyConfig({ + output: 'public/sprites', + preview: true, + sprites: [ + { + name: 'icons', + input: 'src/assets/icons', + format: 'stack', + }, + ], +}) +``` + +- `defineConfig` Π·Π°ΠΌΠ΅Π½Ρ‘Π½ Π½Π° `defineLegacyConfig`; +- `sprites[].mode` ΠΏΠ΅Ρ€Π΅ΠΈΠΌΠ΅Π½ΠΎΠ²Π°Π½ Π² `sprites[].format`; +- `generate` Π·Π°ΠΌΠ΅Π½Ρ‘Π½ Π½Π° `generateLegacy`; +- `loadConfig` Π·Π°ΠΌΠ΅Π½Ρ‘Π½ Π½Π° `loadLegacyConfig`; +- `publicPath` ΠΈ гСнСрация старого ΠΎΠ±Ρ‰Π΅Π³ΠΎ React-ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Π° ΡƒΠ΄Π°Π»Π΅Π½Ρ‹. + +Запуск: + +```bash +svg-sprites --mode legacy . +``` + +## ΠŸΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠ½Ρ‹ΠΉ API + +ΠŸΠ°ΠΊΠ΅Ρ‚ распространяСтся Ρ‚ΠΎΠ»ΡŒΠΊΠΎ ΠΊΠ°ΠΊ ESM. Π—Π°ΠΌΠ΅Π½ΠΈΡ‚Π΅ `require()` Π½Π° `import`. + +`compileSpriteContent` Ρ‚Π΅ΠΏΠ΅Ρ€ΡŒ Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅Ρ‚ `Promise`, Ρ‡Ρ‚ΠΎΠ±Ρ‹ ΠΏΡƒΠ±Π»ΠΈΡ‡Π½Ρ‹Π΅ Π΄Π΅ΠΊΠ»Π°Ρ€Π°Ρ†ΠΈΠΈ Π½Π΅ Ρ‚Ρ€Π΅Π±ΠΎΠ²Π°Π»ΠΈ установки `@types/node`. Π’ Node.js фактичСский Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ совмСстим с API, ΠΏΡ€ΠΈΠ½ΠΈΠΌΠ°ΡŽΡ‰ΠΈΠΌΠΈ `Uint8Array`. + +## ПослС ΠΌΠΈΠ³Ρ€Π°Ρ†ΠΈΠΈ + +1. Π£Π΄Π°Π»ΠΈΡ‚Π΅ старыС generated-Ρ„Π°ΠΉΠ»Ρ‹ ΠΈ ΠΏΡ€Π°Π²ΠΈΠ»Π°, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ ΠΈΠ³Π½ΠΎΡ€ΠΈΡ€ΠΎΠ²Π°Π»ΠΈ Ρ†Π΅Π»ΠΈΠΊΠΎΠΌ ΠΊΠ°Ρ‚Π°Π»ΠΎΠ³ с исходными ΠΈΠΊΠΎΠ½ΠΊΠ°ΠΌΠΈ. +2. Π”ΠΎΠ±Π°Π²ΡŒΡ‚Π΅ ΡΠ²Π½ΡƒΡŽ ΠΊΠΎΠΌΠ°Π½Π΄Ρƒ Π³Π΅Π½Π΅Ρ€Π°Ρ†ΠΈΠΈ ΠΏΠ΅Ρ€Π΅Π΄ `dev`, `build` ΠΈ `typecheck`. +3. ЗапуститС Π³Π΅Π½Π΅Ρ€Π°Ρ†ΠΈΡŽ ΠΈ ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΊΡƒ Ρ‚ΠΈΠΏΠΎΠ². +4. ΠŸΡ€ΠΎΠ²Π΅Ρ€ΡŒΡ‚Π΅ всС ΠΈΠΊΠΎΠ½ΠΊΠΈ ΠΈ Ρ†Π²Π΅Ρ‚ΠΎΠ²Ρ‹Π΅ ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½Ρ‹Π΅ Ρ‡Π΅Ρ€Π΅Π· `SpriteViewer` ΠΈΠ»ΠΈ legacy `preview.html`. diff --git a/skills/artifacts/svg-sprites-ru/references/docs/ru/next-app.md b/skills/artifacts/svg-sprites-ru/references/docs/ru/next-app.md new file mode 100644 index 0000000..06049c6 --- /dev/null +++ b/skills/artifacts/svg-sprites-ru/references/docs/ru/next-app.md @@ -0,0 +1,102 @@ +# Next.js App Router + +[← Главная](../../README_RU.md) + +ΠŸΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΈΠ²Π°ΡŽΡ‚ΡΡ Π΄Π²Π° явных Ρ€Π΅ΠΆΠΈΠΌΠ°: + +| Π‘Π±ΠΎΡ€Ρ‰ΠΈΠΊ | Mode key | ВСрсия Next.js | +|---|---|---| +| Turbopack | `next@app/turbopack` | 16.2+ | +| Webpack 5 | `next@app/webpack` | 13.4+ | + +## 1. УстановитС ΠΏΠ°ΠΊΠ΅Ρ‚ + +```bash +npm install @gromlab/svg-sprites +``` + +## 2. Π‘ΠΎΠ·Π΄Π°ΠΉΡ‚Π΅ sprite-ΠΌΠΎΠ΄ΡƒΠ»ΡŒ + +```text +src/ui/file-manager/svg-sprite/ +β”œβ”€β”€ icons/ +β”‚ β”œβ”€β”€ check.svg +β”‚ └── folder.svg +└── svg-sprite.config.ts +``` + +```ts +// src/ui/file-manager/svg-sprite/svg-sprite.config.ts +import { defineNextSpriteConfig } from '@gromlab/svg-sprites' + +export default defineNextSpriteConfig({ + name: 'file-manager', + description: 'Иконки Ρ„Π°ΠΉΠ»ΠΎΠ²ΠΎΠ³ΠΎ ΠΌΠ΅Π½Π΅Π΄ΠΆΠ΅Ρ€Π°', +}) +``` + +## 3. Π”ΠΎΠ±Π°Π²ΡŒΡ‚Π΅ Π³Π΅Π½Π΅Ρ€Π°Ρ†ΠΈΡŽ + +Для Turbopack: + +```json +{ + "scripts": { + "sprite:file-manager": "svg-sprites --mode next@app/turbopack src/ui/file-manager/svg-sprite", + "predev": "npm run sprite:file-manager", + "prebuild": "npm run sprite:file-manager" + } +} +``` + +Для Webpack Π·Π°ΠΌΠ΅Π½ΠΈΡ‚Π΅ mode key Π½Π° `next@app/webpack`. Π’ Next 13–15 Webpack ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ΡΡ ΠΎΠ±Ρ‹Ρ‡Π½ΠΎΠΉ ΠΊΠΎΠΌΠ°Π½Π΄ΠΎΠΉ `next build`, Π² Next 16 β€” ΠΊΠΎΠΌΠ°Π½Π΄ΠΎΠΉ `next build --webpack`. + +## 4. Π˜ΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠΉΡ‚Π΅ Π² Server Component + +Generated-ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚ Π½Π΅ содСрТит `'use client'`, поэтому Π΅Π³ΠΎ ΠΌΠΎΠΆΠ½ΠΎ ΠΈΠΌΠΏΠΎΡ€Ρ‚ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ нСпосрСдствСнно Π² `page.tsx` ΠΈΠ»ΠΈ `layout.tsx`: + +```tsx +import { FileManagerIcon } from '@/ui/file-manager/svg-sprite' + +export default function Page() { + return ( +
+ +
+ ) +} +``` + +Next.js выпустит ΠΎΡ‚Π΄Π΅Π»ΡŒΠ½Ρ‹ΠΉ SVG asset с content hash. Один generated-ΠΊΠΎΠ΄ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ΡΡ ΠΏΡ€ΠΈ SSR ΠΈ Π² Π±Ρ€Π°ΡƒΠ·Π΅Ρ€Π΅ Π±Π΅Π· расхоТдСния URL. + +## 5. Π”ΠΎΠ±Π°Π²ΡŒΡ‚Π΅ SpriteViewer + +Viewer ΠΈΠ½Ρ‚Π΅Ρ€Π°ΠΊΡ‚ΠΈΠ²Π΅Π½, поэтому для Π½Π΅Π³ΠΎ Π½ΡƒΠΆΠ½Π° ΠΎΡ‚Π΄Π΅Π»ΡŒΠ½Π°Ρ Client Component Π³Ρ€Π°Π½ΠΈΡ†Π°: + +```tsx +'use client' + +import { SpriteViewer } from '@gromlab/svg-sprites/react' + +const sources = [ + () => import('@/ui/file-manager/svg-sprite/manifest'), +] + +export default function SpritesPage() { + return +} +``` + +## ΠŸΡ€ΠΎΠ²Π΅Ρ€ΠΊΠ° сборщика + +```bash +# Turbopack +npx next build --turbopack + +# Webpack 5 +npx next build --webpack +``` + +Для Next 13–15 с Webpack ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠΉΡ‚Π΅ `npx next build` Π±Π΅Π· Ρ„Π»Π°Π³Π°. + +Команда Next.js ΠΈ mode key Π³Π΅Π½Π΅Ρ€Π°Ρ‚ΠΎΡ€Π° Π΄ΠΎΠ»ΠΆΠ½Ρ‹ ΡƒΠΊΠ°Π·Ρ‹Π²Π°Ρ‚ΡŒ ΠΎΠ΄ΠΈΠ½ ΠΈ Ρ‚ΠΎΡ‚ ΠΆΠ΅ сборщик. diff --git a/skills/artifacts/svg-sprites-ru/references/docs/ru/next-pages.md b/skills/artifacts/svg-sprites-ru/references/docs/ru/next-pages.md new file mode 100644 index 0000000..926f0ef --- /dev/null +++ b/skills/artifacts/svg-sprites-ru/references/docs/ru/next-pages.md @@ -0,0 +1,96 @@ +# Next.js Pages Router + +[← Главная](../../README_RU.md) + +ΠŸΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΈΠ²Π°ΡŽΡ‚ΡΡ Π΄Π²Π° явных Ρ€Π΅ΠΆΠΈΠΌΠ°: + +| Π‘Π±ΠΎΡ€Ρ‰ΠΈΠΊ | Mode key | ВСрсия Next.js | +|---|---|---| +| Turbopack | `next@pages/turbopack` | 16.2+ | +| Webpack 5 | `next@pages/webpack` | 12.2+ | + +Для Next.js 12.2 трСбуСтся React 18. + +## 1. УстановитС ΠΏΠ°ΠΊΠ΅Ρ‚ + +```bash +npm install @gromlab/svg-sprites +``` + +## 2. Π‘ΠΎΠ·Π΄Π°ΠΉΡ‚Π΅ sprite-ΠΌΠΎΠ΄ΡƒΠ»ΡŒ + +```text +src/ui/file-manager/svg-sprite/ +β”œβ”€β”€ icons/ +β”‚ β”œβ”€β”€ check.svg +β”‚ └── folder.svg +└── svg-sprite.config.ts +``` + +```ts +// src/ui/file-manager/svg-sprite/svg-sprite.config.ts +import { defineNextSpriteConfig } from '@gromlab/svg-sprites' + +export default defineNextSpriteConfig({ + name: 'file-manager', + description: 'Иконки Ρ„Π°ΠΉΠ»ΠΎΠ²ΠΎΠ³ΠΎ ΠΌΠ΅Π½Π΅Π΄ΠΆΠ΅Ρ€Π°', +}) +``` + +## 3. Π”ΠΎΠ±Π°Π²ΡŒΡ‚Π΅ Π³Π΅Π½Π΅Ρ€Π°Ρ†ΠΈΡŽ + +```json +{ + "scripts": { + "sprite:file-manager": "svg-sprites --mode next@pages/webpack src/ui/file-manager/svg-sprite", + "predev": "npm run sprite:file-manager", + "prebuild": "npm run sprite:file-manager" + } +} +``` + +Для Next.js 16.2 с Turbopack Π·Π°ΠΌΠ΅Π½ΠΈΡ‚Π΅ mode key Π½Π° `next@pages/turbopack`. + +## 4. Π˜ΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠΉΡ‚Π΅ Π½Π° страницС + +```tsx +import { FileManagerIcon } from '@/ui/file-manager/svg-sprite' + +export default function FilesPage() { + return +} + +export function getServerSideProps() { + return { props: {} } +} +``` + +ΠšΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚ ΠΎΠ΄ΠΈΠ½Π°ΠΊΠΎΠ²ΠΎ Ρ€Π°Π±ΠΎΡ‚Π°Π΅Ρ‚ ΠΏΡ€ΠΈ SSR, SSG ΠΈ клиСнтских ΠΏΠ΅Ρ€Π΅Ρ…ΠΎΠ΄Π°Ρ…. Next.js выпускаСт ΠΎΡ‚Π΄Π΅Π»ΡŒΠ½Ρ‹ΠΉ SVG asset с content hash. + +## 5. Π”ΠΎΠ±Π°Π²ΡŒΡ‚Π΅ SpriteViewer + +```tsx +import { SpriteViewer } from '@gromlab/svg-sprites/react' + +const sources = [ + () => import('@/ui/file-manager/svg-sprite/manifest'), +] + +export default function SpritesPage() { + return +} +``` + +## ΠŸΡ€ΠΎΠ²Π΅Ρ€ΠΊΠ° сборщика + +```bash +# Turbopack +npx next build --turbopack + +# Webpack 5 +npx next build --webpack +``` + +Для Next 12–15 с Webpack ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠΉΡ‚Π΅ `npx next build` Π±Π΅Π· Ρ„Π»Π°Π³Π°. + +Команда Next.js ΠΈ mode key Π³Π΅Π½Π΅Ρ€Π°Ρ‚ΠΎΡ€Π° Π΄ΠΎΠ»ΠΆΠ½Ρ‹ ΡƒΠΊΠ°Π·Ρ‹Π²Π°Ρ‚ΡŒ ΠΎΠ΄ΠΈΠ½ ΠΈ Ρ‚ΠΎΡ‚ ΠΆΠ΅ сборщик. diff --git a/skills/artifacts/svg-sprites-ru/references/docs/ru/programmatic-api.md b/skills/artifacts/svg-sprites-ru/references/docs/ru/programmatic-api.md new file mode 100644 index 0000000..999cd01 --- /dev/null +++ b/skills/artifacts/svg-sprites-ru/references/docs/ru/programmatic-api.md @@ -0,0 +1,203 @@ +# ΠŸΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠ½Ρ‹ΠΉ API + +[← Главная](../../README_RU.md) + +ΠŸΠ°ΠΊΠ΅Ρ‚ прСдоставляСт ΠΎΡΠ½ΠΎΠ²Π½ΡƒΡŽ Node.js Ρ‚ΠΎΡ‡ΠΊΡƒ Π²Ρ…ΠΎΠ΄Π° ΠΈ ΠΎΡ‚Π΄Π΅Π»ΡŒΠ½Ρ‹ΠΉ React runtime entry. ОбС Ρ‚ΠΎΡ‡ΠΊΠΈ Ρ€Π°ΡΠΏΡ€ΠΎΡΡ‚Ρ€Π°Π½ΡΡŽΡ‚ΡΡ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ ΠΊΠ°ΠΊ ESM ΠΈ ΠΏΠΎΠ΄ΠΊΠ»ΡŽΡ‡Π°ΡŽΡ‚ΡΡ Ρ‡Π΅Ρ€Π΅Π· `import`. + +Для Ρ€Π°Π·Ρ€Π΅ΡˆΠ΅Π½ΠΈΡ `@gromlab/svg-sprites/react` Π² TypeScript ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠΉΡ‚Π΅ `moduleResolution: "bundler"`, `"node16"` ΠΈΠ»ΠΈ `"nodenext"`. + +## Основной entry + +```ts +import { + defineNextSpriteConfig, + defineReactSpriteConfig, + generateNextSprite, + generateReactSprite, +} from '@gromlab/svg-sprites' +``` + +Основной entry Π½Π΅ ΠΈΠΌΠΏΠΎΡ€Ρ‚ΠΈΡ€ΡƒΠ΅Ρ‚ React ΠΈ ΠΌΠΎΠΆΠ΅Ρ‚ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒΡΡ Π² CLI, build scripts ΠΈ Node.js инструмСнтах. + +## `generateReactSprite` + +```ts +import { generateReactSprite } from '@gromlab/svg-sprites' + +const result = await generateReactSprite( + 'src/ui/file-manager/svg-sprite', + 'vite', +) +``` + +Π’Ρ‚ΠΎΡ€ΠΎΠΉ Π°Ρ€Π³ΡƒΠΌΠ΅Π½Ρ‚ обязатСлСн: + +```ts +type ReactAssetTarget = 'vite' | 'webpack' +``` + +Π Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚: + +```ts +type ReactSpriteGenerationResult = { + name: string + rootDir: string + generatedDir: string + spritePath: string + manifestPath: string + iconCount: number + target: 'vite' | 'webpack' +} +``` + +```ts +console.log(result.name) +console.log(result.iconCount) +console.log(result.spritePath) +console.log(result.manifestPath) +``` + +Ѐункция Π·Π°Π³Ρ€ΡƒΠΆΠ°Π΅Ρ‚ `svg-sprite.config.ts` ΠΈΠ· ΡƒΠΊΠ°Π·Π°Π½Π½ΠΎΠ³ΠΎ корня, ΠΊΠΎΠΌΠΏΠΈΠ»ΠΈΡ€ΡƒΠ΅Ρ‚ SVG ΠΈ бСзопасно обновляСт managed-Ρ„Π°ΠΉΠ»Ρ‹. + +## `generateNextSprite` + +```ts +import { generateNextSprite } from '@gromlab/svg-sprites' + +const result = await generateNextSprite( + 'src/ui/file-manager/svg-sprite', + { + router: 'app', + bundler: 'turbopack', + }, +) +``` + +ДоступныС значСния: + +```ts +type NextSpriteGenerationOptions = { + router: 'app' | 'pages' + bundler: 'turbopack' | 'webpack' +} +``` + +Π Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ Π΄ΠΎΠΏΠΎΠ»Π½ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎ содСрТит Π²Ρ‹Π±Ρ€Π°Π½Π½Ρ‹Π΅ `router`, `bundler` ΠΈ ΠΏΠΎΠ»Π½Ρ‹ΠΉ target Π²ΠΈΠ΄Π° `next@app/turbopack`. + +## `defineReactSpriteConfig` + +```ts +import { defineReactSpriteConfig } from '@gromlab/svg-sprites' + +export default defineReactSpriteConfig({ + name: 'file-manager', + description: 'Иконки Ρ„Π°ΠΉΠ»ΠΎΠ²ΠΎΠ³ΠΎ ΠΌΠ΅Π½Π΅Π΄ΠΆΠ΅Ρ€Π°', + inputFolder: './icons', + inputFiles: [ + '../../shared/icons/check.svg', + ], + transform: { + removeSize: true, + replaceColors: true, + addTransition: true, + }, + generatedNotice: true, +}) +``` + +`inputFolder` ΠΈ `inputFiles` ΠΎΠ±ΡŠΠ΅Π΄ΠΈΠ½ΡΡŽΡ‚ΡΡ. Π₯Π΅Π»ΠΏΠ΅Ρ€ Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅Ρ‚ ΠΊΠΎΠ½Ρ„ΠΈΠ³ Π±Π΅Π· runtime-ΠΏΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΠΎΠ²Π°Π½ΠΈΠΉ ΠΈ прСдоставляСт TypeScript autocomplete. + +## `defineNextSpriteConfig` + +```ts +import { defineNextSpriteConfig } from '@gromlab/svg-sprites' + +export default defineNextSpriteConfig({ + name: 'file-manager', + description: 'Иконки Ρ„Π°ΠΉΠ»ΠΎΠ²ΠΎΠ³ΠΎ ΠΌΠ΅Π½Π΅Π΄ΠΆΠ΅Ρ€Π°', + inputFolder: './icons', +}) +``` + +Next.js ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ Ρ‚ΠΎΡ‚ ΠΆΠ΅ ΠΊΠΎΠ½Ρ‚Ρ€Π°ΠΊΡ‚ ΠΊΠΎΠ½Ρ„ΠΈΠ³ΡƒΡ€Π°Ρ†ΠΈΠΈ, Ρ‡Ρ‚ΠΎ ΠΈ React presets. + +## `generateLegacy` + +```ts +import { generateLegacy } from '@gromlab/svg-sprites' + +const results = await generateLegacy({ + output: 'public/sprites', + preview: false, + sprites: [ + { + name: 'icons', + input: 'src/assets/icons', + format: 'symbol', + }, + ], +}) +``` + +ВозвращаСтся массив: + +```ts +type SpriteResult = { + name: string + format: 'symbol' | 'stack' + spritePath: string + iconCount: number +} +``` + +ΠŸΠΎΠ΄Ρ€ΠΎΠ±Π½Π΅Π΅: [Legacy mode](legacy.md). + +## НизкоуровнСвыС Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ + +Основная Ρ‚ΠΎΡ‡ΠΊΠ° Π²Ρ…ΠΎΠ΄Π° Ρ‚Π°ΠΊΠΆΠ΅ экспортируСт: + +```ts +import { + compileSprite, + compileSpriteContent, + createShapeTransform, + generatePreview, + loadLegacyConfig, + loadReactSpriteConfig, + resolveSpriteEntry, + resolveSprites, +} from '@gromlab/svg-sprites' +``` + +Π­Ρ‚ΠΈ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ ΠΏΡ€Π΅Π΄Π½Π°Π·Π½Π°Ρ‡Π΅Π½Ρ‹ для собствСнного orchestration ΠΏΠΎΠ²Π΅Ρ€Ρ… ΡΡƒΡ‰Π΅ΡΡ‚Π²ΡƒΡŽΡ‰Π΅Π³ΠΎ compiler ΠΈ writer. Для стандартного использования ΠΏΡ€Π΅Π΄ΠΏΠΎΡ‡Ρ‚ΠΈΡ‚Π΅Π»ΡŒΠ½Ρ‹ `generateReactSprite` ΠΈ `generateLegacy`. + +## React runtime entry + +```tsx +import { SpriteViewer } from '@gromlab/svg-sprites/react' +``` + +Π’ΠΈΠΏΡ‹: + +```ts +import type { + SpriteManifest, + SpriteManifestColor, + SpriteManifestIcon, + SpriteManifestLoader, + SpriteManifestModule, + SpriteViewerColorTheme, + SpriteViewerProps, + SpriteViewerSource, + SpriteViewerSources, +} from '@gromlab/svg-sprites/react' +``` + +React entry содСрТит `'use client'` ΠΈ ΠΏΡ€Π΅Π΄Π½Π°Π·Π½Π°Ρ‡Π΅Π½ для debug-инструмСнтов. Generated production-ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Ρ‹ ΠΈΠΌΠΏΠΎΡ€Ρ‚ΠΈΡ€ΡƒΡŽΡ‚ΡΡ ΠΈΠ· Π»ΠΎΠΊΠ°Π»ΡŒΠ½Ρ‹Ρ… sprite-ΠΌΠΎΠ΄ΡƒΠ»Π΅ΠΉ прилоТСния, Π° Π½Π΅ ΠΈΠ· React entry ΠΏΠ°ΠΊΠ΅Ρ‚Π°. + +`SpriteViewerProps.colorTheme` ΠΏΡ€ΠΈΠ½ΠΈΠΌΠ°Π΅Ρ‚ `auto | light | dark`. Π—Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ `auto` ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ΡΡ ΠΏΠΎ ΡƒΠΌΠΎΠ»Ρ‡Π°Π½ΠΈΡŽ ΠΈ слСдуСт `prefers-color-scheme`; для синхронизации с Ρ‚Π΅ΠΌΠΎΠΉ прилоТСния ΠΏΠ΅Ρ€Π΅Π΄Π°Π²Π°ΠΉΡ‚Π΅ вычислСнноС `light` ΠΈΠ»ΠΈ `dark`. + +## БвязанныС руководства + +- [React + Vite](react-vite.md) +- [React + Webpack 5](react-webpack.md) diff --git a/skills/artifacts/svg-sprites-ru/references/docs/ru/react-vite.md b/skills/artifacts/svg-sprites-ru/references/docs/ru/react-vite.md new file mode 100644 index 0000000..2ae3b39 --- /dev/null +++ b/skills/artifacts/svg-sprites-ru/references/docs/ru/react-vite.md @@ -0,0 +1,116 @@ +# React + Vite + +[← Главная](../../README_RU.md) + +ΠšΡ€Π°Ρ‚ΠΊΠ°Ρ инструкция ΠΏΠΎ установкС ΠΈ использованию SVG-спрайтов Π² ΠΏΡ€ΠΎΠ΅ΠΊΡ‚Π΅ Π½Π° React ΠΈ Vite. + +Π’ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Π΅ Π²Ρ‹ ΠΏΠΎΠ»ΡƒΡ‡ΠΈΡ‚Π΅ Ρ‚ΠΈΠΏΠΈΠ·ΠΈΡ€ΠΎΠ²Π°Π½Π½Ρ‹ΠΉ React-ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚ ΠΈ ΠΎΡ‚Π΄Π΅Π»ΡŒΠ½Ρ‹ΠΉ ΠΊΠ΅ΡˆΠΈΡ€ΡƒΠ΅ΠΌΡ‹ΠΉ SVG asset. + +## 1. УстановитС ΠΏΠ°ΠΊΠ΅Ρ‚ + +```bash +npm install @gromlab/svg-sprites +``` + +## 2. Π‘ΠΎΠ·Π΄Π°ΠΉΡ‚Π΅ ΠΏΠ°ΠΏΠΊΡƒ спрайта + +```text +src/ui/file-manager/svg-sprite/ +β”œβ”€β”€ icons/ +β”‚ β”œβ”€β”€ check.svg +β”‚ └── folder.svg +└── svg-sprite.config.ts +``` + +ΠŸΠΎΠΌΠ΅ΡΡ‚ΠΈΡ‚Π΅ исходныС SVG-Ρ„Π°ΠΉΠ»Ρ‹ Π² `icons/`. + +## 3. Π”ΠΎΠ±Π°Π²ΡŒΡ‚Π΅ ΠΊΠΎΠ½Ρ„ΠΈΠ³ + +```ts +// src/ui/file-manager/svg-sprite/svg-sprite.config.ts +import { defineReactSpriteConfig } from '@gromlab/svg-sprites' + +export default defineReactSpriteConfig({ + name: 'file-manager', + description: 'Иконки Ρ„Π°ΠΉΠ»ΠΎΠ²ΠΎΠ³ΠΎ ΠΌΠ΅Π½Π΅Π΄ΠΆΠ΅Ρ€Π°', +}) +``` + +По ΡƒΠΌΠΎΠ»Ρ‡Π°Π½ΠΈΡŽ SVG бСрутся ΠΈΠ· `./icons`. ΠžΠ±Ρ‰ΠΈΠ΅ ΠΈΠΊΠΎΠ½ΠΊΠΈ ΠΈΠ· Π΄Ρ€ΡƒΠ³ΠΈΡ… ΠΏΠ°ΠΏΠΎΠΊ ΠΌΠΎΠΆΠ½ΠΎ Π΄ΠΎΠ±Π°Π²ΠΈΡ‚ΡŒ Ρ‡Π΅Ρ€Π΅Π· `inputFiles`: ΠΏΠ°ΠΏΠΊΠ° ΠΈ список ΠΎΠ±ΡŠΠ΅Π΄ΠΈΠ½ΡΡŽΡ‚ΡΡ Π² ΠΎΠ΄ΠΈΠ½ спрайт. + +ΠŸΠΎΠ»Π½Ρ‹ΠΉ список ΠΎΠΏΡ†ΠΈΠΉ находится Π² Ρ€Π°Π·Π΄Π΅Π»Π΅ [ΠšΠΎΠ½Ρ„ΠΈΠ³ΡƒΡ€Π°Ρ†ΠΈΡ β†’ React](../../README_RU.md#react). + +## 4. Π”ΠΎΠ±Π°Π²ΡŒΡ‚Π΅ Π³Π΅Π½Π΅Ρ€Π°Ρ†ΠΈΡŽ Π² package.json + +```json +{ + "scripts": { + "sprite:file-manager": "svg-sprites --mode react@vite src/ui/file-manager/svg-sprite", + "predev": "npm run sprite:file-manager", + "prebuild": "npm run sprite:file-manager", + "pretypecheck": "npm run sprite:file-manager" + } +} +``` + +Generated-Ρ„Π°ΠΉΠ»Ρ‹ ΠΈΡΠΊΠ»ΡŽΡ‡Π°ΡŽΡ‚ΡΡ ΠΈΠ· Git, поэтому гСнСрация Π΄ΠΎΠ»ΠΆΠ½Π° Π²Ρ‹ΠΏΠΎΠ»Π½ΡΡ‚ΡŒΡΡ ΠΏΠ΅Ρ€Π΅Π΄ `dev`, `build` ΠΈ `typecheck`. + +ΠŸΠ΅Ρ€Π²Ρ‹ΠΉ запуск: + +```bash +npm run sprite:file-manager +``` + +## 5. Π˜ΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠΉΡ‚Π΅ ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚ + +Имя `file-manager` прСобразуСтся Π² `FileManagerIcon`: + +```tsx +import { FileManagerIcon } from './svg-sprite' + +export const OpenFolderButton = () => ( + +) +``` + +Π—Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ `icon` провСряСтся TypeScript ΠΏΠΎ ΠΈΠΌΠ΅Π½Π°ΠΌ Ρ„Π°ΠΉΠ»ΠΎΠ²: + +```tsx + // допустимо + // ошибка TypeScript +``` + +Π’ΠΈΠΏΡ‹, способы отобраТСния ΠΈ ΡƒΠΏΡ€Π°Π²Π»Π΅Π½ΠΈΠ΅ Ρ†Π²Π΅Ρ‚Π°ΠΌΠΈ описаны Π² [основной Π΄ΠΎΠΊΡƒΠΌΠ΅Π½Ρ‚Π°Ρ†ΠΈΠΈ](../../README_RU.md#способы-отобраТСния). + +Vite выпустит спрайт ΠΎΡ‚Π΄Π΅Π»ΡŒΠ½Ρ‹ΠΌ Ρ„Π°ΠΉΠ»ΠΎΠΌ Π²ΠΈΠ΄Π° `assets/sprite-.svg`. SVG path-Π΄Π°Π½Π½Ρ‹Π΅ Π½Π΅ ΠΏΠΎΠΏΠ°Π΄ΡƒΡ‚ Π² JavaScript. + +## 6. Π”ΠΎΠ±Π°Π²ΡŒΡ‚Π΅ debug-страницу + +ПослС ΠΏΠΎΠ΄ΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΡ ΠΈΠΊΠΎΠ½ΠΎΠΊ ΠΌΠΎΠΆΠ½ΠΎ вывСсти всС React-спрайты Ρ‡Π΅Ρ€Π΅Π· `SpriteViewer`: + +```tsx +import { SpriteViewer } from '@gromlab/svg-sprites/react' +import type { SpriteManifestModule } from '@gromlab/svg-sprites/react' + +const sources = import.meta.glob( + '/src/**/svg-sprite/manifest.ts', +) + +export const IconsDebugPage = () => ( + +) +``` + +Vite автоматичСски Π½Π°ΠΉΠ΄Ρ‘Ρ‚ generated `manifest.ts` ΠΊΠ°ΠΆΠ΄ΠΎΠ³ΠΎ React-спрайта. Π¨Π°Π±Π»ΠΎΠ½ `import.meta.glob` Π΄ΠΎΠ»ΠΆΠ΅Π½ Π±Ρ‹Ρ‚ΡŒ строковым Π»ΠΈΡ‚Π΅Ρ€Π°Π»ΠΎΠΌ, Π° гСнСрация Π΄ΠΎΠ»ΠΆΠ½Π° Π²Ρ‹ΠΏΠΎΠ»Π½ΠΈΡ‚ΡŒΡΡ Π΄ΠΎ запуска Vite. + +Π Π°Π·ΠΌΠ΅Ρ‰Π°ΠΉΡ‚Π΅ Viewer Ρ‚ΠΎΠ»ΡŒΠΊΠΎ Π½Π° debug-ΠΌΠ°Ρ€ΡˆΡ€ΡƒΡ‚Π΅ ΠΈΠ»ΠΈ Π²ΠΎ Π²Π½ΡƒΡ‚Ρ€Π΅Π½Π½Π΅ΠΌ инструмСнтС. + +## Если Ρ‡Ρ‚ΠΎ-Ρ‚ΠΎ Π½Π΅ Ρ€Π°Π±ΠΎΡ‚Π°Π΅Ρ‚ + +- НСт `index.ts`: запуститС `npm run sprite:file-manager`. +- Viewer Π½Π΅ Π²ΠΈΠ΄ΠΈΡ‚ спрайт: ΠΏΡ€ΠΎΠ²Π΅Ρ€ΡŒΡ‚Π΅ ΠΏΡƒΡ‚ΡŒ glob ΠΈ Π½Π°Π»ΠΈΡ‡ΠΈΠ΅ `manifest.ts`. +- Ошибка `Refusing to overwrite a user file`: Π² generated-ΠΏΡƒΡ‚ΠΈ находится ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»ΡŒΡΠΊΠΈΠΉ Ρ„Π°ΠΉΠ». +- Иконка Π½Π΅ мСняСт Ρ†Π²Π΅Ρ‚: ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠΉΡ‚Π΅ `color` ΠΈΠ»ΠΈ `--icon-color-N`. diff --git a/skills/artifacts/svg-sprites-ru/references/docs/ru/react-webpack.md b/skills/artifacts/svg-sprites-ru/references/docs/ru/react-webpack.md new file mode 100644 index 0000000..2a3c015 --- /dev/null +++ b/skills/artifacts/svg-sprites-ru/references/docs/ru/react-webpack.md @@ -0,0 +1,118 @@ +# React + Webpack 5 + +[← Главная](../../README_RU.md) + +ΠšΡ€Π°Ρ‚ΠΊΠ°Ρ инструкция ΠΏΠΎ установкС ΠΈ использованию SVG-спрайтов Π² ΠΏΡ€ΠΎΠ΅ΠΊΡ‚Π΅ Π½Π° React ΠΈ Webpack 5. + +Π’ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Π΅ Π²Ρ‹ ΠΏΠΎΠ»ΡƒΡ‡ΠΈΡ‚Π΅ Ρ‚ΠΈΠΏΠΈΠ·ΠΈΡ€ΠΎΠ²Π°Π½Π½Ρ‹ΠΉ React-ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚ ΠΈ ΠΎΡ‚Π΄Π΅Π»ΡŒΠ½Ρ‹ΠΉ SVG asset Ρ‡Π΅Ρ€Π΅Π· Webpack Asset Modules. + +## 1. УстановитС ΠΏΠ°ΠΊΠ΅Ρ‚ + +```bash +npm install @gromlab/svg-sprites +``` + +## 2. Π‘ΠΎΠ·Π΄Π°ΠΉΡ‚Π΅ ΠΏΠ°ΠΏΠΊΡƒ спрайта + +```text +src/ui/file-manager/svg-sprite/ +β”œβ”€β”€ icons/ +β”‚ β”œβ”€β”€ check.svg +β”‚ └── folder.svg +└── svg-sprite.config.ts +``` + +ΠŸΠΎΠΌΠ΅ΡΡ‚ΠΈΡ‚Π΅ исходныС SVG-Ρ„Π°ΠΉΠ»Ρ‹ Π² `icons/`. + +## 3. Π”ΠΎΠ±Π°Π²ΡŒΡ‚Π΅ ΠΊΠΎΠ½Ρ„ΠΈΠ³ + +```ts +// src/ui/file-manager/svg-sprite/svg-sprite.config.ts +import { defineReactSpriteConfig } from '@gromlab/svg-sprites' + +export default defineReactSpriteConfig({ + name: 'file-manager', + description: 'Иконки Ρ„Π°ΠΉΠ»ΠΎΠ²ΠΎΠ³ΠΎ ΠΌΠ΅Π½Π΅Π΄ΠΆΠ΅Ρ€Π°', +}) +``` + +По ΡƒΠΌΠΎΠ»Ρ‡Π°Π½ΠΈΡŽ SVG бСрутся ΠΈΠ· `./icons`. ΠžΠ±Ρ‰ΠΈΠ΅ ΠΈΠΊΠΎΠ½ΠΊΠΈ ΠΈΠ· Π΄Ρ€ΡƒΠ³ΠΈΡ… ΠΏΠ°ΠΏΠΎΠΊ ΠΌΠΎΠΆΠ½ΠΎ Π΄ΠΎΠ±Π°Π²ΠΈΡ‚ΡŒ Ρ‡Π΅Ρ€Π΅Π· `inputFiles`: ΠΏΠ°ΠΏΠΊΠ° ΠΈ список ΠΎΠ±ΡŠΠ΅Π΄ΠΈΠ½ΡΡŽΡ‚ΡΡ Π² ΠΎΠ΄ΠΈΠ½ спрайт. + +ΠŸΠΎΠ»Π½Ρ‹ΠΉ список ΠΎΠΏΡ†ΠΈΠΉ находится Π² Ρ€Π°Π·Π΄Π΅Π»Π΅ [ΠšΠΎΠ½Ρ„ΠΈΠ³ΡƒΡ€Π°Ρ†ΠΈΡ β†’ React](../../README_RU.md#react). + +## 4. Π”ΠΎΠ±Π°Π²ΡŒΡ‚Π΅ Π³Π΅Π½Π΅Ρ€Π°Ρ†ΠΈΡŽ Π² package.json + +```json +{ + "scripts": { + "sprite:file-manager": "svg-sprites --mode react@webpack src/ui/file-manager/svg-sprite", + "predev": "npm run sprite:file-manager", + "prebuild": "npm run sprite:file-manager", + "pretypecheck": "npm run sprite:file-manager" + } +} +``` + +Generated-Ρ„Π°ΠΉΠ»Ρ‹ ΠΈΡΠΊΠ»ΡŽΡ‡Π°ΡŽΡ‚ΡΡ ΠΈΠ· Git, поэтому гСнСрация Π΄ΠΎΠ»ΠΆΠ½Π° Π²Ρ‹ΠΏΠΎΠ»Π½ΡΡ‚ΡŒΡΡ ΠΏΠ΅Ρ€Π΅Π΄ `dev`, `build` ΠΈ `typecheck`. + +ΠŸΠ΅Ρ€Π²Ρ‹ΠΉ запуск: + +```bash +npm run sprite:file-manager +``` + +## 5. Π˜ΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠΉΡ‚Π΅ ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚ + +```tsx +import { FileManagerIcon } from './svg-sprite' + +export const OpenFolderButton = () => ( + +) +``` + +Π—Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ `icon` провСряСтся TypeScript ΠΏΠΎ ΠΈΠΌΠ΅Π½Π°ΠΌ Ρ„Π°ΠΉΠ»ΠΎΠ²: + +```tsx + // допустимо + // ошибка TypeScript +``` + +Π’ΠΈΠΏΡ‹, способы отобраТСния ΠΈ ΡƒΠΏΡ€Π°Π²Π»Π΅Π½ΠΈΠ΅ Ρ†Π²Π΅Ρ‚Π°ΠΌΠΈ описаны Π² [основной Π΄ΠΎΠΊΡƒΠΌΠ΅Π½Ρ‚Π°Ρ†ΠΈΠΈ](../../README_RU.md#способы-отобраТСния). + +Webpack ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Π°Π΅Ρ‚ generated `new URL('./sprite.svg', import.meta.url)` Ρ‡Π΅Ρ€Π΅Π· Asset Modules ΠΈ выпустит ΠΎΡ‚Π΄Π΅Π»ΡŒΠ½Ρ‹ΠΉ SVG asset. + +Если ΠΏΡ€ΠΎΠ΅ΠΊΡ‚ ΡƒΠΆΠ΅ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ собствСнный SVG loader, ΡƒΠ±Π΅Π΄ΠΈΡ‚Π΅ΡΡŒ, Ρ‡Ρ‚ΠΎ ΠΎΠ½ Π½Π΅ ΠΏΠ΅Ρ€Π΅Ρ…Π²Π°Ρ‚Ρ‹Π²Π°Π΅Ρ‚ generated `sprite.svg` вмСсто Asset Modules. + +## 6. Π”ΠΎΠ±Π°Π²ΡŒΡ‚Π΅ debug-страницу + +Webpack Π½Π΅ ΠΏΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΈΠ²Π°Π΅Ρ‚ Vite API `import.meta.glob`, поэтому ΠΏΠ΅Ρ€Π΅Π΄Π°ΠΉΡ‚Π΅ статичСскиС loaders: + +```tsx +import { SpriteViewer } from '@gromlab/svg-sprites/react' + +const sources = [ + () => import('./ui/file-manager/svg-sprite/manifest'), + () => import('./ui/navigation/svg-sprite/manifest'), +] + +export const IconsDebugPage = () => ( + +) +``` + +ΠŸΡƒΡ‚ΠΈ Π² `import()` Π΄ΠΎΠ»ΠΆΠ½Ρ‹ Π±Ρ‹Ρ‚ΡŒ строковыми Π»ΠΈΡ‚Π΅Ρ€Π°Π»Π°ΠΌΠΈ. Webpack создаст chunks для манифСстов ΠΈ свяТСт ΠΈΡ… с SVG assets. + +Π Π°Π·ΠΌΠ΅Ρ‰Π°ΠΉΡ‚Π΅ Viewer Ρ‚ΠΎΠ»ΡŒΠΊΠΎ Π½Π° debug-ΠΌΠ°Ρ€ΡˆΡ€ΡƒΡ‚Π΅ ΠΈΠ»ΠΈ Π²ΠΎ Π²Π½ΡƒΡ‚Ρ€Π΅Π½Π½Π΅ΠΌ инструмСнтС. + +## Если Ρ‡Ρ‚ΠΎ-Ρ‚ΠΎ Π½Π΅ Ρ€Π°Π±ΠΎΡ‚Π°Π΅Ρ‚ + +- НСт `index.ts`: запуститС `npm run sprite:file-manager`. +- Viewer Π½Π΅ Π·Π°Π³Ρ€ΡƒΠΆΠ°Π΅Ρ‚ спрайт: ΠΏΡ€ΠΎΠ²Π΅Ρ€ΡŒΡ‚Π΅ ΠΏΡƒΡ‚ΡŒ Π² `import()` ΠΈ Π½Π°Π»ΠΈΡ‡ΠΈΠ΅ `manifest.ts`. +- НСвСрный URL asset: ΠΏΡ€ΠΎΠ²Π΅Ρ€ΡŒΡ‚Π΅ `output.publicPath`. +- SVG ΠΏΠ΅Ρ€Π΅Ρ…Π²Π°Ρ‚Ρ‹Π²Π°Π΅Ρ‚ Π΄Ρ€ΡƒΠ³ΠΎΠΉ loader: ΠΈΡΠΊΠ»ΡŽΡ‡ΠΈΡ‚Π΅ generated sprite ΠΈΠ· нСсовмСстимого ΠΏΡ€Π°Π²ΠΈΠ»Π°. + +Для Next.js ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠΉΡ‚Π΅ ΠΎΡ‚Π΄Π΅Π»ΡŒΠ½Ρ‹Π΅ mode key ΠΈΠ· руководств [App Router](next-app.md) ΠΈ [Pages Router](next-pages.md). diff --git a/skills/artifacts/svg-sprites/SKILL.md b/skills/artifacts/svg-sprites/SKILL.md index ffdecf1..b33bec8 100644 --- a/skills/artifacts/svg-sprites/SKILL.md +++ b/skills/artifacts/svg-sprites/SKILL.md @@ -1,64 +1,64 @@ --- name: svg-sprites -description: "Π˜ΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠΉ ΠΏΡ€ΠΈ настройкС, Π³Π΅Π½Π΅Ρ€Π°Ρ†ΠΈΠΈ, ΠΌΠΈΠ³Ρ€Π°Ρ†ΠΈΠΈ ΠΈΠ»ΠΈ диагностикС SVG-спрайтов Ρ‡Π΅Ρ€Π΅Π· @gromlab/svg-sprites. Π’Ρ€ΠΈΠ³Π³Π΅Ρ€Ρ‹: SVG sprite, SVG-спрайт, svg-sprites, svg-sprite.config.ts, svg-sprites.config.ts, defineReactSpriteConfig, defineNextSpriteConfig, react@vite, react@webpack, next@app, next@pages, inputFiles, SpriteViewer, icon=\"...\", --icon-color-N, generated-ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚ ΠΈΠ»ΠΈ ΠΈΠΊΠΎΠ½ΠΊΠ° Π½Π΅ появилась Π² ΠΏΡ€Π΅Π²ΡŒΡŽ ΠΈ Π°Π²Ρ‚ΠΎΠ΄ΠΎΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ. НЕ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠΉ для favicon, растровых ΠΈΠ·ΠΎΠ±Ρ€Π°ΠΆΠ΅Π½ΠΈΠΉ, icon fonts, Π²Ρ‹Π±ΠΎΡ€Π° Π½Π°Π±ΠΎΡ€Π° ΠΈΠΊΠΎΠ½ΠΎΠΊ ΠΈΠ»ΠΈ inline SVG Π±Π΅Π· спрайтов." +description: "Use when configuring, generating, migrating, or troubleshooting SVG sprites with @gromlab/svg-sprites. Triggers: SVG sprite, svg-sprites, svg-sprite.config.ts, svg-sprites.config.ts, defineReactSpriteConfig, defineNextSpriteConfig, react@vite, react@webpack, next@app, next@pages, inputFiles, SpriteViewer, icon=\"...\", --icon-color-N, generated component, or an icon missing from preview or autocomplete. Do NOT use for favicons, raster images, icon fonts, choosing an icon set, or inline SVG without sprites." --- # SVG Sprites -## НазначСниС +## Purpose -Π˜ΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠΉ этот скил для Ρ€Π°Π±ΠΎΡ‚Ρ‹ с `@gromlab/svg-sprites`: ΠΏΠ΅Ρ€Π²ΠΈΡ‡Π½ΠΎΠΉ настройки, добавлСния ΠΈ ΠΏΠ΅Ρ€Π΅ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Π½ΠΈΡ ΠΈΠΊΠΎΠ½ΠΎΠΊ, Π³Π΅Π½Π΅Ρ€Π°Ρ†ΠΈΠΈ React-ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚ΠΎΠ², ΠΏΠΎΠ΄ΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΡ `SpriteViewer`, ΠΌΠΈΠ³Ρ€Π°Ρ†ΠΈΠΈ legacy-ΠΊΠΎΠ½Ρ„ΠΈΠ³ΡƒΡ€Π°Ρ†ΠΈΠΈ ΠΈ диагностики ошибок. +Use this skill when working with `@gromlab/svg-sprites`: initial setup, adding and reusing icons, generating React components, integrating `SpriteViewer`, migrating legacy configurations, and troubleshooting errors. -НС навязывай ΠΏΡ€ΠΎΠ΅ΠΊΡ‚Ρƒ ΠΊΠΎΠ½ΠΊΡ€Π΅Ρ‚Π½ΡƒΡŽ Π°Ρ€Ρ…ΠΈΡ‚Π΅ΠΊΡ‚ΡƒΡ€Ρƒ ΠΊΠ°Ρ‚Π°Π»ΠΎΠ³ΠΎΠ². Π‘Π½Π°Ρ‡Π°Π»Π° ΠΈΠ·ΡƒΡ‡ΠΈ ΡΡƒΡ‰Π΅ΡΡ‚Π²ΡƒΡŽΡ‰ΠΈΠ΅ `package.json`, ΠΊΠΎΠ½Ρ„ΠΈΠ³ΡƒΡ€Π°Ρ†ΠΈΡŽ спрайта, ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅ΠΌΡ‹ΠΉ Ρ„Ρ€Π΅ΠΉΠΌΠ²ΠΎΡ€ΠΊ, Ρ€ΠΎΡƒΡ‚Π΅Ρ€ ΠΈ сборщик. +Do not impose a specific directory architecture on the project. First inspect the existing `package.json`, sprite configuration, framework, router, and bundler. -## Π Π°Π±ΠΎΡ‡ΠΈΠΉ Π°Π»Π³ΠΎΡ€ΠΈΡ‚ΠΌ +## Workflow -1. ΠžΠΏΡ€Π΅Π΄Π΅Π»ΠΈ ΡΡƒΡ‰Π΅ΡΡ‚Π²ΡƒΡŽΡ‰ΠΈΠΉ Ρ€Π΅ΠΆΠΈΠΌ ΠΈ Π½Π΅ смСшивай Π΅Π³ΠΎ API с Π΄Ρ€ΡƒΠ³ΠΈΠΌ Ρ€Π΅ΠΆΠΈΠΌΠΎΠΌ. -2. Для React Π²Ρ‹Π±Π΅Ρ€ΠΈ `react@vite` ΠΈΠ»ΠΈ `react@webpack` ΠΈ ΠΎΡ‚ΠΊΡ€ΠΎΠΉ ΡΠΎΠΎΡ‚Π²Π΅Ρ‚ΡΡ‚Π²ΡƒΡŽΡ‰ΠΈΠΉ reference. -3. Для Next.js ΠΎΠΏΡ€Π΅Π΄Π΅Π»ΠΈ App Router ΠΈΠ»ΠΈ Pages Router, Π·Π°Ρ‚Π΅ΠΌ Turbopack ΠΈΠ»ΠΈ Webpack, ΠΈ ΠΎΡ‚ΠΊΡ€ΠΎΠΉ ΡΠΎΠΎΡ‚Π²Π΅Ρ‚ΡΡ‚Π²ΡƒΡŽΡ‰ΠΈΠΉ reference. -4. Для ΡΡƒΡ‰Π΅ΡΡ‚Π²ΡƒΡŽΡ‰Π΅Π³ΠΎ `svg-sprites.config.ts` с нСсколькими спрайтами ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠΉ legacy-Π΄ΠΎΠΊΡƒΠΌΠ΅Π½Ρ‚Π°Ρ†ΠΈΡŽ. НС ΠΌΠΈΠ³Ρ€ΠΈΡ€ΡƒΠΉ Ρ‚Π°ΠΊΠΎΠΉ ΠΏΡ€ΠΎΠ΅ΠΊΡ‚ Π±Π΅Π· явного запроса. -5. Π˜Π·ΡƒΡ‡ΠΈ Π»ΠΎΠΊΠ°Π»ΡŒΠ½Ρ‹Π΅ scripts ΠΈ добавляй Π³Π΅Π½Π΅Ρ€Π°Ρ†ΠΈΡŽ ΠΏΠ΅Ρ€Π΅Π΄ `dev`, `build` ΠΈ `typecheck`, Ссли generated-Ρ„Π°ΠΉΠ»Ρ‹ Π½Π΅ хранятся Π² Git. -6. ПослС измСнСния ΠΊΠΎΠ½Ρ„ΠΈΠ³ΡƒΡ€Π°Ρ†ΠΈΠΈ ΠΈΠ»ΠΈ SVG запусти Π³Π΅Π½Π΅Ρ€Π°Ρ†ΠΈΡŽ, Π·Π°Ρ‚Π΅ΠΌ Π΄ΠΎΡΡ‚ΡƒΠΏΠ½ΡƒΡŽ ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΊΡƒ Ρ‚ΠΈΠΏΠΎΠ² ΠΈΠ»ΠΈ сборку ΠΏΡ€ΠΎΠ΅ΠΊΡ‚Π°. +1. Identify the existing mode and do not mix its API with another mode. +2. For React, choose `react@vite` or `react@webpack` and open the corresponding reference. +3. For Next.js, identify the App Router or Pages Router, then Turbopack or Webpack, and open the corresponding reference. +4. For an existing `svg-sprites.config.ts` with multiple sprites, use the legacy documentation. Do not migrate such a project unless explicitly requested. +5. Inspect local scripts and run generation before `dev`, `build`, and `typecheck` when generated files are not committed to Git. +6. After changing a configuration or SVG file, run generation followed by the available type check or project build. -## ΠŸΡ€Π°Π²ΠΈΠ»Π° React ΠΈ Next.js +## React And Next.js Rules -- Π˜ΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠΉ Π»ΠΎΠΊΠ°Π»ΡŒΠ½Ρ‹ΠΉ `svg-sprite.config.ts` ΠΈ подходящий config helper: `defineReactSpriteConfig` ΠΈΠ»ΠΈ `defineNextSpriteConfig`. -- НС Ρ€Π΅Π΄Π°ΠΊΡ‚ΠΈΡ€ΡƒΠΉ `generated/`, `index.ts`, `manifest.ts` ΠΈ созданный Π³Π΅Π½Π΅Ρ€Π°Ρ‚ΠΎΡ€ΠΎΠΌ `.gitignore` Π²Ρ€ΡƒΡ‡Π½ΡƒΡŽ. -- ИмСна исходных SVG становятся допустимыми значСниями prop `icon`; ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠΉ generated-ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚ ΠΈ Π΅Π³ΠΎ ΠΏΡƒΠ±Π»ΠΈΡ‡Π½Ρ‹Π΅ Ρ‚ΠΈΠΏΡ‹ вмСсто deep imports. -- ОбъСдиняй Π»ΠΎΠΊΠ°Π»ΡŒΠ½ΡƒΡŽ ΠΏΠ°ΠΏΠΊΡƒ ΠΈ `inputFiles`, ΠΊΠΎΠ³Π΄Π° общая ΠΈΠΊΠΎΠ½ΠΊΠ° Π½ΡƒΠΆΠ½Π° нСскольким спрайтам. НС создавай ΠΊΠΎΠΏΠΈΠΈ ΠΎΠ΄Π½ΠΎΠ³ΠΎ SVG Π±Π΅Π· нСобходимости. -- Π’ Next.js generated-ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚ ΠΌΠΎΠΆΠ½ΠΎ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ Π² Server Components, SSR ΠΈ SSG. НС добавляй `'use client'` Ρ‚ΠΎΠ»ΡŒΠΊΠΎ Ρ€Π°Π΄ΠΈ ΠΈΠΊΠΎΠ½ΠΊΠΈ. -- Π‘ΠΏΡ€Π°ΠΉΡ‚ Π΄ΠΎΠ»ΠΆΠ΅Π½ ΠΎΡΡ‚Π°Π²Π°Ρ‚ΡŒΡΡ внСшним asset сборщика: Π½Π΅ ΠΏΠ΅Ρ€Π΅Π½ΠΎΡΠΈΡ‚ΡŒ SVG path-Π΄Π°Π½Π½Ρ‹Π΅ Π² JavaScript ΠΈ Π½Π΅ ΠΊΠ»Π°ΡΡ‚ΡŒ generated-Ρ„Π°ΠΉΠ» Π²Ρ€ΡƒΡ‡Π½ΡƒΡŽ Π² `public`. +- Use a local `svg-sprite.config.ts` and the appropriate config helper: `defineReactSpriteConfig` or `defineNextSpriteConfig`. +- Do not manually edit `generated/`, `index.ts`, `manifest.ts`, or the generator-created `.gitignore`. +- Source SVG names become valid values for the `icon` prop; use the generated component and its public types instead of deep imports. +- Combine the local folder with `inputFiles` when multiple sprites need a shared icon. Do not create unnecessary copies of the same SVG. +- In Next.js, generated components work in Server Components, SSR, and SSG. Do not add `'use client'` only for an icon. +- Keep the sprite as an external bundler asset: do not move SVG path data into JavaScript or manually place the generated file in `public`. -## Π¦Π²Π΅Ρ‚Π° ΠΈ трансформации +## Colors And Transformations -- По ΡƒΠΌΠΎΠ»Ρ‡Π°Π½ΠΈΡŽ Π³Π΅Π½Π΅Ρ€Π°Ρ‚ΠΎΡ€ удаляСт `width` ΠΈ `height`, замСняСт ΠΏΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΈΠ²Π°Π΅ΠΌΡ‹Π΅ `fill` ΠΈ `stroke` Π½Π° CSS-ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½Ρ‹Π΅ ΠΈ добавляСт transitions. -- Для ΠΌΠΎΠ½ΠΎΡ…Ρ€ΠΎΠΌΠ½ΠΎΠΉ ΠΈΠΊΠΎΠ½ΠΊΠΈ сначала управляй `color`; для ΠΌΠ½ΠΎΠ³ΠΎΡ†Π²Π΅Ρ‚Π½ΠΎΠΉ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠΉ `--icon-color-N`. -- НС ΠΎΠ±Π΅Ρ‰Π°ΠΉ Π°Π²Ρ‚ΠΎΠΌΠ°Ρ‚ΠΈΡ‡Π΅ΡΠΊΡƒΡŽ Π·Π°ΠΌΠ΅Π½Ρƒ Ρ†Π²Π΅Ρ‚ΠΎΠ² Π²Π½ΡƒΡ‚Ρ€ΠΈ Π²Π½Π΅ΡˆΠ½ΠΈΡ… stylesheets, gradients, patterns, filters ΠΈ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠΉ `url(#...)` Π±Π΅Π· ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΊΠΈ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Π°. -- CSS-ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½Ρ‹Π΅ страницы Ρ€Π°Π±ΠΎΡ‚Π°ΡŽΡ‚ ΠΏΡ€ΠΈ ``, Π½ΠΎ Π½Π΅ ΠΏΡ€ΠΎΠ½ΠΈΠΊΠ°ΡŽΡ‚ Π²Π½ΡƒΡ‚Ρ€ΡŒ `` ΠΈ `background-image`. +- By default, the generator removes `width` and `height`, replaces supported `fill` and `stroke` values with CSS variables, and adds transitions. +- For a monochrome icon, control `color` first; for a multicolor icon, use `--icon-color-N`. +- Do not promise automatic color replacement inside external stylesheets, gradients, patterns, filters, or `url(#...)` values without checking the result. +- Page CSS variables work with ``, but do not propagate into `` or `background-image`. -## ΠŸΡ€Π΅Π²ΡŒΡŽ +## Preview -Для React ΠΈ Next.js ΠΏΠΎΠ΄ΠΊΠ»ΡŽΡ‡Π°ΠΉ `` ΠΎΡ‚Π΄Π΅Π»ΡŒΠ½ΠΎΠΉ debug-страницСй прилоТСния. ΠŸΠ΅Ρ€Π΅Π΄Π°ΠΉ Π΅ΠΌΡƒ manifests ΠΈΠ»ΠΈ lazy loaders спрайтов. Viewer ΠΏΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΈΠ²Π°Π΅Ρ‚ поиск, ΡΠ²Π΅Ρ‚Π»ΡƒΡŽ ΠΈ Ρ‚Ρ‘ΠΌΠ½ΡƒΡŽ Ρ‚Π΅ΠΌΡ‹, настройку Ρ†Π²Π΅Ρ‚ΠΎΠ² ΠΈ ΠΏΡ€ΠΈΠΌΠ΅Ρ€Ρ‹ React, SVG, IMG ΠΈ CSS. +For React and Next.js, add `` as a separate debug page in the application. Pass sprite manifests or lazy loaders to it. The Viewer supports search, light and dark themes, color controls, and React, SVG, IMG, and CSS examples. -`SpriteViewer` являСтся клиСнтским debug-инструмСнтом ΠΈ импортируСтся ΠΈΠ· `@gromlab/svg-sprites/react`; production-ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Ρ‹ ΠΈΠΊΠΎΠ½ΠΎΠΊ ΠΎΡ‚ Π½Π΅Π³ΠΎ Π½Π΅ зависят. +`SpriteViewer` is a client-side debug tool imported from `@gromlab/svg-sprites/react`; production icon components do not depend on it. -## Диагностика +## Troubleshooting -- Если имя ΠΈΠΊΠΎΠ½ΠΊΠΈ отсутствуСт Π² Π°Π²Ρ‚ΠΎΠ΄ΠΎΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ, ΠΏΡ€ΠΎΠ²Π΅Ρ€ΡŒ Π²Ρ…ΠΎΠ΄Π½ΡƒΡŽ ΠΏΠ°ΠΏΠΊΡƒ ΠΈ `inputFiles`, Π·Π°Ρ‚Π΅ΠΌ пСрСзапусти Π³Π΅Π½Π΅Ρ€Π°Ρ†ΠΈΡŽ. -- Если Π΄Π²Π° Ρ„Π°ΠΉΠ»Π° ΠΈΠΌΠ΅ΡŽΡ‚ ΠΎΠ΄ΠΈΠ½Π°ΠΊΠΎΠ²ΠΎΠ΅ имя ΠΈΠΊΠΎΠ½ΠΊΠΈ, устрани ΠΊΠΎΠ½Ρ„Π»ΠΈΠΊΡ‚ вмСсто Π²Ρ‹Π±ΠΎΡ€Π° ΠΎΠ΄Π½ΠΎΠ³ΠΎ Ρ„Π°ΠΉΠ»Π° нСявно. -- Если Π³Π΅Π½Π΅Ρ€Π°Ρ‚ΠΎΡ€ отказываСтся ΠΏΠ΅Ρ€Π΅Π·Π°ΠΏΠΈΡΡ‹Π²Π°Ρ‚ΡŒ Ρ„Π°ΠΉΠ», Π½Π΅ удаляй Π·Π°Ρ‰ΠΈΡ‚Π½Ρ‹ΠΉ marker ΠΈ Π½Π΅ ΠΎΠ±Ρ…ΠΎΠ΄ΠΈ writer: пСрСнСси ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»ΡŒΡΠΊΠΈΠΉ Ρ„Π°ΠΉΠ» ΠΈΠ»ΠΈ Π²Ρ‹Π±Π΅Ρ€ΠΈ Π΄Ρ€ΡƒΠ³ΠΎΠΉ ΠΊΠ°Ρ‚Π°Π»ΠΎΠ³ спрайта. -- Если asset Π½Π΅ загруТаСтся, сначала ΠΏΡ€ΠΎΠ²Π΅Ρ€ΡŒ соотвСтствиС CLI mode Ρ€Π΅Π°Π»ΡŒΠ½ΠΎΠΌΡƒ сборщику ΠΏΡ€ΠΎΠ΅ΠΊΡ‚Π° ΠΈ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΡƒ generated SVG Π΅Π³ΠΎ asset pipeline. -- Если ΠΏΡ€ΠΎΠ΅ΠΊΡ‚ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ старый API, ΡΠ²Π΅Ρ€ΡŒ ΡƒΡΡ‚Π°Π½ΠΎΠ²Π»Π΅Π½Π½ΡƒΡŽ Π²Π΅Ρ€ΡΠΈΡŽ ΠΏΠ°ΠΊΠ΅Ρ‚Π° ΠΈ legacy reference ΠΏΠ΅Ρ€Π΅Π΄ измСнСниями. +- If an icon name is missing from autocomplete, check the input folder and `inputFiles`, then rerun generation. +- If two files have the same icon name, resolve the conflict instead of implicitly selecting one file. +- If the generator refuses to overwrite a file, do not remove the protection marker or bypass the writer: move the user file or choose another sprite directory. +- If an asset fails to load, first confirm that the CLI mode matches the project's actual bundler and that its asset pipeline handles the generated SVG. +- If the project uses the old API, check the installed package version and the legacy reference before making changes. ## References -- [Основная докумСнтация ΠΈ API](./references/README.md) -- [React + Vite](./references/docs/ru/react-vite.md) -- [React + Webpack 5](./references/docs/ru/react-webpack.md) -- [Next.js App Router](./references/docs/ru/next-app.md) -- [Next.js Pages Router](./references/docs/ru/next-pages.md) -- [Legacy mode](./references/docs/ru/legacy.md) -- [ΠœΠΈΠ³Ρ€Π°Ρ†ΠΈΡ с 0.1.x](./references/docs/ru/migration-1.md) -- [ΠŸΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠ½Ρ‹ΠΉ API](./references/docs/ru/programmatic-api.md) +- [Main documentation and API](./references/README.md) +- [React + Vite](./references/docs/en/react-vite.md) +- [React + Webpack 5](./references/docs/en/react-webpack.md) +- [Next.js App Router](./references/docs/en/next-app.md) +- [Next.js Pages Router](./references/docs/en/next-pages.md) +- [Legacy mode](./references/docs/en/legacy.md) +- [Migrating from 0.1.x](./references/docs/en/migration-1.md) +- [Programmatic API](./references/docs/en/programmatic-api.md) diff --git a/skills/artifacts/svg-sprites/references/README.md b/skills/artifacts/svg-sprites/references/README.md index 8242cc9..5461b0e 100644 --- a/skills/artifacts/svg-sprites/references/README.md +++ b/skills/artifacts/svg-sprites/references/README.md @@ -1,77 +1,80 @@ # @gromlab/svg-sprites +πŸ‡¬πŸ‡§ English | [πŸ‡·πŸ‡Ί Русский](README_RU.md) + ![npm](https://img.shields.io/npm/v/@gromlab/svg-sprites) ![license](https://img.shields.io/npm/l/@gromlab/svg-sprites) -CLI для Π³Π΅Π½Π΅Ρ€Π°Ρ†ΠΈΠΈ SVG-спрайтов ΠΈ Ρ‚ΠΈΠΏΠΈΠ·ΠΈΡ€ΠΎΠ²Π°Π½Π½Ρ‹Ρ… ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚ΠΎΠ² ΠΈΠΊΠΎΠ½ΠΎΠΊ для React ΠΈ Next.js. +A CLI for generating SVG sprites and typed icon components for React and Next.js. ![Preview](https://gromlab.ru/gromov/svg-sprites/media/branch/master/preview-image.png) -## Навигация +## Navigation -- [ВозмоТности](#возмоТности) -- [Π’Π°Π±Π»ΠΈΡ†Π° ΠΏΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΊΠΈ](#Ρ‚Π°Π±Π»ΠΈΡ†Π°-ΠΏΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΊΠΈ) -- [ВрСбования](#трСбования) -- [Быстрый старт](#быстрый-старт) - - [React + Vite](docs/ru/react-vite.md) - - [React + Webpack 5](docs/ru/react-webpack.md) - - [Next.js App Router](docs/ru/next-app.md) - - [Next.js Pages Router](docs/ru/next-pages.md) -- [ΠšΠΎΠ½Ρ„ΠΈΠ³ΡƒΡ€Π°Ρ†ΠΈΡ](#конфигурация) +- [Features](#features) +- [Support matrix](#support-matrix) +- [Requirements](#requirements) +- [Quick start](#quick-start) + - [React + Vite](docs/en/react-vite.md) + - [React + Webpack 5](docs/en/react-webpack.md) + - [Next.js App Router](docs/en/next-app.md) + - [Next.js Pages Router](docs/en/next-pages.md) +- [Configuration](#configuration) - [React](#react) - [Next.js](#nextjs) -- [ΠœΠ½ΠΎΠΆΠ΅ΡΡ‚Π²Π΅Π½Π½Ρ‹Π΅ спрайты](#мноТСствСнныС-спрайты) +- [Multiple sprites](#multiple-sprites) - [TypeScript](#typescript) -- [Π€ΠΎΡ€ΠΌΠ°Ρ‚Ρ‹ спрайтов](#Ρ„ΠΎΡ€ΠΌΠ°Ρ‚Ρ‹-спрайтов) -- [Бпособы отобраТСния](#способы-отобраТСния) -- [Врансформации](#трансформации) -- [Π£ΠΏΡ€Π°Π²Π»Π΅Π½ΠΈΠ΅ Ρ†Π²Π΅Ρ‚ΠΎΠΌ ΠΈΠΊΠΎΠ½ΠΎΠΊ](#ΡƒΠΏΡ€Π°Π²Π»Π΅Π½ΠΈΠ΅-Ρ†Π²Π΅Ρ‚ΠΎΠΌ-ΠΈΠΊΠΎΠ½ΠΎΠΊ) -- [ΠšΠ΅ΡˆΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠ΅](#ΠΊΠ΅ΡˆΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠ΅) +- [Sprite formats](#sprite-formats) +- [Rendering methods](#rendering-methods) +- [Transformations](#transformations) +- [Icon color management](#icon-color-management) +- [Caching](#caching) - [SpriteViewer](#spriteviewer) -- [ΠœΠΈΠ³Ρ€Π°Ρ†ΠΈΡ с 0.1.x](docs/ru/migration-1.md) -- [ДокумСнтация](#докумСнтация) +- [Migrating from 0.1.x](docs/en/migration-1.md) +- [Documentation](#documentation) -## ВозмоТности +## Features -- **TypeScript-friendly** β€” Ρ‚ΠΈΠΏΠΈΠ·ΠΈΡ€ΠΎΠ²Π°Π½Π½Ρ‹Π΅ React-ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Ρ‹, union-Ρ‚ΠΈΠΏΡ‹ ΠΈ runtime-списки доступных ΠΈΠΊΠΎΠ½ΠΎΠΊ. -- **Чистая гСнСрация** β€” generated-Ρ„Π°ΠΉΠ»Ρ‹ автоматичСски ΠΈΡΠΊΠ»ΡŽΡ‡Π°ΡŽΡ‚ΡΡ ΠΈΠ· Git, спрайт Π½Π΅ Π½ΡƒΠΆΠ½ΠΎ Π²Ρ€ΡƒΡ‡Π½ΡƒΡŽ Ρ€Π°Π·ΠΌΠ΅Ρ‰Π°Ρ‚ΡŒ Π² `public`, Π° Π³Π΅Π½Π΅Ρ€Π°Ρ‚ΠΎΡ€ обновляСт Ρ‚ΠΎΠ»ΡŒΠΊΠΎ ΠΏΡ€ΠΈΠ½Π°Π΄Π»Π΅ΠΆΠ°Ρ‰ΠΈΠ΅ Π΅ΠΌΡƒ Ρ„Π°ΠΉΠ»Ρ‹. -- **ΠžΠ±Ρ‰ΠΈΠ΅ ΠΈΠΊΠΎΠ½ΠΊΠΈ Π±Π΅Π· копирования** β€” SVG ΠΈΠ· локальной ΠΏΠ°ΠΏΠΊΠΈ ΠΈ `inputFiles` ΠΎΠ±ΡŠΠ΅Π΄ΠΈΠ½ΡΡŽΡ‚ΡΡ Π² ΠΎΠ΄ΠΈΠ½ спрайт; ΠΎΠ΄ΠΈΠ½ Ρ„Π°ΠΉΠ» ΠΌΠΎΠΆΠ½ΠΎ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ Π² Π½Π΅ΡΠΊΠΎΠ»ΡŒΠΊΠΈΡ… спрайтах. -- **ВстроСнноС ΠΈΠ½Ρ‚Π΅Ρ€Π°ΠΊΡ‚ΠΈΠ²Π½ΠΎΠ΅ ΠΏΡ€Π΅Π²ΡŒΡŽ** β€” `` ΠΏΠΎΠ΄ΠΊΠ»ΡŽΡ‡Π°Π΅Ρ‚ΡΡ ΠΊΠ°ΠΊ страница прилоТСния ΠΈ ΠΏΠΎΠΊΠ°Π·Ρ‹Π²Π°Π΅Ρ‚ ΠΏΠ΅Ρ€Π΅Π΄Π°Π½Π½Ρ‹Π΅ React- ΠΈ Next.js-спрайты с поиском, настройкой Ρ†Π²Π΅Ρ‚ΠΎΠ² ΠΈ ΠΏΡ€ΠΈΠΌΠ΅Ρ€Π°ΠΌΠΈ использования. -- **НастраиваСмыС трансформации SVG** β€” ΡƒΠ΄Π°Π»Π΅Π½ΠΈΠ΅ `width` ΠΈ `height` с сохранСниСм `viewBox`, Π·Π°ΠΌΠ΅Π½Π° исходных Ρ†Π²Π΅Ρ‚ΠΎΠ² Π½Π° CSS-ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½Ρ‹Π΅ ΠΈ transitions для `fill` ΠΈ `stroke`. -- **ΠžΡ‚Π΄Π΅Π»ΡŒΠ½Ρ‹ΠΉ ΠΊΠ΅ΡˆΠΈΡ€ΡƒΠ΅ΠΌΡ‹ΠΉ SVG asset** β€” SVG path-Π΄Π°Π½Π½Ρ‹Π΅ Π½Π΅ ΠΏΠΎΠΏΠ°Π΄Π°ΡŽΡ‚ Π² JavaScript chunks, Π° сборщик выпускаСт Ρ„Π°ΠΉΠ» с content hash. -- **ΠœΠ½ΠΎΠΆΠ΅ΡΡ‚Π²Π΅Π½Π½Ρ‹Π΅ спрайты** β€” нСзависимыС React- ΠΈ Next.js-ΠΌΠΎΠ΄ΡƒΠ»ΠΈ со своими ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Π°ΠΌΠΈ, Ρ‚ΠΈΠΏΠ°ΠΌΠΈ ΠΈ SVG assets. -- **Server-first Next.js** β€” generated-ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Ρ‹ Ρ€Π°Π±ΠΎΡ‚Π°ΡŽΡ‚ Π² Server Components, SSR ΠΈ SSG Π±Π΅Π· Π΄ΠΈΡ€Π΅ΠΊΡ‚ΠΈΠ²Ρ‹ `'use client'`. -- **Π€ΠΎΡ€ΠΌΠ°Ρ‚Ρ‹ ΠΏΠΎΠ΄ Ρ€Π°Π·Π½Ρ‹Π΅ сцСнарии** β€” React ΠΈ Next.js ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΡŽΡ‚ `stack`, legacy-Ρ€Π΅ΠΆΠΈΠΌ Ρ‚Π°ΠΊΠΆΠ΅ ΠΏΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΈΠ²Π°Π΅Ρ‚ `symbol` для ΡΡƒΡ‰Π΅ΡΡ‚Π²ΡƒΡŽΡ‰ΠΈΡ… ΠΈΠ½Ρ‚Π΅Π³Ρ€Π°Ρ†ΠΈΠΉ. +- **AI-agent friendly** - the repository includes a ready-to-use skill with up-to-date documentation for configuring, migrating, and troubleshooting `@gromlab/svg-sprites`. +- **TypeScript-friendly** - typed React components, union types, and runtime lists of available icons. +- **Clean generation** - generated files are automatically excluded from Git, the sprite does not need to be placed in `public` manually, and the generator updates only files it owns. +- **Shared icons without copying** - SVGs from the local folder and `inputFiles` are merged into a single sprite; one file can be used in multiple sprites. +- **Built-in interactive preview** - `` is integrated as an application page and displays the provided React and Next.js sprites with search, color controls, and usage examples. +- **Configurable SVG transformations** - remove `width` and `height` while preserving `viewBox`, replace source colors with CSS variables, and add transitions for `fill` and `stroke`. +- **Separate cacheable SVG asset** - SVG path data does not end up in JavaScript chunks, and the bundler emits a file with a content hash. +- **Multiple sprites** - independent React and Next.js modules with their own components, types, and SVG assets. +- **Server-first Next.js** - generated components work in Server Components, SSR, and SSG without the `'use client'` directive. +- **Formats for different use cases** - React and Next.js use `stack`; legacy mode also supports `symbol` for existing integrations. -## Π’Π°Π±Π»ΠΈΡ†Π° ΠΏΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΊΠΈ +## Support matrix -| Π‘Ρ€Π΅Π΄Π° | ΠšΠ»ΡŽΡ‡ ΠΌΠΎΠ΄Π° API | Бтатус | +| Environment | API mode key | Status | |---|---|---| -| React + Vite | `react@vite` | Π“ΠΎΡ‚ΠΎΠ²ΠΎ | -| React + Webpack 5 | `react@webpack` | Π“ΠΎΡ‚ΠΎΠ²ΠΎ | -| Next.js 16.2+ App Router + Turbopack | `next@app/turbopack` | Π“ΠΎΡ‚ΠΎΠ²ΠΎ | -| Next.js 13.4+ App Router + Webpack 5 | `next@app/webpack` | Π“ΠΎΡ‚ΠΎΠ²ΠΎ | -| Next.js 16.2+ Pages Router + Turbopack | `next@pages/turbopack` | Π“ΠΎΡ‚ΠΎΠ²ΠΎ | -| Next.js 12.2+ Pages Router + Webpack 5 | `next@pages/webpack` | Π“ΠΎΡ‚ΠΎΠ²ΠΎ | -| Vue | β€” | Π‘ΠΊΠΎΡ€ΠΎ | -| Standalone | β€” | Π‘ΠΊΠΎΡ€ΠΎ | +| React + Vite | `react@vite` | Ready | +| React + Webpack 5 | `react@webpack` | Ready | +| Next.js 16.2+ App Router + Turbopack | `next@app/turbopack` | Ready | +| Next.js 13.4+ App Router + Webpack 5 | `next@app/webpack` | Ready | +| Next.js 16.2+ Pages Router + Turbopack | `next@pages/turbopack` | Ready | +| Next.js 12.2+ Pages Router + Webpack 5 | `next@pages/webpack` | Ready | +| Vue | - | Coming soon | +| Standalone | - | Coming soon | -## ВрСбования +## Requirements -- Node.js 18 ΠΈΠ»ΠΈ Π½ΠΎΠ²Π΅Π΅; -- ΠΏΠ°ΠΊΠ΅Ρ‚ распространяСтся Ρ‚ΠΎΠ»ΡŒΠΊΠΎ ΠΊΠ°ΠΊ ESM ΠΈ ΠΏΠΎΠ΄ΠΊΠ»ΡŽΡ‡Π°Π΅Ρ‚ΡΡ Ρ‡Π΅Ρ€Π΅Π· `import`; -- React 18 ΠΈΠ»ΠΈ 19 трСбуСтся Ρ‚ΠΎΠ»ΡŒΠΊΠΎ для generated-ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚ΠΎΠ² ΠΈ Ρ‚ΠΎΡ‡ΠΊΠΈ Π²Ρ…ΠΎΠ΄Π° `@gromlab/svg-sprites/react`; -- для Ρ‚ΠΈΠΏΠΈΠ·Π°Ρ†ΠΈΠΈ subpath exports ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠΉΡ‚Π΅ TypeScript 5+ с `moduleResolution: "bundler"`, `"node16"` ΠΈΠ»ΠΈ `"nodenext"`. +- Node.js 18 or newer; +- the package is distributed as ESM only and is loaded via `import`; +- React 18 or 19 is required only for generated components and the `@gromlab/svg-sprites/react` entry point; +- for subpath export typings, use TypeScript 5+ with `moduleResolution: "bundler"`, `"node16"`, or `"nodenext"`. -## Быстрый старт +## Quick start -Для быстрого старта Π²ΠΎΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠΉΡ‚Π΅ΡΡŒ инструкциСй для вашСго стСка: +For a quick start, follow the guide for your stack: -- [React + Vite](docs/ru/react-vite.md) -- [React + Webpack 5](docs/ru/react-webpack.md) -- [Next.js App Router](docs/ru/next-app.md) -- [Next.js Pages Router](docs/ru/next-pages.md) +- [React + Vite](docs/en/react-vite.md) +- [React + Webpack 5](docs/en/react-webpack.md) +- [Next.js App Router](docs/en/next-app.md) +- [Next.js Pages Router](docs/en/next-pages.md) -## ΠšΠΎΠ½Ρ„ΠΈΠ³ΡƒΡ€Π°Ρ†ΠΈΡ +## Configuration ### React @@ -80,7 +83,7 @@ import { defineReactSpriteConfig } from '@gromlab/svg-sprites' export default defineReactSpriteConfig({ name: 'file-manager', - description: 'Иконки Ρ„Π°ΠΉΠ»ΠΎΠ²ΠΎΠ³ΠΎ ΠΌΠ΅Π½Π΅Π΄ΠΆΠ΅Ρ€Π°', + description: 'File manager icons', inputFolder: './icons', inputFiles: [ '../../shared/icons/check.svg', @@ -94,78 +97,78 @@ export default defineReactSpriteConfig({ }) ``` -| ΠžΠΏΡ†ΠΈΡ | Π’ΠΈΠΏ | По ΡƒΠΌΠΎΠ»Ρ‡Π°Π½ΠΈΡŽ | НазначСниС | +| Option | Type | Default | Purpose | |---|---|---|---| -| `name` | `string` | Имя ΠΏΠ°ΠΏΠΊΠΈ | Имя спрайта, ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Π° ΠΈ ΠΏΡƒΠ±Π»ΠΈΡ‡Π½Ρ‹Ρ… Ρ‚ΠΈΠΏΠΎΠ² | -| `description` | `string` | НСт | ОписаниС для Ρ‚ΠΈΠΏΠΎΠ² ΠΈ debug-манифСста | -| `inputFolder` | `string` | `./icons` | Папка с исходными SVG ΠΎΡ‚Π½ΠΎΡΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎ ΠΊΠΎΠ½Ρ„ΠΈΠ³Π° | -| `inputFiles` | `string[]` | `[]` | Π”ΠΎΠΏΠΎΠ»Π½ΠΈΡ‚Π΅Π»ΡŒΠ½Ρ‹Π΅ SVG-Ρ„Π°ΠΉΠ»Ρ‹ ΠΎΡ‚Π½ΠΎΡΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎ ΠΊΠΎΠ½Ρ„ΠΈΠ³Π° | -| `transform` | `TransformOptions` | ВсС Π²ΠΊΠ»ΡŽΡ‡Π΅Π½Ρ‹ | [Настройки трансформации](#трансформации) исходных SVG | -| `generatedNotice` | `boolean` | `true` | ПолноС Π»ΠΈΠ±ΠΎ ΠΊΠΎΡ€ΠΎΡ‚ΠΊΠΎΠ΅ ΠΏΡ€Π΅Π΄ΡƒΠΏΡ€Π΅ΠΆΠ΄Π΅Π½ΠΈΠ΅ Π² generated-Ρ„Π°ΠΉΠ»Π°Ρ… | +| `name` | `string` | Folder name | Name of the sprite, component, and public types | +| `description` | `string` | None | Description for types and the debug manifest | +| `inputFolder` | `string` | `./icons` | Folder containing source SVGs, relative to the config | +| `inputFiles` | `string[]` | `[]` | Additional SVG files, relative to the config | +| `transform` | `TransformOptions` | All enabled | [Transformation settings](#transformations) for source SVGs | +| `generatedNotice` | `boolean` | `true` | Full or short warning in generated files | -`inputFolder` ΠΈ `inputFiles` ΠΎΠ±ΡŠΠ΅Π΄ΠΈΠ½ΡΡŽΡ‚ΡΡ Π² ΠΎΠ΄ΠΈΠ½ спрайт, поэтому ΠΎΠ΄ΠΈΠ½ SVG-Ρ„Π°ΠΉΠ» ΠΌΠΎΠΆΠ½ΠΎ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ Π² Π½Π΅ΡΠΊΠΎΠ»ΡŒΠΊΠΈΡ… спрайтах Π±Π΅Π· копирования. Если нСявной ΠΏΠ°ΠΏΠΊΠΈ `./icons` Π½Π΅Ρ‚, Π½ΠΎ `inputFiles` Π·Π°ΠΏΠΎΠ»Π½Π΅Π½, гСнСрация продолТаСтся Ρ‚ΠΎΠ»ΡŒΠΊΠΎ ΠΏΠΎ списку. Π―Π²Π½ΠΎ указанная ΠΎΡ‚ΡΡƒΡ‚ΡΡ‚Π²ΡƒΡŽΡ‰Π°Ρ ΠΏΠ°ΠΏΠΊΠ° считаСтся ошибкой. ΠžΠ΄ΠΈΠ½Π°ΠΊΠΎΠ²Ρ‹Π΅ ΠΏΡƒΡ‚ΠΈ Π΄Π΅Π΄ΡƒΠΏΠ»ΠΈΡ†ΠΈΡ€ΡƒΡŽΡ‚ΡΡ, Π° Ρ€Π°Π·Π½Ρ‹Π΅ Ρ„Π°ΠΉΠ»Ρ‹ с ΠΎΠ΄ΠΈΠ½Π°ΠΊΠΎΠ²Ρ‹ΠΌ ΠΈΠΌΠ΅Π½Π΅ΠΌ ΠΈΠΊΠΎΠ½ΠΊΠΈ ΡΡ‡ΠΈΡ‚Π°ΡŽΡ‚ΡΡ ошибкой. +`inputFolder` and `inputFiles` are merged into a single sprite, so one SVG file can be used in multiple sprites without copying. If the implicit `./icons` folder does not exist but `inputFiles` is populated, generation continues using only the list. An explicitly specified missing folder is an error. Duplicate paths are deduplicated, while different files with the same icon name are treated as an error. -`name` записываСтся Π² kebab-case ΠΈ Π΄ΠΎΠ»ΠΆΠ½ΠΎ Π½Π°Ρ‡ΠΈΠ½Π°Ρ‚ΡŒΡΡ с латинской Π±ΡƒΠΊΠ²Ρ‹. React ΠΈ Next.js presets ΡΠΎΠ·Π΄Π°ΡŽΡ‚ Ρ„ΠΎΡ€ΠΌΠ°Ρ‚ `stack`. +`name` is stored in kebab-case and must start with a Latin letter. The React and Next.js presets produce the `stack` format. ### Next.js -Next.js ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ Ρ‚ΠΎΡ‚ ΠΆΠ΅ `svg-sprite.config.ts` ΠΈ Π½Π°Π±ΠΎΡ€ ΠΎΠΏΡ†ΠΈΠΉ. Для Ρ‚ΠΈΠΏΠΈΠ·Π°Ρ†ΠΈΠΈ ΠΌΠΎΠΆΠ½ΠΎ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ ΠΎΡ‚Π΄Π΅Π»ΡŒΠ½Ρ‹ΠΉ Ρ…Π΅Π»ΠΏΠ΅Ρ€: +Next.js uses the same `svg-sprite.config.ts` and set of options. For type checking, you can use a dedicated helper: ```ts import { defineNextSpriteConfig } from '@gromlab/svg-sprites' export default defineNextSpriteConfig({ name: 'file-manager', - description: 'Иконки Ρ„Π°ΠΉΠ»ΠΎΠ²ΠΎΠ³ΠΎ ΠΌΠ΅Π½Π΅Π΄ΠΆΠ΅Ρ€Π°', + description: 'File manager icons', inputFolder: './icons', }) ``` -Π ΠΎΡƒΡ‚Π΅Ρ€ ΠΈ сборщик Π²Ρ‹Π±ΠΈΡ€Π°ΡŽΡ‚ΡΡ Ρ‡Π΅Ρ€Π΅Π· mode key, поэтому ΠΏΠ΅Ρ€Π΅ΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅ ΠΌΠ΅ΠΆΠ΄Ρƒ Turbopack ΠΈ Webpack всСгда явно ΠΎΡ‚Ρ€Π°ΠΆΠ΅Π½ΠΎ Π² ΠΊΠΎΠΌΠ°Π½Π΄Π΅ Π³Π΅Π½Π΅Ρ€Π°Ρ†ΠΈΠΈ. +The router and bundler are selected through the mode key, so switching between Turbopack and Webpack is always explicitly reflected in the generation command. -## ΠœΠ½ΠΎΠΆΠ΅ΡΡ‚Π²Π΅Π½Π½Ρ‹Π΅ спрайты +## Multiple sprites -ΠŸΡ€ΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅ ΠΌΠΎΠΆΠ΅Ρ‚ ΡΠΎΠ΄Π΅Ρ€ΠΆΠ°Ρ‚ΡŒ нСсколько нСзависимых спрайтов с Ρ€Π°Π·Π½ΠΎΠΉ ΠΎΠ±Π»Π°ΡΡ‚ΡŒΡŽ использования: +An application can contain several independent sprites for different scopes: -**ΠŸΡ€ΠΎΠ±Π»Π΅ΠΌΠ°:** ΠΎΠ΄ΠΈΠ½ Π³Π»ΠΎΠ±Π°Π»ΡŒΠ½Ρ‹ΠΉ спрайт Π·Π°Π³Ρ€ΡƒΠΆΠ°Π΅Ρ‚ ΠΈΠΊΠΎΠ½ΠΊΠΈ, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ Ρ‚Π΅ΠΊΡƒΡ‰Π΅ΠΌΡƒ экрану Π½Π΅ Π½ΡƒΠΆΠ½Ρ‹. +**Problem:** one global sprite loads icons that the current screen does not need. -**РСшСниС:** ΠΎΠ±Ρ‰ΠΈΠ΅ ΠΈΠΊΠΎΠ½ΠΊΠΈ Ρ…Ρ€Π°Π½ΠΈΡ‚ΡŒ глобально, Π° Π½Π°Π±ΠΎΡ€Ρ‹ страниц ΠΈ ΠΊΡ€ΡƒΠΏΠ½Ρ‹Ρ… ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚ΠΎΠ² β€” Π² ΠΎΡ‚Π΄Π΅Π»ΡŒΠ½Ρ‹Ρ… спрайтах, Π·Π°Π³Ρ€ΡƒΠΆΠ°Π΅ΠΌΡ‹Ρ… вмСстС с Π½ΠΈΠΌΠΈ. +**Solution:** keep shared icons globally, and place icon sets for pages and large components in separate sprites that load alongside them. ```text -global β†’ GlobalIcon β†’ ΠΎΠ±Ρ‰ΠΈΠ΅ ΠΈΠΊΠΎΠ½ΠΊΠΈ прилоТСния -analytics-page β†’ AnalyticsPageIcon β†’ ΠΈΠΊΠΎΠ½ΠΊΠΈ ΠΎΡ‚Π΄Π΅Π»ΡŒΠ½ΠΎΠΉ страницы -file-manager β†’ FileManagerIcon β†’ ΠΈΠΊΠΎΠ½ΠΊΠΈ ΠΊΡ€ΡƒΠΏΠ½ΠΎΠ³ΠΎ ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Π° +global -> GlobalIcon -> shared application icons +analytics-page -> AnalyticsPageIcon -> icons for a specific page +file-manager -> FileManagerIcon -> icons for a large component ``` -- **Π“Π»ΠΎΠ±Π°Π»ΡŒΠ½Ρ‹ΠΉ спрайт** содСрТит нСбольшиС ΠΎΠ±Ρ‰ΠΈΠ΅ ΠΈΠΊΠΎΠ½ΠΊΠΈ, ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅ΠΌΡ‹Π΅ Π² Ρ€Π°Π·Π½Ρ‹Ρ… частях прилоТСния: Π½Π°Π²ΠΈΠ³Π°Ρ†ΠΈΡŽ, состояния ΠΈ Π±Π°Π·ΠΎΠ²Ρ‹Π΅ дСйствия. -- **Π‘ΠΏΡ€Π°ΠΉΡ‚ страницы** загруТаСтся вмСстС с ΠΊΠΎΠ½ΠΊΡ€Π΅Ρ‚Π½Ρ‹ΠΌ Ρ€Π°Π·Π΄Π΅Π»ΠΎΠΌ ΠΈ Π½Π΅ ΡƒΠ²Π΅Π»ΠΈΡ‡ΠΈΠ²Π°Π΅Ρ‚ ΠΎΠ±Ρ‰ΠΈΠΉ спрайт ΠΈΠΊΠΎΠ½ΠΊΠ°ΠΌΠΈ, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ большС Π½ΠΈΠ³Π΄Π΅ Π½Π΅ Π½ΡƒΠΆΠ½Ρ‹. -- **Π‘ΠΏΡ€Π°ΠΉΡ‚ ΠΊΡ€ΡƒΠΏΠ½ΠΎΠ³ΠΎ ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Π°** инкапсулируСт собствСнный Π½Π°Π±ΠΎΡ€ ΠΈΠΊΠΎΠ½ΠΎΠΊ слоТного UI-модуля, Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€ Ρ„Π°ΠΉΠ»ΠΎΠ²ΠΎΠ³ΠΎ ΠΌΠ΅Π½Π΅Π΄ΠΆΠ΅Ρ€Π° ΠΈΠ»ΠΈ Ρ€Π΅Π΄Π°ΠΊΡ‚ΠΎΡ€Π°. +- **Global sprite** contains a small set of shared icons used in different parts of the application: navigation, states, and basic actions. +- **Page sprite** loads with a specific section and does not increase the shared sprite with icons that are not needed anywhere else. +- **Large component sprite** encapsulates the icon set of a complex UI module, such as a file manager or editor. -КаТдая Π³Ρ€ΡƒΠΏΠΏΠ° ΠΏΠΎΠ»ΡƒΡ‡Π°Π΅Ρ‚: +Each group gets: -- собствСнный SVG asset; -- собствСнный Ρ‚ΠΈΠΏΠΈΠ·ΠΈΡ€ΠΎΠ²Π°Π½Π½Ρ‹ΠΉ ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚; -- ΠΎΡ‚Π΄Π΅Π»ΡŒΠ½Ρ‹ΠΉ список ΠΈΠΌΡ‘Π½ ΠΈΠΊΠΎΠ½ΠΎΠΊ; -- ΠΎΡ‚Π΄Π΅Π»ΡŒΠ½Ρ‹ΠΉ debug-манифСст; -- нСзависимый cache lifecycle. +- its own SVG asset; +- its own typed component; +- a separate list of icon names; +- a separate debug manifest; +- an independent cache lifecycle. ## TypeScript -Главная Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎΡΡ‚ΡŒ TypeScript API β€” Π°Π²Ρ‚ΠΎΠ΄ΠΎΠΏΠΎΠ»Π½Π΅Π½ΠΈΠ΅ ΠΈΠΌΡ‘Π½ ΠΈΠΊΠΎΠ½ΠΎΠΊ нСпосрСдствСнно Π² prop `icon`: +The main feature of the TypeScript API is icon name autocomplete directly in the `icon` prop: ```tsx -// ↑ Ρ€Π΅Π΄Π°ΠΊΡ‚ΠΎΡ€ ΠΏΡ€Π΅Π΄Π»Π°Π³Π°Π΅Ρ‚ всС ΠΈΠΊΠΎΠ½ΠΊΠΈ спрайта +// ^ the editor suggests every icon in the sprite ``` -ИмСна SVG-Ρ„Π°ΠΉΠ»ΠΎΠ² становятся допустимыми значСниями `icon`. ΠžΠΏΠ΅Ρ‡Π°Ρ‚ΠΊΠ° ΠΈΠ»ΠΈ нСизвСстноС имя сразу становятся ошибкой TypeScript: +SVG file names become valid `icon` values. A typo or unknown name immediately becomes a TypeScript error: ```tsx - // ошибка TypeScript + // TypeScript error ``` -Для ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠ½ΠΎΠ³ΠΎ доступа generated-ΠΌΠΎΠ΄ΡƒΠ»ΡŒ экспортируСт readonly-массив всСх доступных ΠΈΠΊΠΎΠ½ΠΎΠΊ ΠΊΠΎΠ½ΠΊΡ€Π΅Ρ‚Π½ΠΎΠ³ΠΎ спрайта: +For programmatic access, the generated module exports a readonly array of all icons available in a specific sprite: ```ts import { fileManagerIconNames } from './svg-sprite' @@ -173,39 +176,39 @@ import { fileManagerIconNames } from './svg-sprite' // readonly ['check', 'folder', ...] ``` -Π­Ρ‚ΠΎΡ‚ список ΠΌΠΎΠΆΠ½ΠΎ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ Π² собствСнных ΠΊΠ°Ρ‚Π°Π»ΠΎΠ³Π°Ρ…, select-ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Π°Ρ…, тСстах ΠΈ Π΄Ρ€ΡƒΠ³ΠΈΡ… runtime-сцСнариях. Из Π½Π΅Π³ΠΎ Ρ‚Π°ΠΊΠΆΠ΅ выводится union-Ρ‚ΠΈΠΏ `FileManagerIconName`. +You can use this list in custom catalogs, select components, tests, and other runtime scenarios. The `FileManagerIconName` union type is also derived from it. -ИмСна Ρ„Π°ΠΉΠ»ΠΎΠ² с ΠΏΡ€ΠΎΠ±Π΅Π»Π°ΠΌΠΈ ΠΈ Π΄Ρ€ΡƒΠ³ΠΈΠΌΠΈ нСбСзопасными для SVG ID символами ΠΎΡΡ‚Π°ΡŽΡ‚ΡΡ Ρ‡Π°ΡΡ‚ΡŒΡŽ ΠΏΡƒΠ±Π»ΠΈΡ‡Π½ΠΎΠ³ΠΎ TypeScript API. Для Π²Π½ΡƒΡ‚Ρ€Π΅Π½Π½Π΅Π³ΠΎ `` Π³Π΅Π½Π΅Ρ€Π°Ρ‚ΠΎΡ€ создаёт ΡΡ‚Π°Π±ΠΈΠ»ΡŒΠ½Ρ‹ΠΉ hash ID. +File names containing spaces and other characters unsafe for SVG IDs remain part of the public TypeScript API. For the internal ``, the generator creates a stable hash ID. ```text -folder open.svg β†’ icon="folder open" β†’ id="icon-" +folder open.svg -> icon="folder open" -> id="icon-" ``` -Для Ρ‚Π°ΠΊΠΈΡ… ΠΈΠΌΡ‘Π½ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠΉΡ‚Π΅ generated-ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚ ΠΈΠ»ΠΈ `id` ΠΈΠ· debug-манифСста. Π ΡƒΡ‡Π½Ρ‹Π΅ ΠΏΡ€ΠΈΠΌΠ΅Ρ€Ρ‹ Π½ΠΈΠΆΠ΅ с `#<имя>` подходят Ρ‚ΠΎΠ»ΡŒΠΊΠΎ для ΠΈΠΌΡ‘Π½, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ ΡƒΠΆΠ΅ ΡΠ²Π»ΡΡŽΡ‚ΡΡ бСзопасными SVG ID. +For such names, use the generated component or the `id` from the debug manifest. The manual examples below using `#` are suitable only for names that are already safe SVG IDs. -## Π€ΠΎΡ€ΠΌΠ°Ρ‚Ρ‹ спрайтов +## Sprite formats -`stack` β€” Π±ΠΎΠ»Π΅Π΅ соврСмСнный Ρ„ΠΎΡ€ΠΌΠ°Ρ‚, поэтому ΠΎΠ½ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ΡΡ ΠΏΠΎ ΡƒΠΌΠΎΠ»Ρ‡Π°Π½ΠΈΡŽ. Иконки ΠΌΠΎΠΆΠ½ΠΎ ΠΎΡ‚ΠΎΠ±Ρ€Π°ΠΆΠ°Ρ‚ΡŒ Ρ‡Π΅Ρ€Π΅Π· ``, `` ΠΈ CSS `background-image`. +`stack` is the more modern format, so it is used by default. Icons can be rendered through ``, ``, and CSS `background-image`. -`symbol` сохраняСтся для совмСстимости с ΡΡƒΡ‰Π΅ΡΡ‚Π²ΡƒΡŽΡ‰ΠΈΠΌΠΈ интСграциями ΠΈ ΠΏΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΈΠ²Π°Π΅Ρ‚ ΠΎΡ‚ΠΎΠ±Ρ€Π°ΠΆΠ΅Π½ΠΈΠ΅ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ Ρ‡Π΅Ρ€Π΅Π· ``. +`symbol` is retained for compatibility with existing integrations and supports rendering only through ``. -## Бпособы отобраТСния +## Rendering methods -### React-ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚ β€” рСкомСндуСтся +### React component - recommended -Generated-ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚ прСдоставляСт Ρ‚ΠΈΠΏΠΈΠ·Π°Ρ†ΠΈΡŽ, Π°Π²Ρ‚ΠΎΠ΄ΠΎΠΏΠΎΠ»Π½Π΅Π½ΠΈΠ΅ ΠΈΠΌΡ‘Π½ ΠΈΠΊΠΎΠ½ΠΎΠΊ ΠΈ сам Ρ„ΠΎΡ€ΠΌΠΈΡ€ΡƒΠ΅Ρ‚ URL SVG asset. +The generated component provides type safety and icon name autocomplete, and constructs the SVG asset URL itself. ```tsx ``` -Π§Π΅Ρ€Π΅Π· `color` ΠΈ `--icon-color-N` доступны ΠΎΠ΄Π½ΠΎΡ†Π²Π΅Ρ‚Π½Ρ‹Π΅ ΠΈ ΠΌΠ½ΠΎΠ³ΠΎΡ†Π²Π΅Ρ‚Π½Ρ‹Π΅ ΠΈΠΊΠΎΠ½ΠΊΠΈ. +Monochrome and multicolor icons are supported through `color` and `--icon-color-N`. -### Π‘Π°ΠΌΠΎΡΡ‚ΠΎΡΡ‚Π΅Π»ΡŒΠ½ΠΎ Ρ‡Π΅Ρ€Π΅Π· `` +### Manually with `` -Π₯ΠΎΡ€ΠΎΡˆΠΈΠΉ Π½ΠΈΠ·ΠΊΠΎΡƒΡ€ΠΎΠ²Π½Π΅Π²Ρ‹ΠΉ способ с ΠΏΠΎΠ»Π½Ρ‹ΠΌ ΡƒΠΏΡ€Π°Π²Π»Π΅Π½ΠΈΠ΅ΠΌ Ρ€Π°Π·ΠΌΠ΅Ρ€Π°ΠΌΠΈ ΠΈ Ρ†Π²Π΅Ρ‚Π°ΠΌΠΈ. React-ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚ ΠΏΠΎΠ΄ ΠΊΠ°ΠΏΠΎΡ‚ΠΎΠΌ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ ΠΈΠΌΠ΅Π½Π½ΠΎ Π΅Π³ΠΎ. +A good low-level method that provides full control over dimensions and colors. This is exactly what the React component uses under the hood. -Бпособ получСния `spriteUrl` зависит ΠΎΡ‚ сборщика. +How you obtain `spriteUrl` depends on the bundler. **Vite:** @@ -222,7 +225,7 @@ const spriteUrl = new URL( ).href ``` -**Next.js с Webpack 5 ΠΈΠ»ΠΈ Turbopack:** +**Next.js with Webpack 5 or Turbopack:** ```tsx const spriteUrl = new URL( @@ -231,7 +234,7 @@ const spriteUrl = new URL( ).href ``` -ПослС получСния URL ΠΈΠΊΠΎΠ½ΠΊΠ° отобраТаСтся ΠΎΠ΄ΠΈΠ½Π°ΠΊΠΎΠ²ΠΎ: +After obtaining the URL, the icon is rendered the same way: ```tsx @@ -239,17 +242,17 @@ const spriteUrl = new URL( ``` -Vite, Webpack 5 ΠΈ Next.js сами Π·Π°ΠΌΠ΅Π½ΡΡŽΡ‚ исходный ΠΏΡƒΡ‚ΡŒ Π½Π° ΠΈΡ‚ΠΎΠ³ΠΎΠ²Ρ‹ΠΉ URL asset с hash. +Vite, Webpack 5, and Next.js replace the source path with the final hashed asset URL automatically. -### Π§Π΅Ρ€Π΅Π· `` β€” ΠΌΠ΅Π½Π΅Π΅ эффСктивно +### With `` - less efficient ```tsx -Π“ΠΎΡ‚ΠΎΠ²ΠΎ +Done ``` -SVG загруТаСтся ΠΊΠ°ΠΊ ΠΈΠ·ΠΎΠ»ΠΈΡ€ΠΎΠ²Π°Π½Π½ΠΎΠ΅ ΠΈΠ·ΠΎΠ±Ρ€Π°ΠΆΠ΅Π½ΠΈΠ΅: ΠΈΠ·ΠΌΠ΅Π½ΠΈΡ‚ΡŒ Π΅Π³ΠΎ Ρ†Π²Π΅Ρ‚Π° Ρ‡Π΅Ρ€Π΅Π· `color` ΠΈΠ»ΠΈ `--icon-color-N` нСльзя. +The SVG loads as an isolated image: its colors cannot be changed through `color` or `--icon-color-N`. -### Π§Π΅Ρ€Π΅Π· CSS `background-image` β€” ΠΌΠ΅Π½Π΅Π΅ эффСктивно +### With CSS `background-image` - less efficient ```css .icon { @@ -257,9 +260,9 @@ SVG загруТаСтся ΠΊΠ°ΠΊ ΠΈΠ·ΠΎΠ»ΠΈΡ€ΠΎΠ²Π°Π½Π½ΠΎΠ΅ ΠΈΠ·ΠΎΠ±Ρ€Π°ΠΆΠ΅Π½ } ``` -Как ΠΈ ``, этот способ Π½Π΅ позволяСт ΡƒΠΏΡ€Π°Π²Π»ΡΡ‚ΡŒ Π²Π½ΡƒΡ‚Ρ€Π΅Π½Π½ΠΈΠΌΠΈ Ρ†Π²Π΅Ρ‚Π°ΠΌΠΈ SVG. ΠŸΡƒΡ‚ΡŒ указываСтся ΠΎΡ‚Π½ΠΎΡΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎ CSS-Ρ„Π°ΠΉΠ»Π°, Π° Vite/Webpack замСняСт Π΅Π³ΠΎ Π½Π° ΠΈΡ‚ΠΎΠ³ΠΎΠ²Ρ‹ΠΉ URL с hash ΠΏΡ€ΠΈ сборкС. +Like ``, this method does not allow you to control internal SVG colors. The path is specified relative to the CSS file, and Vite/Webpack replaces it with the final hashed URL during the build. -### Π§Π΅Ρ€Π΅Π· CSS mask β€” ΠΌΠ΅Π½Π΅Π΅ эффСктивно +### With CSS mask - less efficient ```css .icon { @@ -268,37 +271,37 @@ SVG загруТаСтся ΠΊΠ°ΠΊ ΠΈΠ·ΠΎΠ»ΠΈΡ€ΠΎΠ²Π°Π½Π½ΠΎΠ΅ ΠΈΠ·ΠΎΠ±Ρ€Π°ΠΆΠ΅Π½ } ``` -Mask оставляСт Ρ‚ΠΎΠ»ΡŒΠΊΠΎ силуэт ΠΈ ΠΎΠΊΡ€Π°ΡˆΠΈΠ²Π°Π΅Ρ‚ Π΅Π³ΠΎ ΠΎΠ΄Π½ΠΈΠΌ Ρ†Π²Π΅Ρ‚ΠΎΠΌ. Π˜ΡΡ…ΠΎΠ΄Π½Ρ‹Π΅ Ρ†Π²Π΅Ρ‚Π°, gradients ΠΈ различия ΠΌΠ΅ΠΆΠ΄Ρƒ `fill` ΠΈ `stroke` Ρ‚Π΅Ρ€ΡΡŽΡ‚ΡΡ. +A mask retains only the silhouette and colors it with a single color. The original colors, gradients, and distinctions between `fill` and `stroke` are lost. -## Врансформации +## Transformations -ВсС трансформации Π²ΠΊΠ»ΡŽΡ‡Π΅Π½Ρ‹ ΠΏΠΎ ΡƒΠΌΠΎΠ»Ρ‡Π°Π½ΠΈΡŽ ΠΈ Π½Π°ΡΡ‚Ρ€Π°ΠΈΠ²Π°ΡŽΡ‚ΡΡ нСзависимо Ρ‡Π΅Ρ€Π΅Π· `transform`. +All transformations are enabled by default and configured independently through `transform`. -| ΠžΠΏΡ†ΠΈΡ | По ΡƒΠΌΠΎΠ»Ρ‡Π°Π½ΠΈΡŽ | Π§Ρ‚ΠΎ Π΄Π΅Π»Π°Π΅Ρ‚ | +| Option | Default | What it does | |---|---|---| -| `removeSize` | `true` | УдаляСт `width` ΠΈ `height` с ΠΊΠΎΡ€Π½Π΅Π²ΠΎΠ³ΠΎ ``, сохраняя ΡΡƒΡ‰Π΅ΡΡ‚Π²ΡƒΡŽΡ‰ΠΈΠΉ `viewBox`. Π Π°Π·ΠΌΠ΅Ρ€ ΠΈΠΊΠΎΠ½ΠΊΠΈ послС этого задаётся снаруТи. | -| `replaceColors` | `true` | ЗамСняСт Ρ†Π²Π΅Ρ‚Π° `fill` ΠΈ `stroke` Π½Π° `--icon-color-N`. Для ΠΎΠ΄Π½ΠΎΡ†Π²Π΅Ρ‚Π½ΠΎΠΉ ΠΈΠΊΠΎΠ½ΠΊΠΈ fallback становится `currentColor`, для ΠΌΠ½ΠΎΠ³ΠΎΡ†Π²Π΅Ρ‚Π½ΠΎΠΉ ΡΠΎΡ…Ρ€Π°Π½ΡΡŽΡ‚ΡΡ исходныС Ρ†Π²Π΅Ρ‚Π°. | -| `addTransition` | `true` | ДобавляСт `style="transition:fill 0.3s,stroke 0.3s;"` нСпосрСдствСнно Ρ†Π²Π΅Ρ‚Π½Ρ‹ΠΌ элСмСнтам SVG. Π‘ΡƒΡ‰Π΅ΡΡ‚Π²ΡƒΡŽΡ‰ΠΈΠΉ `transition` Π½Π΅ пСрСзаписываСтся. | +| `removeSize` | `true` | Removes `width` and `height` from the root `` while preserving the existing `viewBox`. The icon size is then set externally. | +| `replaceColors` | `true` | Replaces `fill` and `stroke` colors with `--icon-color-N`. For a monochrome icon, the fallback becomes `currentColor`; for a multicolor icon, the original colors are preserved. | +| `addTransition` | `true` | Adds `style="transition:fill 0.3s,stroke 0.3s;"` directly to colored SVG elements. An existing `transition` is not overwritten. | -Π§Ρ‚ΠΎΠ±Ρ‹ ΠΎΡ‚ΠΊΠ»ΡŽΡ‡ΠΈΡ‚ΡŒ ΠΏΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΠΎΠ²Π°Π½ΠΈΠ΅, ΠΏΠ΅Ρ€Π΅Π΄Π°ΠΉΡ‚Π΅ для ΡΠΎΠΎΡ‚Π²Π΅Ρ‚ΡΡ‚Π²ΡƒΡŽΡ‰Π΅ΠΉ ΠΎΠΏΡ†ΠΈΠΈ `false`. ΠŸΠΎΠ΄Ρ€ΠΎΠ±Π½Π΅Π΅ ΠΎ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Π΅ `replaceColors` β€” Π² Ρ€Π°Π·Π΄Π΅Π»Π΅ [Β«Π£ΠΏΡ€Π°Π²Π»Π΅Π½ΠΈΠ΅ Ρ†Π²Π΅Ρ‚ΠΎΠΌ ΠΈΠΊΠΎΠ½ΠΎΠΊΒ»](#ΡƒΠΏΡ€Π°Π²Π»Π΅Π½ΠΈΠ΅-Ρ†Π²Π΅Ρ‚ΠΎΠΌ-ΠΈΠΊΠΎΠ½ΠΎΠΊ). +To disable a transformation, pass `false` for the corresponding option. For more details about the result of `replaceColors`, see [Icon color management](#icon-color-management). -## Π£ΠΏΡ€Π°Π²Π»Π΅Π½ΠΈΠ΅ Ρ†Π²Π΅Ρ‚ΠΎΠΌ ΠΈΠΊΠΎΠ½ΠΎΠΊ +## Icon color management -ΠŸΡ€ΠΈ Π²ΠΊΠ»ΡŽΡ‡Ρ‘Π½Π½ΠΎΠΉ Π·Π°ΠΌΠ΅Π½Π΅ Ρ†Π²Π΅Ρ‚ΠΎΠ² Π³Π΅Π½Π΅Ρ€Π°Ρ‚ΠΎΡ€ Π°Π½Π°Π»ΠΈΠ·ΠΈΡ€ΡƒΠ΅Ρ‚ `fill` ΠΈ `stroke` ΠΈ ΠΏΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΡƒΠ΅Ρ‚ ΠΈΡ… Π² CSS custom properties. +When color replacement is enabled, the generator analyzes `fill` and `stroke` and converts them to CSS custom properties. -### ΠœΠΎΠ½ΠΎΡ…Ρ€ΠΎΠΌΠ½Ρ‹Π΅ ΠΈΠΊΠΎΠ½ΠΊΠΈ +### Monochrome icons -Если Π½Π°ΠΉΠ΄Π΅Π½ ΠΎΠ΄ΠΈΠ½ Ρ†Π²Π΅Ρ‚, fallback замСняСтся Π½Π° `currentColor`: +If one color is found, the fallback is replaced with `currentColor`: ```svg stroke="var(--icon-color-1, currentColor)" ``` -Π¦Π²Π΅Ρ‚ΠΎΠΌ управляСт CSS-свойство `color` внСшнСго `` ΠΈΠ»ΠΈ Π΅Π³ΠΎ родитСля. +The color is controlled by the CSS `color` property of the outer `` or its parent. -### ΠœΠ½ΠΎΠ³ΠΎΡ†Π²Π΅Ρ‚Π½Ρ‹Π΅ ΠΈΠΊΠΎΠ½ΠΊΠΈ +### Multicolor icons -ΠšΠ°ΠΆΠ΄Ρ‹ΠΉ ΡƒΠ½ΠΈΠΊΠ°Π»ΡŒΠ½Ρ‹ΠΉ Ρ†Π²Π΅Ρ‚ ΠΏΠΎΠ»ΡƒΡ‡Π°Π΅Ρ‚ ΠΎΡ‚Π΄Π΅Π»ΡŒΠ½ΡƒΡŽ ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½ΡƒΡŽ с исходным fallback: +Each unique color gets a separate variable with the original fallback: ```svg fill="var(--icon-color-1, #798198)" @@ -306,7 +309,7 @@ fill="var(--icon-color-2, #ffffff)" fill="var(--icon-color-3, #129d9d)" ``` -Π‘Ρ‚Ρ€Π°Π½ΠΈΡ†Π° ΠΌΠΎΠΆΠ΅Ρ‚ Π·Π°ΠΌΠ΅Π½ΠΈΡ‚ΡŒ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΡ‹Π΅ Ρ†Π²Π΅Ρ‚Π°: +The page can override only the required colors: ```css .icon { @@ -315,62 +318,62 @@ fill="var(--icon-color-3, #129d9d)" } ``` -### ΠžΠ³Ρ€Π°Π½ΠΈΡ‡Π΅Π½ΠΈΡ Ρ†Π²Π΅Ρ‚ΠΎΠ² +### Color limitations -- `none`, `transparent`, `inherit`, `unset` ΠΈ `initial` Π½Π΅ Π·Π°ΠΌΠ΅Π½ΡΡŽΡ‚ΡΡ; -- Ρ†Π²Π΅Ρ‚Π° Π² Π°Ρ‚Ρ€ΠΈΠ±ΡƒΡ‚Π°Ρ… `fill`, `stroke` ΠΈ inline `style` ΠΎΠ±Ρ€Π°Π±Π°Ρ‚Ρ‹Π²Π°ΡŽΡ‚ΡΡ Π½Π°Π΄Ρ‘ΠΆΠ½Π΅Π΅ всСго; -- CSS-классы ΠΈ внСшниС stylesheets Π²Π½ΡƒΡ‚Ρ€ΠΈ исходного SVG Π½Π΅ ΡΠ²Π»ΡΡŽΡ‚ΡΡ основным сцСнариСм трансформации; -- gradients, patterns, filters ΠΈ значСния `url(#...)` Ρ‚Ρ€Π΅Π±ΡƒΡŽΡ‚ ΠΎΡ‚Π΄Π΅Π»ΡŒΠ½ΠΎΠΉ ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΊΠΈ ΠΈ ΠΌΠΎΠ³ΡƒΡ‚ Π±Ρ‹Ρ‚ΡŒ нСсовмСстимы с автоматичСской Π·Π°ΠΌΠ΅Π½ΠΎΠΉ Ρ†Π²Π΅Ρ‚ΠΎΠ²; -- CSS-ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½Ρ‹Π΅ страницы доступны ΠΏΡ€ΠΈ ``, Π½ΠΎ нСдоступны Π²Π½ΡƒΡ‚Ρ€ΠΈ `` ΠΈ `background-image`. +- `none`, `transparent`, `inherit`, `unset`, and `initial` are not replaced; +- colors in `fill`, `stroke`, and inline `style` attributes are handled most reliably; +- CSS classes and external stylesheets inside the source SVG are not the primary transformation use case; +- gradients, patterns, filters, and `url(#...)` values require separate verification and may be incompatible with automatic color replacement; +- page CSS variables are available with ``, but are not available inside `` and `background-image`. -## ΠšΠ΅ΡˆΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠ΅ +## Caching -Vite, Webpack ΠΈ Next.js target Π²Ρ‹ΠΏΡƒΡΠΊΠ°ΡŽΡ‚ спрайт ΠΎΡ‚Π΄Π΅Π»ΡŒΠ½Ρ‹ΠΌ asset с content hash: +The Vite, Webpack, and Next.js targets emit the sprite as a separate asset with a content hash: ```text /assets/sprite-.svg ``` -Π­Ρ‚ΠΎ Π΄Π°Ρ‘Ρ‚ ΡΠ»Π΅Π΄ΡƒΡŽΡ‰ΠΈΠ΅ свойства: +This provides the following properties: -- SVG ΠΊΠ΅ΡˆΠΈΡ€ΡƒΠ΅Ρ‚ΡΡ нСзависимо ΠΎΡ‚ JavaScript; -- ΠΈΠ·ΠΌΠ΅Π½Π΅Π½ΠΈΠ΅ React-ΠΊΠΎΠ΄Π° Π½Π΅ мСняСт содСрТимоС спрайта; -- ΠΈΠ·ΠΌΠ΅Π½Π΅Π½ΠΈΠ΅ ΠΈΠΊΠΎΠ½ΠΎΠΊ создаёт Π½ΠΎΠ²Ρ‹ΠΉ hash asset; -- ΠΎΠ΄ΠΈΠ½ Ρ„Π°ΠΉΠ» ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ΡΡ всСми экзСмплярами generated-ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Π°; -- SVG path-Π΄Π°Π½Π½Ρ‹Π΅ ΠΎΡ‚ΡΡƒΡ‚ΡΡ‚Π²ΡƒΡŽΡ‚ Π² JavaScript chunks. +- the SVG is cached independently of JavaScript; +- changes to React code do not alter the sprite contents; +- icon changes produce a new hashed asset; +- one file is used by every instance of the generated component; +- SVG path data is absent from JavaScript chunks. -Vite target Π·Π°ΠΏΡ€Π΅Ρ‰Π°Π΅Ρ‚ inline Ρ‡Π΅Ρ€Π΅Π· `?no-inline`. Webpack 5 target ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ Asset Modules Ρ‡Π΅Ρ€Π΅Π· `new URL(..., import.meta.url)`. +The Vite target prevents inlining through `?no-inline`. The Webpack 5 target uses Asset Modules through `new URL(..., import.meta.url)`. ## SpriteViewer -`SpriteViewer` β€” React-ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚ для просмотра generated-спрайтов Π²Π½ΡƒΡ‚Ρ€ΠΈ debug-ΠΌΠ°Ρ€ΡˆΡ€ΡƒΡ‚Π° прилоТСния. +`SpriteViewer` is a React component for viewing generated sprites inside an application's debug route. -Он ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ ΠΎΡ‚Π΄Π΅Π»ΡŒΠ½Ρ‹Π΅ манифСсты ΠΈ ΠΏΠΎΠΊΠ°Π·Ρ‹Π²Π°Π΅Ρ‚: +It uses separate manifests and displays: -- Π³Ρ€ΡƒΠΏΠΏΡ‹ спрайтов; -- список ΠΈ количСство ΠΈΠΊΠΎΠ½ΠΎΠΊ; -- поиск ΠΈ ΡΠΈΡΡ‚Π΅ΠΌΠ½ΡƒΡŽ ΡΠ²Π΅Ρ‚Π»ΡƒΡŽ/Ρ‚Ρ‘ΠΌΠ½ΡƒΡŽ Ρ‚Π΅ΠΌΡƒ; -- модальноС ΠΏΡ€Π΅Π²ΡŒΡŽ с `viewBox` ΠΈ настройкой Ρ†Π²Π΅Ρ‚ΠΎΠ²Ρ‹Ρ… ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½Ρ‹Ρ…; -- ΠΏΡ€ΠΈΠΌΠ΅Ρ€Ρ‹ React, SVG, IMG ΠΈ CSS с ΠΊΠΎΠΏΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠ΅ΠΌ ΠΊΠΎΠ΄Π°. +- sprite groups; +- the icon list and count; +- search and the system light/dark theme; +- a preview modal with the `viewBox` and color variable controls; +- React, SVG, IMG, and CSS examples with code copying. -Production-ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Ρ‹ Π½Π΅ ΠΈΠΌΠΏΠΎΡ€Ρ‚ΠΈΡ€ΡƒΡŽΡ‚ debug-манифСсты. Бпособ ΠΏΠΎΠ΄ΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΡ Viewer зависит ΠΎΡ‚ сборщика: +Production components do not import debug manifests. How you integrate the Viewer depends on the bundler: -- [React + Vite: автоматичСский `import.meta.glob`](docs/ru/react-vite.md#6-Π΄ΠΎΠ±Π°Π²ΡŒΡ‚Π΅-debug-страницу); -- [React + Webpack 5: статичСскиС `import()`](docs/ru/react-webpack.md#6-Π΄ΠΎΠ±Π°Π²ΡŒΡ‚Π΅-debug-страницу); -- [Next.js App Router](docs/ru/next-app.md#5-Π΄ΠΎΠ±Π°Π²ΡŒΡ‚Π΅-spriteviewer); -- [Next.js Pages Router](docs/ru/next-pages.md#5-Π΄ΠΎΠ±Π°Π²ΡŒΡ‚Π΅-spriteviewer). +- [React + Vite: automatic `import.meta.glob`](docs/en/react-vite.md#6-add-a-debug-page); +- [React + Webpack 5: static `import()`](docs/en/react-webpack.md#6-add-a-debug-page); +- [Next.js App Router](docs/en/next-app.md#5-add-spriteviewer); +- [Next.js Pages Router](docs/en/next-pages.md#5-add-spriteviewer). -Viewer ΠΏΠΎΠ΄ΠΊΠ»ΡŽΡ‡Π°Π΅Ρ‚ΡΡ ΠΈΠ· ΠΎΡ‚Π΄Π΅Π»ΡŒΠ½ΠΎΠΉ клиСнтской Ρ‚ΠΎΡ‡ΠΊΠΈ Π²Ρ…ΠΎΠ΄Π° `@gromlab/svg-sprites/react` ΠΈ Π½Π΅ ΠΏΠΎΠΏΠ°Π΄Π°Π΅Ρ‚ Π² production-ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Ρ‹ ΠΈΠΊΠΎΠ½ΠΎΠΊ. +The Viewer is imported from the separate `@gromlab/svg-sprites/react` client entry point and is not included in production icon components. -### Π’Π΅ΠΌΠ° Viewer +### Viewer theme -По ΡƒΠΌΠΎΠ»Ρ‡Π°Π½ΠΈΡŽ `colorTheme="auto"`: Viewer слСдуСт `prefers-color-scheme` ΠΈ Ρ€Π΅Π°Π³ΠΈΡ€ΡƒΠ΅Ρ‚ Π½Π° смСну систСмной Ρ‚Π΅ΠΌΡ‹. Π’Π΅ΠΌΡƒ прилоТСния ΠΌΠΎΠΆΠ½ΠΎ ΠΏΠ΅Ρ€Π΅Π΄Π°Ρ‚ΡŒ явно: +By default, `colorTheme="auto"`: the Viewer follows `prefers-color-scheme` and responds to system theme changes. The application theme can be passed explicitly: ```tsx ``` -ДопустимыС значСния `colorTheme`: `auto`, `light`, `dark`. ΠŸΡ€ΠΈ ΡƒΠΏΡ€Π°Π²Π»Π΅Π½ΠΈΠΈ Ρ‚Π΅ΠΌΠΎΠΉ ΠΈΠ·Π²Π½Π΅ встроСнный ΠΏΠ΅Ρ€Π΅ΠΊΠ»ΡŽΡ‡Π°Ρ‚Π΅Π»ΡŒ скрываСтся. Π§Ρ‚ΠΎΠ±Ρ‹ ΠΎΡΡ‚Π°Π²ΠΈΡ‚ΡŒ Π΅Π³ΠΎ ΠΈ ΠΎΠ±Π½ΠΎΠ²Π»ΡΡ‚ΡŒ Ρ‚Π΅ΠΌΡƒ прилоТСния Ρ‡Π΅Ρ€Π΅Π· Viewer, ΠΏΠ΅Ρ€Π΅Π΄Π°ΠΉΡ‚Π΅ callback: +Valid `colorTheme` values are `auto`, `light`, and `dark`. When the theme is controlled externally, the built-in switch is hidden. To keep it and update the application theme through the Viewer, pass a callback: ```tsx ``` -## ДокумСнтация +## Documentation -- [React + Vite](docs/ru/react-vite.md) -- [React + Webpack 5](docs/ru/react-webpack.md) -- [Next.js App Router](docs/ru/next-app.md) -- [Next.js Pages Router](docs/ru/next-pages.md) -- [Legacy mode](docs/ru/legacy.md) -- [ΠœΠΈΠ³Ρ€Π°Ρ†ΠΈΡ с 0.1.x](docs/ru/migration-1.md) -- [ΠŸΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠ½Ρ‹ΠΉ API](docs/ru/programmatic-api.md) +- [React + Vite](docs/en/react-vite.md) +- [React + Webpack 5](docs/en/react-webpack.md) +- [Next.js App Router](docs/en/next-app.md) +- [Next.js Pages Router](docs/en/next-pages.md) +- [Legacy mode](docs/en/legacy.md) +- [Migrating from 0.1.x](docs/en/migration-1.md) +- [Programmatic API](docs/en/programmatic-api.md) -## ЛицСнзия +## License MIT diff --git a/skills/artifacts/svg-sprites/references/README_RU.md b/skills/artifacts/svg-sprites/references/README_RU.md new file mode 100644 index 0000000..8ac80c5 --- /dev/null +++ b/skills/artifacts/svg-sprites/references/README_RU.md @@ -0,0 +1,398 @@ +# @gromlab/svg-sprites + +[πŸ‡¬πŸ‡§ English](README.md) | πŸ‡·πŸ‡Ί Русский + +![npm](https://img.shields.io/npm/v/@gromlab/svg-sprites) ![license](https://img.shields.io/npm/l/@gromlab/svg-sprites) + +CLI для Π³Π΅Π½Π΅Ρ€Π°Ρ†ΠΈΠΈ SVG-спрайтов ΠΈ Ρ‚ΠΈΠΏΠΈΠ·ΠΈΡ€ΠΎΠ²Π°Π½Π½Ρ‹Ρ… ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚ΠΎΠ² ΠΈΠΊΠΎΠ½ΠΎΠΊ для React ΠΈ Next.js. + +![Preview](https://gromlab.ru/gromov/svg-sprites/media/branch/master/preview-image.png) + +## Навигация + +- [ВозмоТности](#возмоТности) +- [Π’Π°Π±Π»ΠΈΡ†Π° ΠΏΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΊΠΈ](#Ρ‚Π°Π±Π»ΠΈΡ†Π°-ΠΏΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΊΠΈ) +- [ВрСбования](#трСбования) +- [Быстрый старт](#быстрый-старт) + - [React + Vite](docs/ru/react-vite.md) + - [React + Webpack 5](docs/ru/react-webpack.md) + - [Next.js App Router](docs/ru/next-app.md) + - [Next.js Pages Router](docs/ru/next-pages.md) +- [ΠšΠΎΠ½Ρ„ΠΈΠ³ΡƒΡ€Π°Ρ†ΠΈΡ](#конфигурация) + - [React](#react) + - [Next.js](#nextjs) +- [ΠœΠ½ΠΎΠΆΠ΅ΡΡ‚Π²Π΅Π½Π½Ρ‹Π΅ спрайты](#мноТСствСнныС-спрайты) +- [TypeScript](#typescript) +- [Π€ΠΎΡ€ΠΌΠ°Ρ‚Ρ‹ спрайтов](#Ρ„ΠΎΡ€ΠΌΠ°Ρ‚Ρ‹-спрайтов) +- [Бпособы отобраТСния](#способы-отобраТСния) +- [Врансформации](#трансформации) +- [Π£ΠΏΡ€Π°Π²Π»Π΅Π½ΠΈΠ΅ Ρ†Π²Π΅Ρ‚ΠΎΠΌ ΠΈΠΊΠΎΠ½ΠΎΠΊ](#ΡƒΠΏΡ€Π°Π²Π»Π΅Π½ΠΈΠ΅-Ρ†Π²Π΅Ρ‚ΠΎΠΌ-ΠΈΠΊΠΎΠ½ΠΎΠΊ) +- [ΠšΠ΅ΡˆΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠ΅](#ΠΊΠ΅ΡˆΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠ΅) +- [SpriteViewer](#spriteviewer) +- [ΠœΠΈΠ³Ρ€Π°Ρ†ΠΈΡ с 0.1.x](docs/ru/migration-1.md) +- [ДокумСнтация](#докумСнтация) + +## ВозмоТности + +- **AI-agent friendly** β€” Ρ€Π΅ΠΏΠΎΠ·ΠΈΡ‚ΠΎΡ€ΠΈΠΉ содСрТит Π³ΠΎΡ‚ΠΎΠ²Ρ‹ΠΉ skill с Π°ΠΊΡ‚ΡƒΠ°Π»ΡŒΠ½ΠΎΠΉ Π΄ΠΎΠΊΡƒΠΌΠ΅Π½Ρ‚Π°Ρ†ΠΈΠ΅ΠΉ для настройки, ΠΌΠΈΠ³Ρ€Π°Ρ†ΠΈΠΈ ΠΈ диагностики `@gromlab/svg-sprites`. +- **TypeScript-friendly** β€” Ρ‚ΠΈΠΏΠΈΠ·ΠΈΡ€ΠΎΠ²Π°Π½Π½Ρ‹Π΅ React-ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Ρ‹, union-Ρ‚ΠΈΠΏΡ‹ ΠΈ runtime-списки доступных ΠΈΠΊΠΎΠ½ΠΎΠΊ. +- **Чистая гСнСрация** β€” generated-Ρ„Π°ΠΉΠ»Ρ‹ автоматичСски ΠΈΡΠΊΠ»ΡŽΡ‡Π°ΡŽΡ‚ΡΡ ΠΈΠ· Git, спрайт Π½Π΅ Π½ΡƒΠΆΠ½ΠΎ Π²Ρ€ΡƒΡ‡Π½ΡƒΡŽ Ρ€Π°Π·ΠΌΠ΅Ρ‰Π°Ρ‚ΡŒ Π² `public`, Π° Π³Π΅Π½Π΅Ρ€Π°Ρ‚ΠΎΡ€ обновляСт Ρ‚ΠΎΠ»ΡŒΠΊΠΎ ΠΏΡ€ΠΈΠ½Π°Π΄Π»Π΅ΠΆΠ°Ρ‰ΠΈΠ΅ Π΅ΠΌΡƒ Ρ„Π°ΠΉΠ»Ρ‹. +- **ΠžΠ±Ρ‰ΠΈΠ΅ ΠΈΠΊΠΎΠ½ΠΊΠΈ Π±Π΅Π· копирования** β€” SVG ΠΈΠ· локальной ΠΏΠ°ΠΏΠΊΠΈ ΠΈ `inputFiles` ΠΎΠ±ΡŠΠ΅Π΄ΠΈΠ½ΡΡŽΡ‚ΡΡ Π² ΠΎΠ΄ΠΈΠ½ спрайт; ΠΎΠ΄ΠΈΠ½ Ρ„Π°ΠΉΠ» ΠΌΠΎΠΆΠ½ΠΎ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ Π² Π½Π΅ΡΠΊΠΎΠ»ΡŒΠΊΠΈΡ… спрайтах. +- **ВстроСнноС ΠΈΠ½Ρ‚Π΅Ρ€Π°ΠΊΡ‚ΠΈΠ²Π½ΠΎΠ΅ ΠΏΡ€Π΅Π²ΡŒΡŽ** β€” `` ΠΏΠΎΠ΄ΠΊΠ»ΡŽΡ‡Π°Π΅Ρ‚ΡΡ ΠΊΠ°ΠΊ страница прилоТСния ΠΈ ΠΏΠΎΠΊΠ°Π·Ρ‹Π²Π°Π΅Ρ‚ ΠΏΠ΅Ρ€Π΅Π΄Π°Π½Π½Ρ‹Π΅ React- ΠΈ Next.js-спрайты с поиском, настройкой Ρ†Π²Π΅Ρ‚ΠΎΠ² ΠΈ ΠΏΡ€ΠΈΠΌΠ΅Ρ€Π°ΠΌΠΈ использования. +- **НастраиваСмыС трансформации SVG** β€” ΡƒΠ΄Π°Π»Π΅Π½ΠΈΠ΅ `width` ΠΈ `height` с сохранСниСм `viewBox`, Π·Π°ΠΌΠ΅Π½Π° исходных Ρ†Π²Π΅Ρ‚ΠΎΠ² Π½Π° CSS-ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½Ρ‹Π΅ ΠΈ transitions для `fill` ΠΈ `stroke`. +- **ΠžΡ‚Π΄Π΅Π»ΡŒΠ½Ρ‹ΠΉ ΠΊΠ΅ΡˆΠΈΡ€ΡƒΠ΅ΠΌΡ‹ΠΉ SVG asset** β€” SVG path-Π΄Π°Π½Π½Ρ‹Π΅ Π½Π΅ ΠΏΠΎΠΏΠ°Π΄Π°ΡŽΡ‚ Π² JavaScript chunks, Π° сборщик выпускаСт Ρ„Π°ΠΉΠ» с content hash. +- **ΠœΠ½ΠΎΠΆΠ΅ΡΡ‚Π²Π΅Π½Π½Ρ‹Π΅ спрайты** β€” нСзависимыС React- ΠΈ Next.js-ΠΌΠΎΠ΄ΡƒΠ»ΠΈ со своими ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Π°ΠΌΠΈ, Ρ‚ΠΈΠΏΠ°ΠΌΠΈ ΠΈ SVG assets. +- **Server-first Next.js** β€” generated-ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Ρ‹ Ρ€Π°Π±ΠΎΡ‚Π°ΡŽΡ‚ Π² Server Components, SSR ΠΈ SSG Π±Π΅Π· Π΄ΠΈΡ€Π΅ΠΊΡ‚ΠΈΠ²Ρ‹ `'use client'`. +- **Π€ΠΎΡ€ΠΌΠ°Ρ‚Ρ‹ ΠΏΠΎΠ΄ Ρ€Π°Π·Π½Ρ‹Π΅ сцСнарии** β€” React ΠΈ Next.js ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΡŽΡ‚ `stack`, legacy-Ρ€Π΅ΠΆΠΈΠΌ Ρ‚Π°ΠΊΠΆΠ΅ ΠΏΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΈΠ²Π°Π΅Ρ‚ `symbol` для ΡΡƒΡ‰Π΅ΡΡ‚Π²ΡƒΡŽΡ‰ΠΈΡ… ΠΈΠ½Ρ‚Π΅Π³Ρ€Π°Ρ†ΠΈΠΉ. + +## Π’Π°Π±Π»ΠΈΡ†Π° ΠΏΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΊΠΈ + +| Π‘Ρ€Π΅Π΄Π° | ΠšΠ»ΡŽΡ‡ ΠΌΠΎΠ΄Π° API | Бтатус | +|---|---|---| +| React + Vite | `react@vite` | Π“ΠΎΡ‚ΠΎΠ²ΠΎ | +| React + Webpack 5 | `react@webpack` | Π“ΠΎΡ‚ΠΎΠ²ΠΎ | +| Next.js 16.2+ App Router + Turbopack | `next@app/turbopack` | Π“ΠΎΡ‚ΠΎΠ²ΠΎ | +| Next.js 13.4+ App Router + Webpack 5 | `next@app/webpack` | Π“ΠΎΡ‚ΠΎΠ²ΠΎ | +| Next.js 16.2+ Pages Router + Turbopack | `next@pages/turbopack` | Π“ΠΎΡ‚ΠΎΠ²ΠΎ | +| Next.js 12.2+ Pages Router + Webpack 5 | `next@pages/webpack` | Π“ΠΎΡ‚ΠΎΠ²ΠΎ | +| Vue | β€” | Π‘ΠΊΠΎΡ€ΠΎ | +| Standalone | β€” | Π‘ΠΊΠΎΡ€ΠΎ | + +## ВрСбования + +- Node.js 18 ΠΈΠ»ΠΈ Π½ΠΎΠ²Π΅Π΅; +- ΠΏΠ°ΠΊΠ΅Ρ‚ распространяСтся Ρ‚ΠΎΠ»ΡŒΠΊΠΎ ΠΊΠ°ΠΊ ESM ΠΈ ΠΏΠΎΠ΄ΠΊΠ»ΡŽΡ‡Π°Π΅Ρ‚ΡΡ Ρ‡Π΅Ρ€Π΅Π· `import`; +- React 18 ΠΈΠ»ΠΈ 19 трСбуСтся Ρ‚ΠΎΠ»ΡŒΠΊΠΎ для generated-ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚ΠΎΠ² ΠΈ Ρ‚ΠΎΡ‡ΠΊΠΈ Π²Ρ…ΠΎΠ΄Π° `@gromlab/svg-sprites/react`; +- для Ρ‚ΠΈΠΏΠΈΠ·Π°Ρ†ΠΈΠΈ subpath exports ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠΉΡ‚Π΅ TypeScript 5+ с `moduleResolution: "bundler"`, `"node16"` ΠΈΠ»ΠΈ `"nodenext"`. + +## Быстрый старт + +Для быстрого старта Π²ΠΎΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠΉΡ‚Π΅ΡΡŒ инструкциСй для вашСго стСка: + +- [React + Vite](docs/ru/react-vite.md) +- [React + Webpack 5](docs/ru/react-webpack.md) +- [Next.js App Router](docs/ru/next-app.md) +- [Next.js Pages Router](docs/ru/next-pages.md) + +## ΠšΠΎΠ½Ρ„ΠΈΠ³ΡƒΡ€Π°Ρ†ΠΈΡ + +### React + +```ts +import { defineReactSpriteConfig } from '@gromlab/svg-sprites' + +export default defineReactSpriteConfig({ + name: 'file-manager', + description: 'Иконки Ρ„Π°ΠΉΠ»ΠΎΠ²ΠΎΠ³ΠΎ ΠΌΠ΅Π½Π΅Π΄ΠΆΠ΅Ρ€Π°', + inputFolder: './icons', + inputFiles: [ + '../../shared/icons/check.svg', + ], + transform: { + removeSize: true, + replaceColors: true, + addTransition: true, + }, + generatedNotice: true, +}) +``` + +| ΠžΠΏΡ†ΠΈΡ | Π’ΠΈΠΏ | По ΡƒΠΌΠΎΠ»Ρ‡Π°Π½ΠΈΡŽ | НазначСниС | +|---|---|---|---| +| `name` | `string` | Имя ΠΏΠ°ΠΏΠΊΠΈ | Имя спрайта, ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Π° ΠΈ ΠΏΡƒΠ±Π»ΠΈΡ‡Π½Ρ‹Ρ… Ρ‚ΠΈΠΏΠΎΠ² | +| `description` | `string` | НСт | ОписаниС для Ρ‚ΠΈΠΏΠΎΠ² ΠΈ debug-манифСста | +| `inputFolder` | `string` | `./icons` | Папка с исходными SVG ΠΎΡ‚Π½ΠΎΡΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎ ΠΊΠΎΠ½Ρ„ΠΈΠ³Π° | +| `inputFiles` | `string[]` | `[]` | Π”ΠΎΠΏΠΎΠ»Π½ΠΈΡ‚Π΅Π»ΡŒΠ½Ρ‹Π΅ SVG-Ρ„Π°ΠΉΠ»Ρ‹ ΠΎΡ‚Π½ΠΎΡΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎ ΠΊΠΎΠ½Ρ„ΠΈΠ³Π° | +| `transform` | `TransformOptions` | ВсС Π²ΠΊΠ»ΡŽΡ‡Π΅Π½Ρ‹ | [Настройки трансформации](#трансформации) исходных SVG | +| `generatedNotice` | `boolean` | `true` | ПолноС Π»ΠΈΠ±ΠΎ ΠΊΠΎΡ€ΠΎΡ‚ΠΊΠΎΠ΅ ΠΏΡ€Π΅Π΄ΡƒΠΏΡ€Π΅ΠΆΠ΄Π΅Π½ΠΈΠ΅ Π² generated-Ρ„Π°ΠΉΠ»Π°Ρ… | + +`inputFolder` ΠΈ `inputFiles` ΠΎΠ±ΡŠΠ΅Π΄ΠΈΠ½ΡΡŽΡ‚ΡΡ Π² ΠΎΠ΄ΠΈΠ½ спрайт, поэтому ΠΎΠ΄ΠΈΠ½ SVG-Ρ„Π°ΠΉΠ» ΠΌΠΎΠΆΠ½ΠΎ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ Π² Π½Π΅ΡΠΊΠΎΠ»ΡŒΠΊΠΈΡ… спрайтах Π±Π΅Π· копирования. Если нСявной ΠΏΠ°ΠΏΠΊΠΈ `./icons` Π½Π΅Ρ‚, Π½ΠΎ `inputFiles` Π·Π°ΠΏΠΎΠ»Π½Π΅Π½, гСнСрация продолТаСтся Ρ‚ΠΎΠ»ΡŒΠΊΠΎ ΠΏΠΎ списку. Π―Π²Π½ΠΎ указанная ΠΎΡ‚ΡΡƒΡ‚ΡΡ‚Π²ΡƒΡŽΡ‰Π°Ρ ΠΏΠ°ΠΏΠΊΠ° считаСтся ошибкой. ΠžΠ΄ΠΈΠ½Π°ΠΊΠΎΠ²Ρ‹Π΅ ΠΏΡƒΡ‚ΠΈ Π΄Π΅Π΄ΡƒΠΏΠ»ΠΈΡ†ΠΈΡ€ΡƒΡŽΡ‚ΡΡ, Π° Ρ€Π°Π·Π½Ρ‹Π΅ Ρ„Π°ΠΉΠ»Ρ‹ с ΠΎΠ΄ΠΈΠ½Π°ΠΊΠΎΠ²Ρ‹ΠΌ ΠΈΠΌΠ΅Π½Π΅ΠΌ ΠΈΠΊΠΎΠ½ΠΊΠΈ ΡΡ‡ΠΈΡ‚Π°ΡŽΡ‚ΡΡ ошибкой. + +`name` записываСтся Π² kebab-case ΠΈ Π΄ΠΎΠ»ΠΆΠ½ΠΎ Π½Π°Ρ‡ΠΈΠ½Π°Ρ‚ΡŒΡΡ с латинской Π±ΡƒΠΊΠ²Ρ‹. React ΠΈ Next.js presets ΡΠΎΠ·Π΄Π°ΡŽΡ‚ Ρ„ΠΎΡ€ΠΌΠ°Ρ‚ `stack`. + +### Next.js + +Next.js ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ Ρ‚ΠΎΡ‚ ΠΆΠ΅ `svg-sprite.config.ts` ΠΈ Π½Π°Π±ΠΎΡ€ ΠΎΠΏΡ†ΠΈΠΉ. Для Ρ‚ΠΈΠΏΠΈΠ·Π°Ρ†ΠΈΠΈ ΠΌΠΎΠΆΠ½ΠΎ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ ΠΎΡ‚Π΄Π΅Π»ΡŒΠ½Ρ‹ΠΉ Ρ…Π΅Π»ΠΏΠ΅Ρ€: + +```ts +import { defineNextSpriteConfig } from '@gromlab/svg-sprites' + +export default defineNextSpriteConfig({ + name: 'file-manager', + description: 'Иконки Ρ„Π°ΠΉΠ»ΠΎΠ²ΠΎΠ³ΠΎ ΠΌΠ΅Π½Π΅Π΄ΠΆΠ΅Ρ€Π°', + inputFolder: './icons', +}) +``` + +Π ΠΎΡƒΡ‚Π΅Ρ€ ΠΈ сборщик Π²Ρ‹Π±ΠΈΡ€Π°ΡŽΡ‚ΡΡ Ρ‡Π΅Ρ€Π΅Π· mode key, поэтому ΠΏΠ΅Ρ€Π΅ΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅ ΠΌΠ΅ΠΆΠ΄Ρƒ Turbopack ΠΈ Webpack всСгда явно ΠΎΡ‚Ρ€Π°ΠΆΠ΅Π½ΠΎ Π² ΠΊΠΎΠΌΠ°Π½Π΄Π΅ Π³Π΅Π½Π΅Ρ€Π°Ρ†ΠΈΠΈ. + +## ΠœΠ½ΠΎΠΆΠ΅ΡΡ‚Π²Π΅Π½Π½Ρ‹Π΅ спрайты + +ΠŸΡ€ΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅ ΠΌΠΎΠΆΠ΅Ρ‚ ΡΠΎΠ΄Π΅Ρ€ΠΆΠ°Ρ‚ΡŒ нСсколько нСзависимых спрайтов с Ρ€Π°Π·Π½ΠΎΠΉ ΠΎΠ±Π»Π°ΡΡ‚ΡŒΡŽ использования: + +**ΠŸΡ€ΠΎΠ±Π»Π΅ΠΌΠ°:** ΠΎΠ΄ΠΈΠ½ Π³Π»ΠΎΠ±Π°Π»ΡŒΠ½Ρ‹ΠΉ спрайт Π·Π°Π³Ρ€ΡƒΠΆΠ°Π΅Ρ‚ ΠΈΠΊΠΎΠ½ΠΊΠΈ, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ Ρ‚Π΅ΠΊΡƒΡ‰Π΅ΠΌΡƒ экрану Π½Π΅ Π½ΡƒΠΆΠ½Ρ‹. + +**РСшСниС:** ΠΎΠ±Ρ‰ΠΈΠ΅ ΠΈΠΊΠΎΠ½ΠΊΠΈ Ρ…Ρ€Π°Π½ΠΈΡ‚ΡŒ глобально, Π° Π½Π°Π±ΠΎΡ€Ρ‹ страниц ΠΈ ΠΊΡ€ΡƒΠΏΠ½Ρ‹Ρ… ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚ΠΎΠ² β€” Π² ΠΎΡ‚Π΄Π΅Π»ΡŒΠ½Ρ‹Ρ… спрайтах, Π·Π°Π³Ρ€ΡƒΠΆΠ°Π΅ΠΌΡ‹Ρ… вмСстС с Π½ΠΈΠΌΠΈ. + +```text +global β†’ GlobalIcon β†’ ΠΎΠ±Ρ‰ΠΈΠ΅ ΠΈΠΊΠΎΠ½ΠΊΠΈ прилоТСния +analytics-page β†’ AnalyticsPageIcon β†’ ΠΈΠΊΠΎΠ½ΠΊΠΈ ΠΎΡ‚Π΄Π΅Π»ΡŒΠ½ΠΎΠΉ страницы +file-manager β†’ FileManagerIcon β†’ ΠΈΠΊΠΎΠ½ΠΊΠΈ ΠΊΡ€ΡƒΠΏΠ½ΠΎΠ³ΠΎ ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Π° +``` + +- **Π“Π»ΠΎΠ±Π°Π»ΡŒΠ½Ρ‹ΠΉ спрайт** содСрТит нСбольшиС ΠΎΠ±Ρ‰ΠΈΠ΅ ΠΈΠΊΠΎΠ½ΠΊΠΈ, ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅ΠΌΡ‹Π΅ Π² Ρ€Π°Π·Π½Ρ‹Ρ… частях прилоТСния: Π½Π°Π²ΠΈΠ³Π°Ρ†ΠΈΡŽ, состояния ΠΈ Π±Π°Π·ΠΎΠ²Ρ‹Π΅ дСйствия. +- **Π‘ΠΏΡ€Π°ΠΉΡ‚ страницы** загруТаСтся вмСстС с ΠΊΠΎΠ½ΠΊΡ€Π΅Ρ‚Π½Ρ‹ΠΌ Ρ€Π°Π·Π΄Π΅Π»ΠΎΠΌ ΠΈ Π½Π΅ ΡƒΠ²Π΅Π»ΠΈΡ‡ΠΈΠ²Π°Π΅Ρ‚ ΠΎΠ±Ρ‰ΠΈΠΉ спрайт ΠΈΠΊΠΎΠ½ΠΊΠ°ΠΌΠΈ, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ большС Π½ΠΈΠ³Π΄Π΅ Π½Π΅ Π½ΡƒΠΆΠ½Ρ‹. +- **Π‘ΠΏΡ€Π°ΠΉΡ‚ ΠΊΡ€ΡƒΠΏΠ½ΠΎΠ³ΠΎ ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Π°** инкапсулируСт собствСнный Π½Π°Π±ΠΎΡ€ ΠΈΠΊΠΎΠ½ΠΎΠΊ слоТного UI-модуля, Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€ Ρ„Π°ΠΉΠ»ΠΎΠ²ΠΎΠ³ΠΎ ΠΌΠ΅Π½Π΅Π΄ΠΆΠ΅Ρ€Π° ΠΈΠ»ΠΈ Ρ€Π΅Π΄Π°ΠΊΡ‚ΠΎΡ€Π°. + +КаТдая Π³Ρ€ΡƒΠΏΠΏΠ° ΠΏΠΎΠ»ΡƒΡ‡Π°Π΅Ρ‚: + +- собствСнный SVG asset; +- собствСнный Ρ‚ΠΈΠΏΠΈΠ·ΠΈΡ€ΠΎΠ²Π°Π½Π½Ρ‹ΠΉ ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚; +- ΠΎΡ‚Π΄Π΅Π»ΡŒΠ½Ρ‹ΠΉ список ΠΈΠΌΡ‘Π½ ΠΈΠΊΠΎΠ½ΠΎΠΊ; +- ΠΎΡ‚Π΄Π΅Π»ΡŒΠ½Ρ‹ΠΉ debug-манифСст; +- нСзависимый cache lifecycle. + + +## TypeScript + +Главная Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎΡΡ‚ΡŒ TypeScript API β€” Π°Π²Ρ‚ΠΎΠ΄ΠΎΠΏΠΎΠ»Π½Π΅Π½ΠΈΠ΅ ΠΈΠΌΡ‘Π½ ΠΈΠΊΠΎΠ½ΠΎΠΊ нСпосрСдствСнно Π² prop `icon`: + +```tsx + +// ↑ Ρ€Π΅Π΄Π°ΠΊΡ‚ΠΎΡ€ ΠΏΡ€Π΅Π΄Π»Π°Π³Π°Π΅Ρ‚ всС ΠΈΠΊΠΎΠ½ΠΊΠΈ спрайта +``` + +ИмСна SVG-Ρ„Π°ΠΉΠ»ΠΎΠ² становятся допустимыми значСниями `icon`. ΠžΠΏΠ΅Ρ‡Π°Ρ‚ΠΊΠ° ΠΈΠ»ΠΈ нСизвСстноС имя сразу становятся ошибкой TypeScript: + +```tsx + // ошибка TypeScript +``` + +Для ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠ½ΠΎΠ³ΠΎ доступа generated-ΠΌΠΎΠ΄ΡƒΠ»ΡŒ экспортируСт readonly-массив всСх доступных ΠΈΠΊΠΎΠ½ΠΎΠΊ ΠΊΠΎΠ½ΠΊΡ€Π΅Ρ‚Π½ΠΎΠ³ΠΎ спрайта: + +```ts +import { fileManagerIconNames } from './svg-sprite' + +// readonly ['check', 'folder', ...] +``` + +Π­Ρ‚ΠΎΡ‚ список ΠΌΠΎΠΆΠ½ΠΎ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ Π² собствСнных ΠΊΠ°Ρ‚Π°Π»ΠΎΠ³Π°Ρ…, select-ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Π°Ρ…, тСстах ΠΈ Π΄Ρ€ΡƒΠ³ΠΈΡ… runtime-сцСнариях. Из Π½Π΅Π³ΠΎ Ρ‚Π°ΠΊΠΆΠ΅ выводится union-Ρ‚ΠΈΠΏ `FileManagerIconName`. + +ИмСна Ρ„Π°ΠΉΠ»ΠΎΠ² с ΠΏΡ€ΠΎΠ±Π΅Π»Π°ΠΌΠΈ ΠΈ Π΄Ρ€ΡƒΠ³ΠΈΠΌΠΈ нСбСзопасными для SVG ID символами ΠΎΡΡ‚Π°ΡŽΡ‚ΡΡ Ρ‡Π°ΡΡ‚ΡŒΡŽ ΠΏΡƒΠ±Π»ΠΈΡ‡Π½ΠΎΠ³ΠΎ TypeScript API. Для Π²Π½ΡƒΡ‚Ρ€Π΅Π½Π½Π΅Π³ΠΎ `` Π³Π΅Π½Π΅Ρ€Π°Ρ‚ΠΎΡ€ создаёт ΡΡ‚Π°Π±ΠΈΠ»ΡŒΠ½Ρ‹ΠΉ hash ID. + +```text +folder open.svg β†’ icon="folder open" β†’ id="icon-" +``` + +Для Ρ‚Π°ΠΊΠΈΡ… ΠΈΠΌΡ‘Π½ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠΉΡ‚Π΅ generated-ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚ ΠΈΠ»ΠΈ `id` ΠΈΠ· debug-манифСста. Π ΡƒΡ‡Π½Ρ‹Π΅ ΠΏΡ€ΠΈΠΌΠ΅Ρ€Ρ‹ Π½ΠΈΠΆΠ΅ с `#<имя>` подходят Ρ‚ΠΎΠ»ΡŒΠΊΠΎ для ΠΈΠΌΡ‘Π½, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ ΡƒΠΆΠ΅ ΡΠ²Π»ΡΡŽΡ‚ΡΡ бСзопасными SVG ID. + +## Π€ΠΎΡ€ΠΌΠ°Ρ‚Ρ‹ спрайтов + +`stack` β€” Π±ΠΎΠ»Π΅Π΅ соврСмСнный Ρ„ΠΎΡ€ΠΌΠ°Ρ‚, поэтому ΠΎΠ½ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ΡΡ ΠΏΠΎ ΡƒΠΌΠΎΠ»Ρ‡Π°Π½ΠΈΡŽ. Иконки ΠΌΠΎΠΆΠ½ΠΎ ΠΎΡ‚ΠΎΠ±Ρ€Π°ΠΆΠ°Ρ‚ΡŒ Ρ‡Π΅Ρ€Π΅Π· ``, `` ΠΈ CSS `background-image`. + +`symbol` сохраняСтся для совмСстимости с ΡΡƒΡ‰Π΅ΡΡ‚Π²ΡƒΡŽΡ‰ΠΈΠΌΠΈ интСграциями ΠΈ ΠΏΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΈΠ²Π°Π΅Ρ‚ ΠΎΡ‚ΠΎΠ±Ρ€Π°ΠΆΠ΅Π½ΠΈΠ΅ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ Ρ‡Π΅Ρ€Π΅Π· ``. + +## Бпособы отобраТСния + +### React-ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚ β€” рСкомСндуСтся + +Generated-ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚ прСдоставляСт Ρ‚ΠΈΠΏΠΈΠ·Π°Ρ†ΠΈΡŽ, Π°Π²Ρ‚ΠΎΠ΄ΠΎΠΏΠΎΠ»Π½Π΅Π½ΠΈΠ΅ ΠΈΠΌΡ‘Π½ ΠΈΠΊΠΎΠ½ΠΎΠΊ ΠΈ сам Ρ„ΠΎΡ€ΠΌΠΈΡ€ΡƒΠ΅Ρ‚ URL SVG asset. + +```tsx + +``` + +Π§Π΅Ρ€Π΅Π· `color` ΠΈ `--icon-color-N` доступны ΠΎΠ΄Π½ΠΎΡ†Π²Π΅Ρ‚Π½Ρ‹Π΅ ΠΈ ΠΌΠ½ΠΎΠ³ΠΎΡ†Π²Π΅Ρ‚Π½Ρ‹Π΅ ΠΈΠΊΠΎΠ½ΠΊΠΈ. + +### Π‘Π°ΠΌΠΎΡΡ‚ΠΎΡΡ‚Π΅Π»ΡŒΠ½ΠΎ Ρ‡Π΅Ρ€Π΅Π· `` + +Π₯ΠΎΡ€ΠΎΡˆΠΈΠΉ Π½ΠΈΠ·ΠΊΠΎΡƒΡ€ΠΎΠ²Π½Π΅Π²Ρ‹ΠΉ способ с ΠΏΠΎΠ»Π½Ρ‹ΠΌ ΡƒΠΏΡ€Π°Π²Π»Π΅Π½ΠΈΠ΅ΠΌ Ρ€Π°Π·ΠΌΠ΅Ρ€Π°ΠΌΠΈ ΠΈ Ρ†Π²Π΅Ρ‚Π°ΠΌΠΈ. React-ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚ ΠΏΠΎΠ΄ ΠΊΠ°ΠΏΠΎΡ‚ΠΎΠΌ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ ΠΈΠΌΠ΅Π½Π½ΠΎ Π΅Π³ΠΎ. + +Бпособ получСния `spriteUrl` зависит ΠΎΡ‚ сборщика. + +**Vite:** + +```tsx +import spriteUrl from './svg-sprite/generated/sprite.svg?no-inline' +``` + +**Webpack 5:** + +```tsx +const spriteUrl = new URL( + './svg-sprite/generated/sprite.svg', + import.meta.url, +).href +``` + +**Next.js с Webpack 5 ΠΈΠ»ΠΈ Turbopack:** + +```tsx +const spriteUrl = new URL( + './svg-sprite/generated/sprite.svg', + import.meta.url, +).href +``` + +ПослС получСния URL ΠΈΠΊΠΎΠ½ΠΊΠ° отобраТаСтся ΠΎΠ΄ΠΈΠ½Π°ΠΊΠΎΠ²ΠΎ: + +```tsx + + + +``` + +Vite, Webpack 5 ΠΈ Next.js сами Π·Π°ΠΌΠ΅Π½ΡΡŽΡ‚ исходный ΠΏΡƒΡ‚ΡŒ Π½Π° ΠΈΡ‚ΠΎΠ³ΠΎΠ²Ρ‹ΠΉ URL asset с hash. + +### Π§Π΅Ρ€Π΅Π· `` β€” ΠΌΠ΅Π½Π΅Π΅ эффСктивно + +```tsx +Π“ΠΎΡ‚ΠΎΠ²ΠΎ +``` + +SVG загруТаСтся ΠΊΠ°ΠΊ ΠΈΠ·ΠΎΠ»ΠΈΡ€ΠΎΠ²Π°Π½Π½ΠΎΠ΅ ΠΈΠ·ΠΎΠ±Ρ€Π°ΠΆΠ΅Π½ΠΈΠ΅: ΠΈΠ·ΠΌΠ΅Π½ΠΈΡ‚ΡŒ Π΅Π³ΠΎ Ρ†Π²Π΅Ρ‚Π° Ρ‡Π΅Ρ€Π΅Π· `color` ΠΈΠ»ΠΈ `--icon-color-N` нСльзя. + +### Π§Π΅Ρ€Π΅Π· CSS `background-image` β€” ΠΌΠ΅Π½Π΅Π΅ эффСктивно + +```css +.icon { + background: url('./svg-sprite/generated/sprite.svg#check') center / contain no-repeat; +} +``` + +Как ΠΈ ``, этот способ Π½Π΅ позволяСт ΡƒΠΏΡ€Π°Π²Π»ΡΡ‚ΡŒ Π²Π½ΡƒΡ‚Ρ€Π΅Π½Π½ΠΈΠΌΠΈ Ρ†Π²Π΅Ρ‚Π°ΠΌΠΈ SVG. ΠŸΡƒΡ‚ΡŒ указываСтся ΠΎΡ‚Π½ΠΎΡΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎ CSS-Ρ„Π°ΠΉΠ»Π°, Π° Vite/Webpack замСняСт Π΅Π³ΠΎ Π½Π° ΠΈΡ‚ΠΎΠ³ΠΎΠ²Ρ‹ΠΉ URL с hash ΠΏΡ€ΠΈ сборкС. + +### Π§Π΅Ρ€Π΅Π· CSS mask β€” ΠΌΠ΅Π½Π΅Π΅ эффСктивно + +```css +.icon { + background-color: currentColor; + mask: url('./svg-sprite/generated/sprite.svg#check') center / contain no-repeat; +} +``` + +Mask оставляСт Ρ‚ΠΎΠ»ΡŒΠΊΠΎ силуэт ΠΈ ΠΎΠΊΡ€Π°ΡˆΠΈΠ²Π°Π΅Ρ‚ Π΅Π³ΠΎ ΠΎΠ΄Π½ΠΈΠΌ Ρ†Π²Π΅Ρ‚ΠΎΠΌ. Π˜ΡΡ…ΠΎΠ΄Π½Ρ‹Π΅ Ρ†Π²Π΅Ρ‚Π°, gradients ΠΈ различия ΠΌΠ΅ΠΆΠ΄Ρƒ `fill` ΠΈ `stroke` Ρ‚Π΅Ρ€ΡΡŽΡ‚ΡΡ. + +## Врансформации + +ВсС трансформации Π²ΠΊΠ»ΡŽΡ‡Π΅Π½Ρ‹ ΠΏΠΎ ΡƒΠΌΠΎΠ»Ρ‡Π°Π½ΠΈΡŽ ΠΈ Π½Π°ΡΡ‚Ρ€Π°ΠΈΠ²Π°ΡŽΡ‚ΡΡ нСзависимо Ρ‡Π΅Ρ€Π΅Π· `transform`. + +| ΠžΠΏΡ†ΠΈΡ | По ΡƒΠΌΠΎΠ»Ρ‡Π°Π½ΠΈΡŽ | Π§Ρ‚ΠΎ Π΄Π΅Π»Π°Π΅Ρ‚ | +|---|---|---| +| `removeSize` | `true` | УдаляСт `width` ΠΈ `height` с ΠΊΠΎΡ€Π½Π΅Π²ΠΎΠ³ΠΎ ``, сохраняя ΡΡƒΡ‰Π΅ΡΡ‚Π²ΡƒΡŽΡ‰ΠΈΠΉ `viewBox`. Π Π°Π·ΠΌΠ΅Ρ€ ΠΈΠΊΠΎΠ½ΠΊΠΈ послС этого задаётся снаруТи. | +| `replaceColors` | `true` | ЗамСняСт Ρ†Π²Π΅Ρ‚Π° `fill` ΠΈ `stroke` Π½Π° `--icon-color-N`. Для ΠΎΠ΄Π½ΠΎΡ†Π²Π΅Ρ‚Π½ΠΎΠΉ ΠΈΠΊΠΎΠ½ΠΊΠΈ fallback становится `currentColor`, для ΠΌΠ½ΠΎΠ³ΠΎΡ†Π²Π΅Ρ‚Π½ΠΎΠΉ ΡΠΎΡ…Ρ€Π°Π½ΡΡŽΡ‚ΡΡ исходныС Ρ†Π²Π΅Ρ‚Π°. | +| `addTransition` | `true` | ДобавляСт `style="transition:fill 0.3s,stroke 0.3s;"` нСпосрСдствСнно Ρ†Π²Π΅Ρ‚Π½Ρ‹ΠΌ элСмСнтам SVG. Π‘ΡƒΡ‰Π΅ΡΡ‚Π²ΡƒΡŽΡ‰ΠΈΠΉ `transition` Π½Π΅ пСрСзаписываСтся. | + +Π§Ρ‚ΠΎΠ±Ρ‹ ΠΎΡ‚ΠΊΠ»ΡŽΡ‡ΠΈΡ‚ΡŒ ΠΏΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΠΎΠ²Π°Π½ΠΈΠ΅, ΠΏΠ΅Ρ€Π΅Π΄Π°ΠΉΡ‚Π΅ для ΡΠΎΠΎΡ‚Π²Π΅Ρ‚ΡΡ‚Π²ΡƒΡŽΡ‰Π΅ΠΉ ΠΎΠΏΡ†ΠΈΠΈ `false`. ΠŸΠΎΠ΄Ρ€ΠΎΠ±Π½Π΅Π΅ ΠΎ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Π΅ `replaceColors` β€” Π² Ρ€Π°Π·Π΄Π΅Π»Π΅ [Β«Π£ΠΏΡ€Π°Π²Π»Π΅Π½ΠΈΠ΅ Ρ†Π²Π΅Ρ‚ΠΎΠΌ ΠΈΠΊΠΎΠ½ΠΎΠΊΒ»](#ΡƒΠΏΡ€Π°Π²Π»Π΅Π½ΠΈΠ΅-Ρ†Π²Π΅Ρ‚ΠΎΠΌ-ΠΈΠΊΠΎΠ½ΠΎΠΊ). + +## Π£ΠΏΡ€Π°Π²Π»Π΅Π½ΠΈΠ΅ Ρ†Π²Π΅Ρ‚ΠΎΠΌ ΠΈΠΊΠΎΠ½ΠΎΠΊ + +ΠŸΡ€ΠΈ Π²ΠΊΠ»ΡŽΡ‡Ρ‘Π½Π½ΠΎΠΉ Π·Π°ΠΌΠ΅Π½Π΅ Ρ†Π²Π΅Ρ‚ΠΎΠ² Π³Π΅Π½Π΅Ρ€Π°Ρ‚ΠΎΡ€ Π°Π½Π°Π»ΠΈΠ·ΠΈΡ€ΡƒΠ΅Ρ‚ `fill` ΠΈ `stroke` ΠΈ ΠΏΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΡƒΠ΅Ρ‚ ΠΈΡ… Π² CSS custom properties. + +### ΠœΠΎΠ½ΠΎΡ…Ρ€ΠΎΠΌΠ½Ρ‹Π΅ ΠΈΠΊΠΎΠ½ΠΊΠΈ + +Если Π½Π°ΠΉΠ΄Π΅Π½ ΠΎΠ΄ΠΈΠ½ Ρ†Π²Π΅Ρ‚, fallback замСняСтся Π½Π° `currentColor`: + +```svg +stroke="var(--icon-color-1, currentColor)" +``` + +Π¦Π²Π΅Ρ‚ΠΎΠΌ управляСт CSS-свойство `color` внСшнСго `` ΠΈΠ»ΠΈ Π΅Π³ΠΎ родитСля. + +### ΠœΠ½ΠΎΠ³ΠΎΡ†Π²Π΅Ρ‚Π½Ρ‹Π΅ ΠΈΠΊΠΎΠ½ΠΊΠΈ + +ΠšΠ°ΠΆΠ΄Ρ‹ΠΉ ΡƒΠ½ΠΈΠΊΠ°Π»ΡŒΠ½Ρ‹ΠΉ Ρ†Π²Π΅Ρ‚ ΠΏΠΎΠ»ΡƒΡ‡Π°Π΅Ρ‚ ΠΎΡ‚Π΄Π΅Π»ΡŒΠ½ΡƒΡŽ ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½ΡƒΡŽ с исходным fallback: + +```svg +fill="var(--icon-color-1, #798198)" +fill="var(--icon-color-2, #ffffff)" +fill="var(--icon-color-3, #129d9d)" +``` + +Π‘Ρ‚Ρ€Π°Π½ΠΈΡ†Π° ΠΌΠΎΠΆΠ΅Ρ‚ Π·Π°ΠΌΠ΅Π½ΠΈΡ‚ΡŒ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΡ‹Π΅ Ρ†Π²Π΅Ρ‚Π°: + +```css +.icon { + --icon-color-1: #4b5563; + --icon-color-3: #14b8a6; +} +``` + +### ΠžΠ³Ρ€Π°Π½ΠΈΡ‡Π΅Π½ΠΈΡ Ρ†Π²Π΅Ρ‚ΠΎΠ² + +- `none`, `transparent`, `inherit`, `unset` ΠΈ `initial` Π½Π΅ Π·Π°ΠΌΠ΅Π½ΡΡŽΡ‚ΡΡ; +- Ρ†Π²Π΅Ρ‚Π° Π² Π°Ρ‚Ρ€ΠΈΠ±ΡƒΡ‚Π°Ρ… `fill`, `stroke` ΠΈ inline `style` ΠΎΠ±Ρ€Π°Π±Π°Ρ‚Ρ‹Π²Π°ΡŽΡ‚ΡΡ Π½Π°Π΄Ρ‘ΠΆΠ½Π΅Π΅ всСго; +- CSS-классы ΠΈ внСшниС stylesheets Π²Π½ΡƒΡ‚Ρ€ΠΈ исходного SVG Π½Π΅ ΡΠ²Π»ΡΡŽΡ‚ΡΡ основным сцСнариСм трансформации; +- gradients, patterns, filters ΠΈ значСния `url(#...)` Ρ‚Ρ€Π΅Π±ΡƒΡŽΡ‚ ΠΎΡ‚Π΄Π΅Π»ΡŒΠ½ΠΎΠΉ ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΊΠΈ ΠΈ ΠΌΠΎΠ³ΡƒΡ‚ Π±Ρ‹Ρ‚ΡŒ нСсовмСстимы с автоматичСской Π·Π°ΠΌΠ΅Π½ΠΎΠΉ Ρ†Π²Π΅Ρ‚ΠΎΠ²; +- CSS-ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½Ρ‹Π΅ страницы доступны ΠΏΡ€ΠΈ ``, Π½ΠΎ нСдоступны Π²Π½ΡƒΡ‚Ρ€ΠΈ `` ΠΈ `background-image`. + +## ΠšΠ΅ΡˆΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠ΅ + +Vite, Webpack ΠΈ Next.js target Π²Ρ‹ΠΏΡƒΡΠΊΠ°ΡŽΡ‚ спрайт ΠΎΡ‚Π΄Π΅Π»ΡŒΠ½Ρ‹ΠΌ asset с content hash: + +```text +/assets/sprite-.svg +``` + +Π­Ρ‚ΠΎ Π΄Π°Ρ‘Ρ‚ ΡΠ»Π΅Π΄ΡƒΡŽΡ‰ΠΈΠ΅ свойства: + +- SVG ΠΊΠ΅ΡˆΠΈΡ€ΡƒΠ΅Ρ‚ΡΡ нСзависимо ΠΎΡ‚ JavaScript; +- ΠΈΠ·ΠΌΠ΅Π½Π΅Π½ΠΈΠ΅ React-ΠΊΠΎΠ΄Π° Π½Π΅ мСняСт содСрТимоС спрайта; +- ΠΈΠ·ΠΌΠ΅Π½Π΅Π½ΠΈΠ΅ ΠΈΠΊΠΎΠ½ΠΎΠΊ создаёт Π½ΠΎΠ²Ρ‹ΠΉ hash asset; +- ΠΎΠ΄ΠΈΠ½ Ρ„Π°ΠΉΠ» ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ΡΡ всСми экзСмплярами generated-ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Π°; +- SVG path-Π΄Π°Π½Π½Ρ‹Π΅ ΠΎΡ‚ΡΡƒΡ‚ΡΡ‚Π²ΡƒΡŽΡ‚ Π² JavaScript chunks. + +Vite target Π·Π°ΠΏΡ€Π΅Ρ‰Π°Π΅Ρ‚ inline Ρ‡Π΅Ρ€Π΅Π· `?no-inline`. Webpack 5 target ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ Asset Modules Ρ‡Π΅Ρ€Π΅Π· `new URL(..., import.meta.url)`. + +## SpriteViewer + +`SpriteViewer` β€” React-ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚ для просмотра generated-спрайтов Π²Π½ΡƒΡ‚Ρ€ΠΈ debug-ΠΌΠ°Ρ€ΡˆΡ€ΡƒΡ‚Π° прилоТСния. + +Он ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ ΠΎΡ‚Π΄Π΅Π»ΡŒΠ½Ρ‹Π΅ манифСсты ΠΈ ΠΏΠΎΠΊΠ°Π·Ρ‹Π²Π°Π΅Ρ‚: + +- Π³Ρ€ΡƒΠΏΠΏΡ‹ спрайтов; +- список ΠΈ количСство ΠΈΠΊΠΎΠ½ΠΎΠΊ; +- поиск ΠΈ ΡΠΈΡΡ‚Π΅ΠΌΠ½ΡƒΡŽ ΡΠ²Π΅Ρ‚Π»ΡƒΡŽ/Ρ‚Ρ‘ΠΌΠ½ΡƒΡŽ Ρ‚Π΅ΠΌΡƒ; +- модальноС ΠΏΡ€Π΅Π²ΡŒΡŽ с `viewBox` ΠΈ настройкой Ρ†Π²Π΅Ρ‚ΠΎΠ²Ρ‹Ρ… ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½Ρ‹Ρ…; +- ΠΏΡ€ΠΈΠΌΠ΅Ρ€Ρ‹ React, SVG, IMG ΠΈ CSS с ΠΊΠΎΠΏΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠ΅ΠΌ ΠΊΠΎΠ΄Π°. + +Production-ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Ρ‹ Π½Π΅ ΠΈΠΌΠΏΠΎΡ€Ρ‚ΠΈΡ€ΡƒΡŽΡ‚ debug-манифСсты. Бпособ ΠΏΠΎΠ΄ΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΡ Viewer зависит ΠΎΡ‚ сборщика: + +- [React + Vite: автоматичСский `import.meta.glob`](docs/ru/react-vite.md#6-Π΄ΠΎΠ±Π°Π²ΡŒΡ‚Π΅-debug-страницу); +- [React + Webpack 5: статичСскиС `import()`](docs/ru/react-webpack.md#6-Π΄ΠΎΠ±Π°Π²ΡŒΡ‚Π΅-debug-страницу); +- [Next.js App Router](docs/ru/next-app.md#5-Π΄ΠΎΠ±Π°Π²ΡŒΡ‚Π΅-spriteviewer); +- [Next.js Pages Router](docs/ru/next-pages.md#5-Π΄ΠΎΠ±Π°Π²ΡŒΡ‚Π΅-spriteviewer). + +Viewer ΠΏΠΎΠ΄ΠΊΠ»ΡŽΡ‡Π°Π΅Ρ‚ΡΡ ΠΈΠ· ΠΎΡ‚Π΄Π΅Π»ΡŒΠ½ΠΎΠΉ клиСнтской Ρ‚ΠΎΡ‡ΠΊΠΈ Π²Ρ…ΠΎΠ΄Π° `@gromlab/svg-sprites/react` ΠΈ Π½Π΅ ΠΏΠΎΠΏΠ°Π΄Π°Π΅Ρ‚ Π² production-ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Ρ‹ ΠΈΠΊΠΎΠ½ΠΎΠΊ. + +### Π’Π΅ΠΌΠ° Viewer + +По ΡƒΠΌΠΎΠ»Ρ‡Π°Π½ΠΈΡŽ `colorTheme="auto"`: Viewer слСдуСт `prefers-color-scheme` ΠΈ Ρ€Π΅Π°Π³ΠΈΡ€ΡƒΠ΅Ρ‚ Π½Π° смСну систСмной Ρ‚Π΅ΠΌΡ‹. Π’Π΅ΠΌΡƒ прилоТСния ΠΌΠΎΠΆΠ½ΠΎ ΠΏΠ΅Ρ€Π΅Π΄Π°Ρ‚ΡŒ явно: + +```tsx + +``` + +ДопустимыС значСния `colorTheme`: `auto`, `light`, `dark`. ΠŸΡ€ΠΈ ΡƒΠΏΡ€Π°Π²Π»Π΅Π½ΠΈΠΈ Ρ‚Π΅ΠΌΠΎΠΉ ΠΈΠ·Π²Π½Π΅ встроСнный ΠΏΠ΅Ρ€Π΅ΠΊΠ»ΡŽΡ‡Π°Ρ‚Π΅Π»ΡŒ скрываСтся. Π§Ρ‚ΠΎΠ±Ρ‹ ΠΎΡΡ‚Π°Π²ΠΈΡ‚ΡŒ Π΅Π³ΠΎ ΠΈ ΠΎΠ±Π½ΠΎΠ²Π»ΡΡ‚ΡŒ Ρ‚Π΅ΠΌΡƒ прилоТСния Ρ‡Π΅Ρ€Π΅Π· Viewer, ΠΏΠ΅Ρ€Π΅Π΄Π°ΠΉΡ‚Π΅ callback: + +```tsx + +``` + +## ДокумСнтация + +- [React + Vite](docs/ru/react-vite.md) +- [React + Webpack 5](docs/ru/react-webpack.md) +- [Next.js App Router](docs/ru/next-app.md) +- [Next.js Pages Router](docs/ru/next-pages.md) +- [Legacy mode](docs/ru/legacy.md) +- [ΠœΠΈΠ³Ρ€Π°Ρ†ΠΈΡ с 0.1.x](docs/ru/migration-1.md) +- [ΠŸΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠ½Ρ‹ΠΉ API](docs/ru/programmatic-api.md) + +## ЛицСнзия + +MIT diff --git a/skills/artifacts/svg-sprites/references/docs/en/legacy.md b/skills/artifacts/svg-sprites/references/docs/en/legacy.md new file mode 100644 index 0000000..10b6ea1 --- /dev/null +++ b/skills/artifacts/svg-sprites/references/docs/en/legacy.md @@ -0,0 +1,102 @@ +# Legacy mode + +[← Back to home](../../README.md) + +A quick guide to generating centralized SVG sprites in `symbol` and `stack` formats, with an optional HTML preview. + +## 1. Install the package + +```bash +npm install @gromlab/svg-sprites +``` + +## 2. Prepare the icons and config + +```text +project/ +β”œβ”€β”€ src/assets/icons/ +β”‚ β”œβ”€β”€ check.svg +β”‚ └── folder.svg +└── svg-sprites.config.ts +``` + +```ts +// svg-sprites.config.ts +import { defineLegacyConfig } from '@gromlab/svg-sprites' + +export default defineLegacyConfig({ + output: 'public/sprites', + preview: true, + sprites: [ + { + name: 'icons', + input: 'src/assets/icons', + format: 'symbol', + }, + ], +}) +``` + +## 3. Run generation + +```bash +npx svg-sprites --mode legacy . +``` + +Result: + +```text +public/sprites/ +β”œβ”€β”€ icons.sprite.svg +└── preview.html +``` + +With `preview: false`, the HTML file is not created. For the `stack` format, specify `format: 'stack'`. + +## 4. Use the symbol sprite + +```html + + + +``` + +## 5. Add a package script + +```json +{ + "scripts": { + "sprites": "svg-sprites --mode legacy .", + "prebuild": "npm run sprites" + } +} +``` + +## Multiple sprites + +Add multiple entries to `sprites`: + +```ts +sprites: [ + { + name: 'icons', + input: 'src/assets/icons', + format: 'symbol', + }, + { + name: 'logos', + input: 'src/assets/logos', + format: 'stack', + }, +] +``` + +All output files and the shared `preview.html` will be written to `output`. + +## Troubleshooting + +- Config not found: make sure `svg-sprites.config.ts` is located in the specified root directory. +- No icons: check `sprites[].input` and the `.svg` extension. +- Preview not needed: set `preview: false`. + +For programmatic use, see [`generateLegacy`](programmatic-api.md#generatelegacy). diff --git a/skills/artifacts/svg-sprites/references/docs/en/migration-1.md b/skills/artifacts/svg-sprites/references/docs/en/migration-1.md new file mode 100644 index 0000000..b53b915 --- /dev/null +++ b/skills/artifacts/svg-sprites/references/docs/en/migration-1.md @@ -0,0 +1,96 @@ +# Migrating from 0.1.x to 1.0 + +[← Back to home](../../README.md) + +Version 1.0 separates local generation for React and Next.js from the centralized legacy mode. The old config cannot be mixed with the new API in a single CLI invocation. + +## CLI + +The CLI now always requires an explicit `--mode` and a path to the configuration directory: + +```text +svg-sprites +β†’ svg-sprites --mode +``` + +Choose a mode based on your environment: + +| Environment | Mode | +|---|---| +| 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` | +| Centralized legacy setup | `legacy` | + +## React and Next.js + +Instead of a root-level `svg-sprites.config.ts`, create a local `svg-sprite.config.ts` next to the icon set: + +```ts +import { defineNextSpriteConfig } from '@gromlab/svg-sprites' + +export default defineNextSpriteConfig({ + name: 'global', + inputFolder: './icons', +}) +``` + +For regular React, use `defineReactSpriteConfig`. A folder and an explicit list of shared SVG files can be combined using `inputFolder` and `inputFiles`. + +The old `publicPath` and `react` options are no longer needed. The generated module is created next to the config and adds its own `.gitignore`, while Vite, Webpack, or Next.js emits the SVG as a separate asset with a content hash. + +The `` component is replaced by a component whose name is derived from `name`: + +```tsx + +``` + +To browse the icons, add `` as a debug page in the application. A separate `preview.html` is available only in legacy mode. + +## Legacy mode + +If you need to preserve the centralized structure, rename the helper and the format fields: + +```ts +import { defineLegacyConfig } from '@gromlab/svg-sprites' + +export default defineLegacyConfig({ + output: 'public/sprites', + preview: true, + sprites: [ + { + name: 'icons', + input: 'src/assets/icons', + format: 'stack', + }, + ], +}) +``` + +- `defineConfig` has been replaced with `defineLegacyConfig`; +- `sprites[].mode` has been renamed to `sprites[].format`; +- `generate` has been replaced with `generateLegacy`; +- `loadConfig` has been replaced with `loadLegacyConfig`; +- `publicPath` and generation of the old shared React component have been removed. + +Run: + +```bash +svg-sprites --mode legacy . +``` + +## Programmatic API + +The package is distributed as ESM only. Replace `require()` with `import`. + +`compileSpriteContent` now returns `Promise` so that the public declarations do not require `@types/node` to be installed. In Node.js, the actual result is compatible with APIs that accept `Uint8Array`. + +## After migration + +1. Remove the old generated files and rules that ignored the entire directory containing the source icons. +2. Add an explicit generation command before `dev`, `build`, and `typecheck`. +3. Run generation and type checking. +4. Check all icons and color variables using `SpriteViewer` or the legacy `preview.html`. diff --git a/skills/artifacts/svg-sprites/references/docs/en/next-app.md b/skills/artifacts/svg-sprites/references/docs/en/next-app.md new file mode 100644 index 0000000..1e334ce --- /dev/null +++ b/skills/artifacts/svg-sprites/references/docs/en/next-app.md @@ -0,0 +1,102 @@ +# Next.js App Router + +[← Back to home](../../README.md) + +Two explicit modes are supported: + +| Bundler | Mode key | Next.js version | +|---|---|---| +| Turbopack | `next@app/turbopack` | 16.2+ | +| Webpack 5 | `next@app/webpack` | 13.4+ | + +## 1. Install the package + +```bash +npm install @gromlab/svg-sprites +``` + +## 2. Create a sprite module + +```text +src/ui/file-manager/svg-sprite/ +β”œβ”€β”€ icons/ +β”‚ β”œβ”€β”€ check.svg +β”‚ └── folder.svg +└── svg-sprite.config.ts +``` + +```ts +// src/ui/file-manager/svg-sprite/svg-sprite.config.ts +import { defineNextSpriteConfig } from '@gromlab/svg-sprites' + +export default defineNextSpriteConfig({ + name: 'file-manager', + description: 'File manager icons', +}) +``` + +## 3. Add generation + +For Turbopack: + +```json +{ + "scripts": { + "sprite:file-manager": "svg-sprites --mode next@app/turbopack src/ui/file-manager/svg-sprite", + "predev": "npm run sprite:file-manager", + "prebuild": "npm run sprite:file-manager" + } +} +``` + +For Webpack, replace the mode key with `next@app/webpack`. In Next 13–15, Webpack is used with the regular `next build` command; in Next 16, use `next build --webpack`. + +## 4. Use it in a Server Component + +The generated component does not contain `'use client'`, so it can be imported directly into `page.tsx` or `layout.tsx`: + +```tsx +import { FileManagerIcon } from '@/ui/file-manager/svg-sprite' + +export default function Page() { + return ( +
+ +
+ ) +} +``` + +Next.js emits a separate SVG asset with a content hash. The same generated code is used during SSR and in the browser, with no URL mismatch. + +## 5. Add SpriteViewer + +The viewer is interactive, so it requires a separate Client Component boundary: + +```tsx +'use client' + +import { SpriteViewer } from '@gromlab/svg-sprites/react' + +const sources = [ + () => import('@/ui/file-manager/svg-sprite/manifest'), +] + +export default function SpritesPage() { + return +} +``` + +## Verify the bundler + +```bash +# Turbopack +npx next build --turbopack + +# Webpack 5 +npx next build --webpack +``` + +For Next 13–15 with Webpack, use `npx next build` without the flag. + +The Next.js command and the generator mode key must target the same bundler. diff --git a/skills/artifacts/svg-sprites/references/docs/en/next-pages.md b/skills/artifacts/svg-sprites/references/docs/en/next-pages.md new file mode 100644 index 0000000..0de0136 --- /dev/null +++ b/skills/artifacts/svg-sprites/references/docs/en/next-pages.md @@ -0,0 +1,96 @@ +# Next.js Pages Router + +[← Back to home](../../README.md) + +Two explicit modes are supported: + +| Bundler | Mode key | Next.js version | +|---|---|---| +| Turbopack | `next@pages/turbopack` | 16.2+ | +| Webpack 5 | `next@pages/webpack` | 12.2+ | + +Next.js 12.2 requires React 18. + +## 1. Install the package + +```bash +npm install @gromlab/svg-sprites +``` + +## 2. Create a sprite module + +```text +src/ui/file-manager/svg-sprite/ +β”œβ”€β”€ icons/ +β”‚ β”œβ”€β”€ check.svg +β”‚ └── folder.svg +└── svg-sprite.config.ts +``` + +```ts +// src/ui/file-manager/svg-sprite/svg-sprite.config.ts +import { defineNextSpriteConfig } from '@gromlab/svg-sprites' + +export default defineNextSpriteConfig({ + name: 'file-manager', + description: 'File manager icons', +}) +``` + +## 3. Add generation + +```json +{ + "scripts": { + "sprite:file-manager": "svg-sprites --mode next@pages/webpack src/ui/file-manager/svg-sprite", + "predev": "npm run sprite:file-manager", + "prebuild": "npm run sprite:file-manager" + } +} +``` + +For Next.js 16.2 with Turbopack, replace the mode key with `next@pages/turbopack`. + +## 4. Use it on a page + +```tsx +import { FileManagerIcon } from '@/ui/file-manager/svg-sprite' + +export default function FilesPage() { + return +} + +export function getServerSideProps() { + return { props: {} } +} +``` + +The component works the same way with SSR, SSG, and client-side navigation. Next.js emits a separate SVG asset with a content hash. + +## 5. Add SpriteViewer + +```tsx +import { SpriteViewer } from '@gromlab/svg-sprites/react' + +const sources = [ + () => import('@/ui/file-manager/svg-sprite/manifest'), +] + +export default function SpritesPage() { + return +} +``` + +## Verify the bundler + +```bash +# Turbopack +npx next build --turbopack + +# Webpack 5 +npx next build --webpack +``` + +For Next 12–15 with Webpack, use `npx next build` without the flag. + +The Next.js command and the generator mode key must target the same bundler. diff --git a/skills/artifacts/svg-sprites/references/docs/en/programmatic-api.md b/skills/artifacts/svg-sprites/references/docs/en/programmatic-api.md new file mode 100644 index 0000000..7a4d44b --- /dev/null +++ b/skills/artifacts/svg-sprites/references/docs/en/programmatic-api.md @@ -0,0 +1,203 @@ +# Programmatic API + +[← Back to home](../../README.md) + +The package provides a main Node.js entry point and a separate React runtime entry point. Both are distributed as ESM only and must be loaded with `import`. + +To resolve `@gromlab/svg-sprites/react` in TypeScript, use `moduleResolution: "bundler"`, `"node16"`, or `"nodenext"`. + +## Main entry point + +```ts +import { + defineNextSpriteConfig, + defineReactSpriteConfig, + generateNextSprite, + generateReactSprite, +} from '@gromlab/svg-sprites' +``` + +The main entry point does not import React and can be used in CLIs, build scripts, and Node.js tools. + +## `generateReactSprite` + +```ts +import { generateReactSprite } from '@gromlab/svg-sprites' + +const result = await generateReactSprite( + 'src/ui/file-manager/svg-sprite', + 'vite', +) +``` + +The second argument is required: + +```ts +type ReactAssetTarget = 'vite' | 'webpack' +``` + +Result: + +```ts +type ReactSpriteGenerationResult = { + name: string + rootDir: string + generatedDir: string + spritePath: string + manifestPath: string + iconCount: number + target: 'vite' | 'webpack' +} +``` + +```ts +console.log(result.name) +console.log(result.iconCount) +console.log(result.spritePath) +console.log(result.manifestPath) +``` + +The function loads `svg-sprite.config.ts` from the specified root, compiles the SVG files, and safely updates managed files. + +## `generateNextSprite` + +```ts +import { generateNextSprite } from '@gromlab/svg-sprites' + +const result = await generateNextSprite( + 'src/ui/file-manager/svg-sprite', + { + router: 'app', + bundler: 'turbopack', + }, +) +``` + +Available values: + +```ts +type NextSpriteGenerationOptions = { + router: 'app' | 'pages' + bundler: 'turbopack' | 'webpack' +} +``` + +The result also contains the selected `router`, `bundler`, and the full target in the form `next@app/turbopack`. + +## `defineReactSpriteConfig` + +```ts +import { defineReactSpriteConfig } from '@gromlab/svg-sprites' + +export default defineReactSpriteConfig({ + name: 'file-manager', + description: 'File manager icons', + inputFolder: './icons', + inputFiles: [ + '../../shared/icons/check.svg', + ], + transform: { + removeSize: true, + replaceColors: true, + addTransition: true, + }, + generatedNotice: true, +}) +``` + +`inputFolder` and `inputFiles` are combined. The helper returns the configuration without runtime transformations and provides TypeScript autocomplete. + +## `defineNextSpriteConfig` + +```ts +import { defineNextSpriteConfig } from '@gromlab/svg-sprites' + +export default defineNextSpriteConfig({ + name: 'file-manager', + description: 'File manager icons', + inputFolder: './icons', +}) +``` + +Next.js uses the same configuration contract as the React presets. + +## `generateLegacy` + +```ts +import { generateLegacy } from '@gromlab/svg-sprites' + +const results = await generateLegacy({ + output: 'public/sprites', + preview: false, + sprites: [ + { + name: 'icons', + input: 'src/assets/icons', + format: 'symbol', + }, + ], +}) +``` + +Returns an array: + +```ts +type SpriteResult = { + name: string + format: 'symbol' | 'stack' + spritePath: string + iconCount: number +} +``` + +For details, see [Legacy mode](legacy.md). + +## Low-level functions + +The main entry point also exports: + +```ts +import { + compileSprite, + compileSpriteContent, + createShapeTransform, + generatePreview, + loadLegacyConfig, + loadReactSpriteConfig, + resolveSpriteEntry, + resolveSprites, +} from '@gromlab/svg-sprites' +``` + +These functions are intended for custom orchestration built on top of the existing compiler and writer. For standard usage, prefer `generateReactSprite` and `generateLegacy`. + +## React runtime entry point + +```tsx +import { SpriteViewer } from '@gromlab/svg-sprites/react' +``` + +Types: + +```ts +import type { + SpriteManifest, + SpriteManifestColor, + SpriteManifestIcon, + SpriteManifestLoader, + SpriteManifestModule, + SpriteViewerColorTheme, + SpriteViewerProps, + SpriteViewerSource, + SpriteViewerSources, +} from '@gromlab/svg-sprites/react' +``` + +The React entry point contains `'use client'` and is intended for debug tools. Generated production components are imported from the application's local sprite modules, not from the package's React entry point. + +`SpriteViewerProps.colorTheme` accepts `auto | light | dark`. The default is `auto`, which follows `prefers-color-scheme`; to synchronize it with the application theme, pass the computed `light` or `dark` value. + +## Related guides + +- [React + Vite](react-vite.md) +- [React + Webpack 5](react-webpack.md) diff --git a/skills/artifacts/svg-sprites/references/docs/en/react-vite.md b/skills/artifacts/svg-sprites/references/docs/en/react-vite.md new file mode 100644 index 0000000..1e37cc4 --- /dev/null +++ b/skills/artifacts/svg-sprites/references/docs/en/react-vite.md @@ -0,0 +1,116 @@ +# React + Vite + +[← Back to home](../../README.md) + +A quick guide to installing and using SVG sprites in a React and Vite project. + +The result is a typed React component and a separate cacheable SVG asset. + +## 1. Install the package + +```bash +npm install @gromlab/svg-sprites +``` + +## 2. Create the sprite directory + +```text +src/ui/file-manager/svg-sprite/ +β”œβ”€β”€ icons/ +β”‚ β”œβ”€β”€ check.svg +β”‚ └── folder.svg +└── svg-sprite.config.ts +``` + +Place the source SVG files in `icons/`. + +## 3. Add the configuration + +```ts +// src/ui/file-manager/svg-sprite/svg-sprite.config.ts +import { defineReactSpriteConfig } from '@gromlab/svg-sprites' + +export default defineReactSpriteConfig({ + name: 'file-manager', + description: 'File manager icons', +}) +``` + +By default, SVG files are loaded from `./icons`. You can add shared icons from other directories through `inputFiles`: the directory and file list are combined into a single sprite. + +The complete list of options is available under [Configuration β†’ React](../../README.md#react). + +## 4. Add generation to package.json + +```json +{ + "scripts": { + "sprite:file-manager": "svg-sprites --mode react@vite src/ui/file-manager/svg-sprite", + "predev": "npm run sprite:file-manager", + "prebuild": "npm run sprite:file-manager", + "pretypecheck": "npm run sprite:file-manager" + } +} +``` + +Generated files are excluded from Git, so generation must run before `dev`, `build`, and `typecheck`. + +First run: + +```bash +npm run sprite:file-manager +``` + +## 5. Use the component + +The name `file-manager` is converted to `FileManagerIcon`: + +```tsx +import { FileManagerIcon } from './svg-sprite' + +export const OpenFolderButton = () => ( + +) +``` + +TypeScript checks the `icon` value against the file names: + +```tsx + // valid + // TypeScript error +``` + +Types, display methods, and color controls are described in the [main documentation](../../README.md#display-methods). + +Vite emits the sprite as a separate file named like `assets/sprite-.svg`. SVG path data is not included in JavaScript. + +## 6. Add a debug page + +After integrating the icons, you can display all React sprites with `SpriteViewer`: + +```tsx +import { SpriteViewer } from '@gromlab/svg-sprites/react' +import type { SpriteManifestModule } from '@gromlab/svg-sprites/react' + +const sources = import.meta.glob( + '/src/**/svg-sprite/manifest.ts', +) + +export const IconsDebugPage = () => ( + +) +``` + +Vite automatically finds the generated `manifest.ts` for each React sprite. The `import.meta.glob` pattern must be a string literal, and generation must run before Vite starts. + +Only include the Viewer on a debug route or in an internal tool. + +## Troubleshooting + +- Missing `index.ts`: run `npm run sprite:file-manager`. +- The Viewer cannot find the sprite: check the glob path and make sure `manifest.ts` exists. +- `Refusing to overwrite a user file` error: there is a user file at a generated path. +- The icon does not change color: use `color` or `--icon-color-N`. diff --git a/skills/artifacts/svg-sprites/references/docs/en/react-webpack.md b/skills/artifacts/svg-sprites/references/docs/en/react-webpack.md new file mode 100644 index 0000000..15383db --- /dev/null +++ b/skills/artifacts/svg-sprites/references/docs/en/react-webpack.md @@ -0,0 +1,118 @@ +# React + Webpack 5 + +[← Back to home](../../README.md) + +A quick guide to installing and using SVG sprites in a React and Webpack 5 project. + +The result is a typed React component and a separate SVG asset emitted through Webpack Asset Modules. + +## 1. Install the package + +```bash +npm install @gromlab/svg-sprites +``` + +## 2. Create the sprite directory + +```text +src/ui/file-manager/svg-sprite/ +β”œβ”€β”€ icons/ +β”‚ β”œβ”€β”€ check.svg +β”‚ └── folder.svg +└── svg-sprite.config.ts +``` + +Place the source SVG files in `icons/`. + +## 3. Add the configuration + +```ts +// src/ui/file-manager/svg-sprite/svg-sprite.config.ts +import { defineReactSpriteConfig } from '@gromlab/svg-sprites' + +export default defineReactSpriteConfig({ + name: 'file-manager', + description: 'File manager icons', +}) +``` + +By default, SVG files are loaded from `./icons`. You can add shared icons from other directories through `inputFiles`: the directory and file list are combined into a single sprite. + +The complete list of options is available under [Configuration β†’ React](../../README.md#react). + +## 4. Add generation to package.json + +```json +{ + "scripts": { + "sprite:file-manager": "svg-sprites --mode react@webpack src/ui/file-manager/svg-sprite", + "predev": "npm run sprite:file-manager", + "prebuild": "npm run sprite:file-manager", + "pretypecheck": "npm run sprite:file-manager" + } +} +``` + +Generated files are excluded from Git, so generation must run before `dev`, `build`, and `typecheck`. + +First run: + +```bash +npm run sprite:file-manager +``` + +## 5. Use the component + +```tsx +import { FileManagerIcon } from './svg-sprite' + +export const OpenFolderButton = () => ( + +) +``` + +TypeScript checks the `icon` value against the file names: + +```tsx + // valid + // TypeScript error +``` + +Types, display methods, and color controls are described in the [main documentation](../../README.md#display-methods). + +Webpack processes the generated `new URL('./sprite.svg', import.meta.url)` through Asset Modules and emits a separate SVG asset. + +If the project already uses a custom SVG loader, make sure it does not intercept the generated `sprite.svg` instead of Asset Modules. + +## 6. Add a debug page + +Webpack does not support Vite's `import.meta.glob` API, so provide static loaders: + +```tsx +import { SpriteViewer } from '@gromlab/svg-sprites/react' + +const sources = [ + () => import('./ui/file-manager/svg-sprite/manifest'), + () => import('./ui/navigation/svg-sprite/manifest'), +] + +export const IconsDebugPage = () => ( + +) +``` + +The paths in `import()` must be string literals. Webpack creates chunks for the manifests and associates them with the SVG assets. + +Only include the Viewer on a debug route or in an internal tool. + +## Troubleshooting + +- Missing `index.ts`: run `npm run sprite:file-manager`. +- The Viewer does not load the sprite: check the path in `import()` and make sure `manifest.ts` exists. +- Incorrect asset URL: check `output.publicPath`. +- Another loader intercepts the SVG: exclude the generated sprite from the incompatible rule. + +For Next.js, use the separate mode keys described in the [App Router](next-app.md) and [Pages Router](next-pages.md) guides. diff --git a/skills/artifacts/svg-sprites/references/docs/ru/legacy.md b/skills/artifacts/svg-sprites/references/docs/ru/legacy.md index 5efd0cf..3d722b8 100644 --- a/skills/artifacts/svg-sprites/references/docs/ru/legacy.md +++ b/skills/artifacts/svg-sprites/references/docs/ru/legacy.md @@ -1,6 +1,6 @@ # Legacy mode -[← Главная](../../README.md) +[← Главная](../../README_RU.md) ΠšΡ€Π°Ρ‚ΠΊΠ°Ρ инструкция ΠΏΠΎ Π³Π΅Π½Π΅Ρ€Π°Ρ†ΠΈΠΈ Ρ†Π΅Π½Ρ‚Ρ€Π°Π»ΠΈΠ·ΠΎΠ²Π°Π½Π½Ρ‹Ρ… SVG-спрайтов Ρ„ΠΎΡ€ΠΌΠ°Ρ‚ΠΎΠ² `symbol` ΠΈ `stack` с optional HTML preview. diff --git a/skills/artifacts/svg-sprites/references/docs/ru/migration-1.md b/skills/artifacts/svg-sprites/references/docs/ru/migration-1.md index a41d3d9..39b15d8 100644 --- a/skills/artifacts/svg-sprites/references/docs/ru/migration-1.md +++ b/skills/artifacts/svg-sprites/references/docs/ru/migration-1.md @@ -1,6 +1,6 @@ # ΠœΠΈΠ³Ρ€Π°Ρ†ΠΈΡ с 0.1.x Π½Π° 1.0 -[← Главная](../../README.md) +[← Главная](../../README_RU.md) ВСрсия 1.0 раздСляСт Π»ΠΎΠΊΠ°Π»ΡŒΠ½ΡƒΡŽ Π³Π΅Π½Π΅Ρ€Π°Ρ†ΠΈΡŽ для React ΠΈ Next.js ΠΈ Ρ†Π΅Π½Ρ‚Ρ€Π°Π»ΠΈΠ·ΠΎΠ²Π°Π½Π½Ρ‹ΠΉ legacy-Ρ€Π΅ΠΆΠΈΠΌ. Π‘Ρ‚Π°Ρ€Ρ‹ΠΉ config нСльзя ΡΠΌΠ΅ΡˆΠΈΠ²Π°Ρ‚ΡŒ с Π½ΠΎΠ²Ρ‹ΠΌ API Π² ΠΎΠ΄Π½ΠΎΠΌ Π²Ρ‹Π·ΠΎΠ²Π΅ CLI. diff --git a/skills/artifacts/svg-sprites/references/docs/ru/next-app.md b/skills/artifacts/svg-sprites/references/docs/ru/next-app.md index 593d02d..06049c6 100644 --- a/skills/artifacts/svg-sprites/references/docs/ru/next-app.md +++ b/skills/artifacts/svg-sprites/references/docs/ru/next-app.md @@ -1,6 +1,6 @@ # Next.js App Router -[← Главная](../../README.md) +[← Главная](../../README_RU.md) ΠŸΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΈΠ²Π°ΡŽΡ‚ΡΡ Π΄Π²Π° явных Ρ€Π΅ΠΆΠΈΠΌΠ°: diff --git a/skills/artifacts/svg-sprites/references/docs/ru/next-pages.md b/skills/artifacts/svg-sprites/references/docs/ru/next-pages.md index d52750b..926f0ef 100644 --- a/skills/artifacts/svg-sprites/references/docs/ru/next-pages.md +++ b/skills/artifacts/svg-sprites/references/docs/ru/next-pages.md @@ -1,6 +1,6 @@ # Next.js Pages Router -[← Главная](../../README.md) +[← Главная](../../README_RU.md) ΠŸΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΈΠ²Π°ΡŽΡ‚ΡΡ Π΄Π²Π° явных Ρ€Π΅ΠΆΠΈΠΌΠ°: diff --git a/skills/artifacts/svg-sprites/references/docs/ru/programmatic-api.md b/skills/artifacts/svg-sprites/references/docs/ru/programmatic-api.md index 510b5fc..999cd01 100644 --- a/skills/artifacts/svg-sprites/references/docs/ru/programmatic-api.md +++ b/skills/artifacts/svg-sprites/references/docs/ru/programmatic-api.md @@ -1,6 +1,6 @@ # ΠŸΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠ½Ρ‹ΠΉ API -[← Главная](../../README.md) +[← Главная](../../README_RU.md) ΠŸΠ°ΠΊΠ΅Ρ‚ прСдоставляСт ΠΎΡΠ½ΠΎΠ²Π½ΡƒΡŽ Node.js Ρ‚ΠΎΡ‡ΠΊΡƒ Π²Ρ…ΠΎΠ΄Π° ΠΈ ΠΎΡ‚Π΄Π΅Π»ΡŒΠ½Ρ‹ΠΉ React runtime entry. ОбС Ρ‚ΠΎΡ‡ΠΊΠΈ Ρ€Π°ΡΠΏΡ€ΠΎΡΡ‚Ρ€Π°Π½ΡΡŽΡ‚ΡΡ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ ΠΊΠ°ΠΊ ESM ΠΈ ΠΏΠΎΠ΄ΠΊΠ»ΡŽΡ‡Π°ΡŽΡ‚ΡΡ Ρ‡Π΅Ρ€Π΅Π· `import`. diff --git a/skills/artifacts/svg-sprites/references/docs/ru/react-vite.md b/skills/artifacts/svg-sprites/references/docs/ru/react-vite.md index 1aa146e..2ae3b39 100644 --- a/skills/artifacts/svg-sprites/references/docs/ru/react-vite.md +++ b/skills/artifacts/svg-sprites/references/docs/ru/react-vite.md @@ -1,6 +1,6 @@ # React + Vite -[← Главная](../../README.md) +[← Главная](../../README_RU.md) ΠšΡ€Π°Ρ‚ΠΊΠ°Ρ инструкция ΠΏΠΎ установкС ΠΈ использованию SVG-спрайтов Π² ΠΏΡ€ΠΎΠ΅ΠΊΡ‚Π΅ Π½Π° React ΠΈ Vite. @@ -38,7 +38,7 @@ export default defineReactSpriteConfig({ По ΡƒΠΌΠΎΠ»Ρ‡Π°Π½ΠΈΡŽ SVG бСрутся ΠΈΠ· `./icons`. ΠžΠ±Ρ‰ΠΈΠ΅ ΠΈΠΊΠΎΠ½ΠΊΠΈ ΠΈΠ· Π΄Ρ€ΡƒΠ³ΠΈΡ… ΠΏΠ°ΠΏΠΎΠΊ ΠΌΠΎΠΆΠ½ΠΎ Π΄ΠΎΠ±Π°Π²ΠΈΡ‚ΡŒ Ρ‡Π΅Ρ€Π΅Π· `inputFiles`: ΠΏΠ°ΠΏΠΊΠ° ΠΈ список ΠΎΠ±ΡŠΠ΅Π΄ΠΈΠ½ΡΡŽΡ‚ΡΡ Π² ΠΎΠ΄ΠΈΠ½ спрайт. -ΠŸΠΎΠ»Π½Ρ‹ΠΉ список ΠΎΠΏΡ†ΠΈΠΉ находится Π² Ρ€Π°Π·Π΄Π΅Π»Π΅ [ΠšΠΎΠ½Ρ„ΠΈΠ³ΡƒΡ€Π°Ρ†ΠΈΡ β†’ React](../../README.md#react). +ΠŸΠΎΠ»Π½Ρ‹ΠΉ список ΠΎΠΏΡ†ΠΈΠΉ находится Π² Ρ€Π°Π·Π΄Π΅Π»Π΅ [ΠšΠΎΠ½Ρ„ΠΈΠ³ΡƒΡ€Π°Ρ†ΠΈΡ β†’ React](../../README_RU.md#react). ## 4. Π”ΠΎΠ±Π°Π²ΡŒΡ‚Π΅ Π³Π΅Π½Π΅Ρ€Π°Ρ†ΠΈΡŽ Π² package.json @@ -83,7 +83,7 @@ export const OpenFolderButton = () => ( // ошибка TypeScript ``` -Π’ΠΈΠΏΡ‹, способы отобраТСния ΠΈ ΡƒΠΏΡ€Π°Π²Π»Π΅Π½ΠΈΠ΅ Ρ†Π²Π΅Ρ‚Π°ΠΌΠΈ описаны Π² [основной Π΄ΠΎΠΊΡƒΠΌΠ΅Π½Ρ‚Π°Ρ†ΠΈΠΈ](../../README.md#способы-отобраТСния). +Π’ΠΈΠΏΡ‹, способы отобраТСния ΠΈ ΡƒΠΏΡ€Π°Π²Π»Π΅Π½ΠΈΠ΅ Ρ†Π²Π΅Ρ‚Π°ΠΌΠΈ описаны Π² [основной Π΄ΠΎΠΊΡƒΠΌΠ΅Π½Ρ‚Π°Ρ†ΠΈΠΈ](../../README_RU.md#способы-отобраТСния). Vite выпустит спрайт ΠΎΡ‚Π΄Π΅Π»ΡŒΠ½Ρ‹ΠΌ Ρ„Π°ΠΉΠ»ΠΎΠΌ Π²ΠΈΠ΄Π° `assets/sprite-.svg`. SVG path-Π΄Π°Π½Π½Ρ‹Π΅ Π½Π΅ ΠΏΠΎΠΏΠ°Π΄ΡƒΡ‚ Π² JavaScript. diff --git a/skills/artifacts/svg-sprites/references/docs/ru/react-webpack.md b/skills/artifacts/svg-sprites/references/docs/ru/react-webpack.md index bd4ccd9..2a3c015 100644 --- a/skills/artifacts/svg-sprites/references/docs/ru/react-webpack.md +++ b/skills/artifacts/svg-sprites/references/docs/ru/react-webpack.md @@ -1,6 +1,6 @@ # React + Webpack 5 -[← Главная](../../README.md) +[← Главная](../../README_RU.md) ΠšΡ€Π°Ρ‚ΠΊΠ°Ρ инструкция ΠΏΠΎ установкС ΠΈ использованию SVG-спрайтов Π² ΠΏΡ€ΠΎΠ΅ΠΊΡ‚Π΅ Π½Π° React ΠΈ Webpack 5. @@ -38,7 +38,7 @@ export default defineReactSpriteConfig({ По ΡƒΠΌΠΎΠ»Ρ‡Π°Π½ΠΈΡŽ SVG бСрутся ΠΈΠ· `./icons`. ΠžΠ±Ρ‰ΠΈΠ΅ ΠΈΠΊΠΎΠ½ΠΊΠΈ ΠΈΠ· Π΄Ρ€ΡƒΠ³ΠΈΡ… ΠΏΠ°ΠΏΠΎΠΊ ΠΌΠΎΠΆΠ½ΠΎ Π΄ΠΎΠ±Π°Π²ΠΈΡ‚ΡŒ Ρ‡Π΅Ρ€Π΅Π· `inputFiles`: ΠΏΠ°ΠΏΠΊΠ° ΠΈ список ΠΎΠ±ΡŠΠ΅Π΄ΠΈΠ½ΡΡŽΡ‚ΡΡ Π² ΠΎΠ΄ΠΈΠ½ спрайт. -ΠŸΠΎΠ»Π½Ρ‹ΠΉ список ΠΎΠΏΡ†ΠΈΠΉ находится Π² Ρ€Π°Π·Π΄Π΅Π»Π΅ [ΠšΠΎΠ½Ρ„ΠΈΠ³ΡƒΡ€Π°Ρ†ΠΈΡ β†’ React](../../README.md#react). +ΠŸΠΎΠ»Π½Ρ‹ΠΉ список ΠΎΠΏΡ†ΠΈΠΉ находится Π² Ρ€Π°Π·Π΄Π΅Π»Π΅ [ΠšΠΎΠ½Ρ„ΠΈΠ³ΡƒΡ€Π°Ρ†ΠΈΡ β†’ React](../../README_RU.md#react). ## 4. Π”ΠΎΠ±Π°Π²ΡŒΡ‚Π΅ Π³Π΅Π½Π΅Ρ€Π°Ρ†ΠΈΡŽ Π² package.json @@ -81,7 +81,7 @@ export const OpenFolderButton = () => ( // ошибка TypeScript ``` -Π’ΠΈΠΏΡ‹, способы отобраТСния ΠΈ ΡƒΠΏΡ€Π°Π²Π»Π΅Π½ΠΈΠ΅ Ρ†Π²Π΅Ρ‚Π°ΠΌΠΈ описаны Π² [основной Π΄ΠΎΠΊΡƒΠΌΠ΅Π½Ρ‚Π°Ρ†ΠΈΠΈ](../../README.md#способы-отобраТСния). +Π’ΠΈΠΏΡ‹, способы отобраТСния ΠΈ ΡƒΠΏΡ€Π°Π²Π»Π΅Π½ΠΈΠ΅ Ρ†Π²Π΅Ρ‚Π°ΠΌΠΈ описаны Π² [основной Π΄ΠΎΠΊΡƒΠΌΠ΅Π½Ρ‚Π°Ρ†ΠΈΠΈ](../../README_RU.md#способы-отобраТСния). Webpack ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Π°Π΅Ρ‚ generated `new URL('./sprite.svg', import.meta.url)` Ρ‡Π΅Ρ€Π΅Π· Asset Modules ΠΈ выпустит ΠΎΡ‚Π΄Π΅Π»ΡŒΠ½Ρ‹ΠΉ SVG asset. diff --git a/skills/svg-sprites/build.mjs b/skills/svg-sprites/build.mjs index 38d05c2..4923526 100644 --- a/skills/svg-sprites/build.mjs +++ b/skills/svg-sprites/build.mjs @@ -13,10 +13,9 @@ import { tmpdir } from 'node:os' import path from 'node:path' import { fileURLToPath } from 'node:url' -import config from './skill.config.mjs' +import configs from './skill.config.mjs' const skillDir = path.dirname(fileURLToPath(import.meta.url)) -const outputDir = path.resolve(skillDir, config.output) const artifactsDir = path.resolve(skillDir, '../artifacts') const isCheck = process.argv.slice(2).includes('--check') @@ -37,7 +36,7 @@ function assertInside(parentDir, childPath) { throw new Error(`Path is outside ${parentDir}: ${childPath}`) } -function validateConfig() { +function validateConfig(config, outputDir) { if (!/^[a-z0-9]+(?:-[a-z0-9]+)*$/.test(config.name)) { throw new Error(`Invalid skill name: ${config.name}`) } @@ -68,7 +67,7 @@ function readRegularFile(filePath) { return readFileSync(filePath, 'utf8') } -function renderSkill() { +function renderSkill(config) { const sourcePath = path.resolve(skillDir, config.source) assertInside(skillDir, sourcePath) const body = readRegularFile(sourcePath).trim() @@ -80,17 +79,17 @@ function renderSkill() { `description: ${JSON.stringify(config.description)}`, '---', '', - '', + ``, '', body, '', ].join('\n') } -function buildSkill(targetDir) { +function buildSkill(config, targetDir) { rmSync(targetDir, { recursive: true, force: true }) mkdirSync(targetDir, { recursive: true }) - writeFileSync(path.join(targetDir, 'SKILL.md'), renderSkill()) + writeFileSync(path.join(targetDir, 'SKILL.md'), renderSkill(config)) for (const reference of config.references) { const sourcePath = path.resolve(skillDir, reference.from) @@ -133,7 +132,7 @@ function validateMarkdown(skillRoot, relativePath) { } } -function validateArtifact(skillRoot) { +function validateArtifact(config, skillRoot) { const expectedFiles = [ 'SKILL.md', ...config.references.map((reference) => reference.to), @@ -174,21 +173,36 @@ function compareArtifacts(expectedDir, actualDir) { } } -validateConfig() - -if (isCheck) { - const temporaryRoot = mkdtempSync(path.join(tmpdir(), 'svg-sprites-skill-')) - try { - const expectedDir = path.join(temporaryRoot, config.name) - buildSkill(expectedDir) - validateArtifact(expectedDir) - compareArtifacts(expectedDir, outputDir) - console.log(`Skill is up to date: ${path.relative(process.cwd(), outputDir)}`) - } finally { - rmSync(temporaryRoot, { recursive: true, force: true }) - } -} else { - buildSkill(outputDir) - validateArtifact(outputDir) - console.log(`Built skill: ${path.relative(process.cwd(), outputDir)}`) +if (!Array.isArray(configs) || configs.length === 0) { + throw new Error('Skill configs must be a non-empty array') +} + +const names = new Set() +const outputs = new Set() + +for (const config of configs) { + const outputDir = path.resolve(skillDir, config.output) + validateConfig(config, outputDir) + + if (names.has(config.name)) throw new Error(`Duplicate skill name: ${config.name}`) + if (outputs.has(outputDir)) throw new Error(`Duplicate skill output: ${config.output}`) + names.add(config.name) + outputs.add(outputDir) + + if (isCheck) { + const temporaryRoot = mkdtempSync(path.join(tmpdir(), `${config.name}-skill-`)) + try { + const expectedDir = path.join(temporaryRoot, config.name) + buildSkill(config, expectedDir) + validateArtifact(config, expectedDir) + compareArtifacts(expectedDir, outputDir) + console.log(`Skill is up to date: ${path.relative(process.cwd(), outputDir)}`) + } finally { + rmSync(temporaryRoot, { recursive: true, force: true }) + } + } else { + buildSkill(config, outputDir) + validateArtifact(config, outputDir) + console.log(`Built skill: ${path.relative(process.cwd(), outputDir)}`) + } } diff --git a/skills/svg-sprites/skill.config.mjs b/skills/svg-sprites/skill.config.mjs index 9bc7577..4de3b7d 100644 --- a/skills/svg-sprites/skill.config.mjs +++ b/skills/svg-sprites/skill.config.mjs @@ -1,16 +1,35 @@ -export default { - name: 'svg-sprites', - description: 'Π˜ΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠΉ ΠΏΡ€ΠΈ настройкС, Π³Π΅Π½Π΅Ρ€Π°Ρ†ΠΈΠΈ, ΠΌΠΈΠ³Ρ€Π°Ρ†ΠΈΠΈ ΠΈΠ»ΠΈ диагностикС SVG-спрайтов Ρ‡Π΅Ρ€Π΅Π· @gromlab/svg-sprites. Π’Ρ€ΠΈΠ³Π³Π΅Ρ€Ρ‹: SVG sprite, SVG-спрайт, svg-sprites, svg-sprite.config.ts, svg-sprites.config.ts, defineReactSpriteConfig, defineNextSpriteConfig, react@vite, react@webpack, next@app, next@pages, inputFiles, SpriteViewer, icon="...", --icon-color-N, generated-ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚ ΠΈΠ»ΠΈ ΠΈΠΊΠΎΠ½ΠΊΠ° Π½Π΅ появилась Π² ΠΏΡ€Π΅Π²ΡŒΡŽ ΠΈ Π°Π²Ρ‚ΠΎΠ΄ΠΎΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ. НЕ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠΉ для favicon, растровых ΠΈΠ·ΠΎΠ±Ρ€Π°ΠΆΠ΅Π½ΠΈΠΉ, icon fonts, Π²Ρ‹Π±ΠΎΡ€Π° Π½Π°Π±ΠΎΡ€Π° ΠΈΠΊΠΎΠ½ΠΎΠΊ ΠΈΠ»ΠΈ inline SVG Π±Π΅Π· спрайтов.', - source: 'src/SKILL.md', - output: '../artifacts/svg-sprites', - references: [ - { from: '../../README.md', to: 'references/README.md' }, - { from: '../../docs/ru/react-vite.md', to: 'references/docs/ru/react-vite.md' }, - { from: '../../docs/ru/react-webpack.md', to: 'references/docs/ru/react-webpack.md' }, - { from: '../../docs/ru/next-app.md', to: 'references/docs/ru/next-app.md' }, - { from: '../../docs/ru/next-pages.md', to: 'references/docs/ru/next-pages.md' }, - { from: '../../docs/ru/legacy.md', to: 'references/docs/ru/legacy.md' }, - { from: '../../docs/ru/migration-1.md', to: 'references/docs/ru/migration-1.md' }, - { from: '../../docs/ru/programmatic-api.md', to: 'references/docs/ru/programmatic-api.md' }, - ], -} +const references = [ + { from: '../../README.md', to: 'references/README.md' }, + { from: '../../README_RU.md', to: 'references/README_RU.md' }, + { from: '../../docs/en/react-vite.md', to: 'references/docs/en/react-vite.md' }, + { from: '../../docs/en/react-webpack.md', to: 'references/docs/en/react-webpack.md' }, + { from: '../../docs/en/next-app.md', to: 'references/docs/en/next-app.md' }, + { from: '../../docs/en/next-pages.md', to: 'references/docs/en/next-pages.md' }, + { from: '../../docs/en/legacy.md', to: 'references/docs/en/legacy.md' }, + { from: '../../docs/en/migration-1.md', to: 'references/docs/en/migration-1.md' }, + { from: '../../docs/en/programmatic-api.md', to: 'references/docs/en/programmatic-api.md' }, + { from: '../../docs/ru/react-vite.md', to: 'references/docs/ru/react-vite.md' }, + { from: '../../docs/ru/react-webpack.md', to: 'references/docs/ru/react-webpack.md' }, + { from: '../../docs/ru/next-app.md', to: 'references/docs/ru/next-app.md' }, + { from: '../../docs/ru/next-pages.md', to: 'references/docs/ru/next-pages.md' }, + { from: '../../docs/ru/legacy.md', to: 'references/docs/ru/legacy.md' }, + { from: '../../docs/ru/migration-1.md', to: 'references/docs/ru/migration-1.md' }, + { from: '../../docs/ru/programmatic-api.md', to: 'references/docs/ru/programmatic-api.md' }, +] + +export default [ + { + name: 'svg-sprites', + description: 'Use when configuring, generating, migrating, or troubleshooting SVG sprites with @gromlab/svg-sprites. Triggers: SVG sprite, svg-sprites, svg-sprite.config.ts, svg-sprites.config.ts, defineReactSpriteConfig, defineNextSpriteConfig, react@vite, react@webpack, next@app, next@pages, inputFiles, SpriteViewer, icon="...", --icon-color-N, generated component, or an icon missing from preview or autocomplete. Do NOT use for favicons, raster images, icon fonts, choosing an icon set, or inline SVG without sprites.', + source: 'src/SKILL.md', + output: '../artifacts/svg-sprites', + references, + }, + { + name: 'svg-sprites-ru', + description: 'Π˜ΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠΉ ΠΏΡ€ΠΈ настройкС, Π³Π΅Π½Π΅Ρ€Π°Ρ†ΠΈΠΈ, ΠΌΠΈΠ³Ρ€Π°Ρ†ΠΈΠΈ ΠΈΠ»ΠΈ диагностикС SVG-спрайтов Ρ‡Π΅Ρ€Π΅Π· @gromlab/svg-sprites. Π’Ρ€ΠΈΠ³Π³Π΅Ρ€Ρ‹: SVG sprite, SVG-спрайт, svg-sprites, svg-sprite.config.ts, svg-sprites.config.ts, defineReactSpriteConfig, defineNextSpriteConfig, react@vite, react@webpack, next@app, next@pages, inputFiles, SpriteViewer, icon="...", --icon-color-N, generated-ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚ ΠΈΠ»ΠΈ ΠΈΠΊΠΎΠ½ΠΊΠ° Π½Π΅ появилась Π² ΠΏΡ€Π΅Π²ΡŒΡŽ ΠΈ Π°Π²Ρ‚ΠΎΠ΄ΠΎΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ. НЕ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠΉ для favicon, растровых ΠΈΠ·ΠΎΠ±Ρ€Π°ΠΆΠ΅Π½ΠΈΠΉ, icon fonts, Π²Ρ‹Π±ΠΎΡ€Π° Π½Π°Π±ΠΎΡ€Π° ΠΈΠΊΠΎΠ½ΠΎΠΊ ΠΈΠ»ΠΈ inline SVG Π±Π΅Π· спрайтов.', + source: 'src/SKILL_RU.md', + output: '../artifacts/svg-sprites-ru', + references, + }, +] diff --git a/skills/svg-sprites/src/SKILL.md b/skills/svg-sprites/src/SKILL.md index 31e0f56..e3e868c 100644 --- a/skills/svg-sprites/src/SKILL.md +++ b/skills/svg-sprites/src/SKILL.md @@ -1,57 +1,57 @@ # SVG Sprites -## НазначСниС +## Purpose -Π˜ΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠΉ этот скил для Ρ€Π°Π±ΠΎΡ‚Ρ‹ с `@gromlab/svg-sprites`: ΠΏΠ΅Ρ€Π²ΠΈΡ‡Π½ΠΎΠΉ настройки, добавлСния ΠΈ ΠΏΠ΅Ρ€Π΅ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Π½ΠΈΡ ΠΈΠΊΠΎΠ½ΠΎΠΊ, Π³Π΅Π½Π΅Ρ€Π°Ρ†ΠΈΠΈ React-ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚ΠΎΠ², ΠΏΠΎΠ΄ΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΡ `SpriteViewer`, ΠΌΠΈΠ³Ρ€Π°Ρ†ΠΈΠΈ legacy-ΠΊΠΎΠ½Ρ„ΠΈΠ³ΡƒΡ€Π°Ρ†ΠΈΠΈ ΠΈ диагностики ошибок. +Use this skill when working with `@gromlab/svg-sprites`: initial setup, adding and reusing icons, generating React components, integrating `SpriteViewer`, migrating legacy configurations, and troubleshooting errors. -НС навязывай ΠΏΡ€ΠΎΠ΅ΠΊΡ‚Ρƒ ΠΊΠΎΠ½ΠΊΡ€Π΅Ρ‚Π½ΡƒΡŽ Π°Ρ€Ρ…ΠΈΡ‚Π΅ΠΊΡ‚ΡƒΡ€Ρƒ ΠΊΠ°Ρ‚Π°Π»ΠΎΠ³ΠΎΠ². Π‘Π½Π°Ρ‡Π°Π»Π° ΠΈΠ·ΡƒΡ‡ΠΈ ΡΡƒΡ‰Π΅ΡΡ‚Π²ΡƒΡŽΡ‰ΠΈΠ΅ `package.json`, ΠΊΠΎΠ½Ρ„ΠΈΠ³ΡƒΡ€Π°Ρ†ΠΈΡŽ спрайта, ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅ΠΌΡ‹ΠΉ Ρ„Ρ€Π΅ΠΉΠΌΠ²ΠΎΡ€ΠΊ, Ρ€ΠΎΡƒΡ‚Π΅Ρ€ ΠΈ сборщик. +Do not impose a specific directory architecture on the project. First inspect the existing `package.json`, sprite configuration, framework, router, and bundler. -## Π Π°Π±ΠΎΡ‡ΠΈΠΉ Π°Π»Π³ΠΎΡ€ΠΈΡ‚ΠΌ +## Workflow -1. ΠžΠΏΡ€Π΅Π΄Π΅Π»ΠΈ ΡΡƒΡ‰Π΅ΡΡ‚Π²ΡƒΡŽΡ‰ΠΈΠΉ Ρ€Π΅ΠΆΠΈΠΌ ΠΈ Π½Π΅ смСшивай Π΅Π³ΠΎ API с Π΄Ρ€ΡƒΠ³ΠΈΠΌ Ρ€Π΅ΠΆΠΈΠΌΠΎΠΌ. -2. Для React Π²Ρ‹Π±Π΅Ρ€ΠΈ `react@vite` ΠΈΠ»ΠΈ `react@webpack` ΠΈ ΠΎΡ‚ΠΊΡ€ΠΎΠΉ ΡΠΎΠΎΡ‚Π²Π΅Ρ‚ΡΡ‚Π²ΡƒΡŽΡ‰ΠΈΠΉ reference. -3. Для Next.js ΠΎΠΏΡ€Π΅Π΄Π΅Π»ΠΈ App Router ΠΈΠ»ΠΈ Pages Router, Π·Π°Ρ‚Π΅ΠΌ Turbopack ΠΈΠ»ΠΈ Webpack, ΠΈ ΠΎΡ‚ΠΊΡ€ΠΎΠΉ ΡΠΎΠΎΡ‚Π²Π΅Ρ‚ΡΡ‚Π²ΡƒΡŽΡ‰ΠΈΠΉ reference. -4. Для ΡΡƒΡ‰Π΅ΡΡ‚Π²ΡƒΡŽΡ‰Π΅Π³ΠΎ `svg-sprites.config.ts` с нСсколькими спрайтами ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠΉ legacy-Π΄ΠΎΠΊΡƒΠΌΠ΅Π½Ρ‚Π°Ρ†ΠΈΡŽ. НС ΠΌΠΈΠ³Ρ€ΠΈΡ€ΡƒΠΉ Ρ‚Π°ΠΊΠΎΠΉ ΠΏΡ€ΠΎΠ΅ΠΊΡ‚ Π±Π΅Π· явного запроса. -5. Π˜Π·ΡƒΡ‡ΠΈ Π»ΠΎΠΊΠ°Π»ΡŒΠ½Ρ‹Π΅ scripts ΠΈ добавляй Π³Π΅Π½Π΅Ρ€Π°Ρ†ΠΈΡŽ ΠΏΠ΅Ρ€Π΅Π΄ `dev`, `build` ΠΈ `typecheck`, Ссли generated-Ρ„Π°ΠΉΠ»Ρ‹ Π½Π΅ хранятся Π² Git. -6. ПослС измСнСния ΠΊΠΎΠ½Ρ„ΠΈΠ³ΡƒΡ€Π°Ρ†ΠΈΠΈ ΠΈΠ»ΠΈ SVG запусти Π³Π΅Π½Π΅Ρ€Π°Ρ†ΠΈΡŽ, Π·Π°Ρ‚Π΅ΠΌ Π΄ΠΎΡΡ‚ΡƒΠΏΠ½ΡƒΡŽ ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΊΡƒ Ρ‚ΠΈΠΏΠΎΠ² ΠΈΠ»ΠΈ сборку ΠΏΡ€ΠΎΠ΅ΠΊΡ‚Π°. +1. Identify the existing mode and do not mix its API with another mode. +2. For React, choose `react@vite` or `react@webpack` and open the corresponding reference. +3. For Next.js, identify the App Router or Pages Router, then Turbopack or Webpack, and open the corresponding reference. +4. For an existing `svg-sprites.config.ts` with multiple sprites, use the legacy documentation. Do not migrate such a project unless explicitly requested. +5. Inspect local scripts and run generation before `dev`, `build`, and `typecheck` when generated files are not committed to Git. +6. After changing a configuration or SVG file, run generation followed by the available type check or project build. -## ΠŸΡ€Π°Π²ΠΈΠ»Π° React ΠΈ Next.js +## React And Next.js Rules -- Π˜ΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠΉ Π»ΠΎΠΊΠ°Π»ΡŒΠ½Ρ‹ΠΉ `svg-sprite.config.ts` ΠΈ подходящий config helper: `defineReactSpriteConfig` ΠΈΠ»ΠΈ `defineNextSpriteConfig`. -- НС Ρ€Π΅Π΄Π°ΠΊΡ‚ΠΈΡ€ΡƒΠΉ `generated/`, `index.ts`, `manifest.ts` ΠΈ созданный Π³Π΅Π½Π΅Ρ€Π°Ρ‚ΠΎΡ€ΠΎΠΌ `.gitignore` Π²Ρ€ΡƒΡ‡Π½ΡƒΡŽ. -- ИмСна исходных SVG становятся допустимыми значСниями prop `icon`; ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠΉ generated-ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚ ΠΈ Π΅Π³ΠΎ ΠΏΡƒΠ±Π»ΠΈΡ‡Π½Ρ‹Π΅ Ρ‚ΠΈΠΏΡ‹ вмСсто deep imports. -- ОбъСдиняй Π»ΠΎΠΊΠ°Π»ΡŒΠ½ΡƒΡŽ ΠΏΠ°ΠΏΠΊΡƒ ΠΈ `inputFiles`, ΠΊΠΎΠ³Π΄Π° общая ΠΈΠΊΠΎΠ½ΠΊΠ° Π½ΡƒΠΆΠ½Π° нСскольким спрайтам. НС создавай ΠΊΠΎΠΏΠΈΠΈ ΠΎΠ΄Π½ΠΎΠ³ΠΎ SVG Π±Π΅Π· нСобходимости. -- Π’ Next.js generated-ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚ ΠΌΠΎΠΆΠ½ΠΎ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ Π² Server Components, SSR ΠΈ SSG. НС добавляй `'use client'` Ρ‚ΠΎΠ»ΡŒΠΊΠΎ Ρ€Π°Π΄ΠΈ ΠΈΠΊΠΎΠ½ΠΊΠΈ. -- Π‘ΠΏΡ€Π°ΠΉΡ‚ Π΄ΠΎΠ»ΠΆΠ΅Π½ ΠΎΡΡ‚Π°Π²Π°Ρ‚ΡŒΡΡ внСшним asset сборщика: Π½Π΅ ΠΏΠ΅Ρ€Π΅Π½ΠΎΡΠΈΡ‚ΡŒ SVG path-Π΄Π°Π½Π½Ρ‹Π΅ Π² JavaScript ΠΈ Π½Π΅ ΠΊΠ»Π°ΡΡ‚ΡŒ generated-Ρ„Π°ΠΉΠ» Π²Ρ€ΡƒΡ‡Π½ΡƒΡŽ Π² `public`. +- Use a local `svg-sprite.config.ts` and the appropriate config helper: `defineReactSpriteConfig` or `defineNextSpriteConfig`. +- Do not manually edit `generated/`, `index.ts`, `manifest.ts`, or the generator-created `.gitignore`. +- Source SVG names become valid values for the `icon` prop; use the generated component and its public types instead of deep imports. +- Combine the local folder with `inputFiles` when multiple sprites need a shared icon. Do not create unnecessary copies of the same SVG. +- In Next.js, generated components work in Server Components, SSR, and SSG. Do not add `'use client'` only for an icon. +- Keep the sprite as an external bundler asset: do not move SVG path data into JavaScript or manually place the generated file in `public`. -## Π¦Π²Π΅Ρ‚Π° ΠΈ трансформации +## Colors And Transformations -- По ΡƒΠΌΠΎΠ»Ρ‡Π°Π½ΠΈΡŽ Π³Π΅Π½Π΅Ρ€Π°Ρ‚ΠΎΡ€ удаляСт `width` ΠΈ `height`, замСняСт ΠΏΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΈΠ²Π°Π΅ΠΌΡ‹Π΅ `fill` ΠΈ `stroke` Π½Π° CSS-ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½Ρ‹Π΅ ΠΈ добавляСт transitions. -- Для ΠΌΠΎΠ½ΠΎΡ…Ρ€ΠΎΠΌΠ½ΠΎΠΉ ΠΈΠΊΠΎΠ½ΠΊΠΈ сначала управляй `color`; для ΠΌΠ½ΠΎΠ³ΠΎΡ†Π²Π΅Ρ‚Π½ΠΎΠΉ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠΉ `--icon-color-N`. -- НС ΠΎΠ±Π΅Ρ‰Π°ΠΉ Π°Π²Ρ‚ΠΎΠΌΠ°Ρ‚ΠΈΡ‡Π΅ΡΠΊΡƒΡŽ Π·Π°ΠΌΠ΅Π½Ρƒ Ρ†Π²Π΅Ρ‚ΠΎΠ² Π²Π½ΡƒΡ‚Ρ€ΠΈ Π²Π½Π΅ΡˆΠ½ΠΈΡ… stylesheets, gradients, patterns, filters ΠΈ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠΉ `url(#...)` Π±Π΅Π· ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΊΠΈ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Π°. -- CSS-ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½Ρ‹Π΅ страницы Ρ€Π°Π±ΠΎΡ‚Π°ΡŽΡ‚ ΠΏΡ€ΠΈ ``, Π½ΠΎ Π½Π΅ ΠΏΡ€ΠΎΠ½ΠΈΠΊΠ°ΡŽΡ‚ Π²Π½ΡƒΡ‚Ρ€ΡŒ `` ΠΈ `background-image`. +- By default, the generator removes `width` and `height`, replaces supported `fill` and `stroke` values with CSS variables, and adds transitions. +- For a monochrome icon, control `color` first; for a multicolor icon, use `--icon-color-N`. +- Do not promise automatic color replacement inside external stylesheets, gradients, patterns, filters, or `url(#...)` values without checking the result. +- Page CSS variables work with ``, but do not propagate into `` or `background-image`. -## ΠŸΡ€Π΅Π²ΡŒΡŽ +## Preview -Для React ΠΈ Next.js ΠΏΠΎΠ΄ΠΊΠ»ΡŽΡ‡Π°ΠΉ `` ΠΎΡ‚Π΄Π΅Π»ΡŒΠ½ΠΎΠΉ debug-страницСй прилоТСния. ΠŸΠ΅Ρ€Π΅Π΄Π°ΠΉ Π΅ΠΌΡƒ manifests ΠΈΠ»ΠΈ lazy loaders спрайтов. Viewer ΠΏΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΈΠ²Π°Π΅Ρ‚ поиск, ΡΠ²Π΅Ρ‚Π»ΡƒΡŽ ΠΈ Ρ‚Ρ‘ΠΌΠ½ΡƒΡŽ Ρ‚Π΅ΠΌΡ‹, настройку Ρ†Π²Π΅Ρ‚ΠΎΠ² ΠΈ ΠΏΡ€ΠΈΠΌΠ΅Ρ€Ρ‹ React, SVG, IMG ΠΈ CSS. +For React and Next.js, add `` as a separate debug page in the application. Pass sprite manifests or lazy loaders to it. The Viewer supports search, light and dark themes, color controls, and React, SVG, IMG, and CSS examples. -`SpriteViewer` являСтся клиСнтским debug-инструмСнтом ΠΈ импортируСтся ΠΈΠ· `@gromlab/svg-sprites/react`; production-ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Ρ‹ ΠΈΠΊΠΎΠ½ΠΎΠΊ ΠΎΡ‚ Π½Π΅Π³ΠΎ Π½Π΅ зависят. +`SpriteViewer` is a client-side debug tool imported from `@gromlab/svg-sprites/react`; production icon components do not depend on it. -## Диагностика +## Troubleshooting -- Если имя ΠΈΠΊΠΎΠ½ΠΊΠΈ отсутствуСт Π² Π°Π²Ρ‚ΠΎΠ΄ΠΎΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ, ΠΏΡ€ΠΎΠ²Π΅Ρ€ΡŒ Π²Ρ…ΠΎΠ΄Π½ΡƒΡŽ ΠΏΠ°ΠΏΠΊΡƒ ΠΈ `inputFiles`, Π·Π°Ρ‚Π΅ΠΌ пСрСзапусти Π³Π΅Π½Π΅Ρ€Π°Ρ†ΠΈΡŽ. -- Если Π΄Π²Π° Ρ„Π°ΠΉΠ»Π° ΠΈΠΌΠ΅ΡŽΡ‚ ΠΎΠ΄ΠΈΠ½Π°ΠΊΠΎΠ²ΠΎΠ΅ имя ΠΈΠΊΠΎΠ½ΠΊΠΈ, устрани ΠΊΠΎΠ½Ρ„Π»ΠΈΠΊΡ‚ вмСсто Π²Ρ‹Π±ΠΎΡ€Π° ΠΎΠ΄Π½ΠΎΠ³ΠΎ Ρ„Π°ΠΉΠ»Π° нСявно. -- Если Π³Π΅Π½Π΅Ρ€Π°Ρ‚ΠΎΡ€ отказываСтся ΠΏΠ΅Ρ€Π΅Π·Π°ΠΏΠΈΡΡ‹Π²Π°Ρ‚ΡŒ Ρ„Π°ΠΉΠ», Π½Π΅ удаляй Π·Π°Ρ‰ΠΈΡ‚Π½Ρ‹ΠΉ marker ΠΈ Π½Π΅ ΠΎΠ±Ρ…ΠΎΠ΄ΠΈ writer: пСрСнСси ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»ΡŒΡΠΊΠΈΠΉ Ρ„Π°ΠΉΠ» ΠΈΠ»ΠΈ Π²Ρ‹Π±Π΅Ρ€ΠΈ Π΄Ρ€ΡƒΠ³ΠΎΠΉ ΠΊΠ°Ρ‚Π°Π»ΠΎΠ³ спрайта. -- Если asset Π½Π΅ загруТаСтся, сначала ΠΏΡ€ΠΎΠ²Π΅Ρ€ΡŒ соотвСтствиС CLI mode Ρ€Π΅Π°Π»ΡŒΠ½ΠΎΠΌΡƒ сборщику ΠΏΡ€ΠΎΠ΅ΠΊΡ‚Π° ΠΈ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΡƒ generated SVG Π΅Π³ΠΎ asset pipeline. -- Если ΠΏΡ€ΠΎΠ΅ΠΊΡ‚ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ старый API, ΡΠ²Π΅Ρ€ΡŒ ΡƒΡΡ‚Π°Π½ΠΎΠ²Π»Π΅Π½Π½ΡƒΡŽ Π²Π΅Ρ€ΡΠΈΡŽ ΠΏΠ°ΠΊΠ΅Ρ‚Π° ΠΈ legacy reference ΠΏΠ΅Ρ€Π΅Π΄ измСнСниями. +- If an icon name is missing from autocomplete, check the input folder and `inputFiles`, then rerun generation. +- If two files have the same icon name, resolve the conflict instead of implicitly selecting one file. +- If the generator refuses to overwrite a file, do not remove the protection marker or bypass the writer: move the user file or choose another sprite directory. +- If an asset fails to load, first confirm that the CLI mode matches the project's actual bundler and that its asset pipeline handles the generated SVG. +- If the project uses the old API, check the installed package version and the legacy reference before making changes. ## References -- [Основная докумСнтация ΠΈ API](./references/README.md) -- [React + Vite](./references/docs/ru/react-vite.md) -- [React + Webpack 5](./references/docs/ru/react-webpack.md) -- [Next.js App Router](./references/docs/ru/next-app.md) -- [Next.js Pages Router](./references/docs/ru/next-pages.md) -- [Legacy mode](./references/docs/ru/legacy.md) -- [ΠœΠΈΠ³Ρ€Π°Ρ†ΠΈΡ с 0.1.x](./references/docs/ru/migration-1.md) -- [ΠŸΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠ½Ρ‹ΠΉ API](./references/docs/ru/programmatic-api.md) +- [Main documentation and API](./references/README.md) +- [React + Vite](./references/docs/en/react-vite.md) +- [React + Webpack 5](./references/docs/en/react-webpack.md) +- [Next.js App Router](./references/docs/en/next-app.md) +- [Next.js Pages Router](./references/docs/en/next-pages.md) +- [Legacy mode](./references/docs/en/legacy.md) +- [Migrating from 0.1.x](./references/docs/en/migration-1.md) +- [Programmatic API](./references/docs/en/programmatic-api.md) diff --git a/skills/svg-sprites/src/SKILL_RU.md b/skills/svg-sprites/src/SKILL_RU.md new file mode 100644 index 0000000..e1a1a78 --- /dev/null +++ b/skills/svg-sprites/src/SKILL_RU.md @@ -0,0 +1,57 @@ +# SVG Sprites + +## НазначСниС + +Π˜ΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠΉ этот скил для Ρ€Π°Π±ΠΎΡ‚Ρ‹ с `@gromlab/svg-sprites`: ΠΏΠ΅Ρ€Π²ΠΈΡ‡Π½ΠΎΠΉ настройки, добавлСния ΠΈ ΠΏΠ΅Ρ€Π΅ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Π½ΠΈΡ ΠΈΠΊΠΎΠ½ΠΎΠΊ, Π³Π΅Π½Π΅Ρ€Π°Ρ†ΠΈΠΈ React-ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚ΠΎΠ², ΠΏΠΎΠ΄ΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΡ `SpriteViewer`, ΠΌΠΈΠ³Ρ€Π°Ρ†ΠΈΠΈ legacy-ΠΊΠΎΠ½Ρ„ΠΈΠ³ΡƒΡ€Π°Ρ†ΠΈΠΈ ΠΈ диагностики ошибок. + +НС навязывай ΠΏΡ€ΠΎΠ΅ΠΊΡ‚Ρƒ ΠΊΠΎΠ½ΠΊΡ€Π΅Ρ‚Π½ΡƒΡŽ Π°Ρ€Ρ…ΠΈΡ‚Π΅ΠΊΡ‚ΡƒΡ€Ρƒ ΠΊΠ°Ρ‚Π°Π»ΠΎΠ³ΠΎΠ². Π‘Π½Π°Ρ‡Π°Π»Π° ΠΈΠ·ΡƒΡ‡ΠΈ ΡΡƒΡ‰Π΅ΡΡ‚Π²ΡƒΡŽΡ‰ΠΈΠ΅ `package.json`, ΠΊΠΎΠ½Ρ„ΠΈΠ³ΡƒΡ€Π°Ρ†ΠΈΡŽ спрайта, ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅ΠΌΡ‹ΠΉ Ρ„Ρ€Π΅ΠΉΠΌΠ²ΠΎΡ€ΠΊ, Ρ€ΠΎΡƒΡ‚Π΅Ρ€ ΠΈ сборщик. + +## Π Π°Π±ΠΎΡ‡ΠΈΠΉ Π°Π»Π³ΠΎΡ€ΠΈΡ‚ΠΌ + +1. ΠžΠΏΡ€Π΅Π΄Π΅Π»ΠΈ ΡΡƒΡ‰Π΅ΡΡ‚Π²ΡƒΡŽΡ‰ΠΈΠΉ Ρ€Π΅ΠΆΠΈΠΌ ΠΈ Π½Π΅ смСшивай Π΅Π³ΠΎ API с Π΄Ρ€ΡƒΠ³ΠΈΠΌ Ρ€Π΅ΠΆΠΈΠΌΠΎΠΌ. +2. Для React Π²Ρ‹Π±Π΅Ρ€ΠΈ `react@vite` ΠΈΠ»ΠΈ `react@webpack` ΠΈ ΠΎΡ‚ΠΊΡ€ΠΎΠΉ ΡΠΎΠΎΡ‚Π²Π΅Ρ‚ΡΡ‚Π²ΡƒΡŽΡ‰ΠΈΠΉ reference. +3. Для Next.js ΠΎΠΏΡ€Π΅Π΄Π΅Π»ΠΈ App Router ΠΈΠ»ΠΈ Pages Router, Π·Π°Ρ‚Π΅ΠΌ Turbopack ΠΈΠ»ΠΈ Webpack, ΠΈ ΠΎΡ‚ΠΊΡ€ΠΎΠΉ ΡΠΎΠΎΡ‚Π²Π΅Ρ‚ΡΡ‚Π²ΡƒΡŽΡ‰ΠΈΠΉ reference. +4. Для ΡΡƒΡ‰Π΅ΡΡ‚Π²ΡƒΡŽΡ‰Π΅Π³ΠΎ `svg-sprites.config.ts` с нСсколькими спрайтами ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠΉ legacy-Π΄ΠΎΠΊΡƒΠΌΠ΅Π½Ρ‚Π°Ρ†ΠΈΡŽ. НС ΠΌΠΈΠ³Ρ€ΠΈΡ€ΡƒΠΉ Ρ‚Π°ΠΊΠΎΠΉ ΠΏΡ€ΠΎΠ΅ΠΊΡ‚ Π±Π΅Π· явного запроса. +5. Π˜Π·ΡƒΡ‡ΠΈ Π»ΠΎΠΊΠ°Π»ΡŒΠ½Ρ‹Π΅ scripts ΠΈ добавляй Π³Π΅Π½Π΅Ρ€Π°Ρ†ΠΈΡŽ ΠΏΠ΅Ρ€Π΅Π΄ `dev`, `build` ΠΈ `typecheck`, Ссли generated-Ρ„Π°ΠΉΠ»Ρ‹ Π½Π΅ хранятся Π² Git. +6. ПослС измСнСния ΠΊΠΎΠ½Ρ„ΠΈΠ³ΡƒΡ€Π°Ρ†ΠΈΠΈ ΠΈΠ»ΠΈ SVG запусти Π³Π΅Π½Π΅Ρ€Π°Ρ†ΠΈΡŽ, Π·Π°Ρ‚Π΅ΠΌ Π΄ΠΎΡΡ‚ΡƒΠΏΠ½ΡƒΡŽ ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΊΡƒ Ρ‚ΠΈΠΏΠΎΠ² ΠΈΠ»ΠΈ сборку ΠΏΡ€ΠΎΠ΅ΠΊΡ‚Π°. + +## ΠŸΡ€Π°Π²ΠΈΠ»Π° React ΠΈ Next.js + +- Π˜ΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠΉ Π»ΠΎΠΊΠ°Π»ΡŒΠ½Ρ‹ΠΉ `svg-sprite.config.ts` ΠΈ подходящий config helper: `defineReactSpriteConfig` ΠΈΠ»ΠΈ `defineNextSpriteConfig`. +- НС Ρ€Π΅Π΄Π°ΠΊΡ‚ΠΈΡ€ΡƒΠΉ `generated/`, `index.ts`, `manifest.ts` ΠΈ созданный Π³Π΅Π½Π΅Ρ€Π°Ρ‚ΠΎΡ€ΠΎΠΌ `.gitignore` Π²Ρ€ΡƒΡ‡Π½ΡƒΡŽ. +- ИмСна исходных SVG становятся допустимыми значСниями prop `icon`; ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠΉ generated-ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚ ΠΈ Π΅Π³ΠΎ ΠΏΡƒΠ±Π»ΠΈΡ‡Π½Ρ‹Π΅ Ρ‚ΠΈΠΏΡ‹ вмСсто deep imports. +- ОбъСдиняй Π»ΠΎΠΊΠ°Π»ΡŒΠ½ΡƒΡŽ ΠΏΠ°ΠΏΠΊΡƒ ΠΈ `inputFiles`, ΠΊΠΎΠ³Π΄Π° общая ΠΈΠΊΠΎΠ½ΠΊΠ° Π½ΡƒΠΆΠ½Π° нСскольким спрайтам. НС создавай ΠΊΠΎΠΏΠΈΠΈ ΠΎΠ΄Π½ΠΎΠ³ΠΎ SVG Π±Π΅Π· нСобходимости. +- Π’ Next.js generated-ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚ ΠΌΠΎΠΆΠ½ΠΎ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ Π² Server Components, SSR ΠΈ SSG. НС добавляй `'use client'` Ρ‚ΠΎΠ»ΡŒΠΊΠΎ Ρ€Π°Π΄ΠΈ ΠΈΠΊΠΎΠ½ΠΊΠΈ. +- Π‘ΠΏΡ€Π°ΠΉΡ‚ Π΄ΠΎΠ»ΠΆΠ΅Π½ ΠΎΡΡ‚Π°Π²Π°Ρ‚ΡŒΡΡ внСшним asset сборщика: Π½Π΅ ΠΏΠ΅Ρ€Π΅Π½ΠΎΡΠΈΡ‚ΡŒ SVG path-Π΄Π°Π½Π½Ρ‹Π΅ Π² JavaScript ΠΈ Π½Π΅ ΠΊΠ»Π°ΡΡ‚ΡŒ generated-Ρ„Π°ΠΉΠ» Π²Ρ€ΡƒΡ‡Π½ΡƒΡŽ Π² `public`. + +## Π¦Π²Π΅Ρ‚Π° ΠΈ трансформации + +- По ΡƒΠΌΠΎΠ»Ρ‡Π°Π½ΠΈΡŽ Π³Π΅Π½Π΅Ρ€Π°Ρ‚ΠΎΡ€ удаляСт `width` ΠΈ `height`, замСняСт ΠΏΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΈΠ²Π°Π΅ΠΌΡ‹Π΅ `fill` ΠΈ `stroke` Π½Π° CSS-ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½Ρ‹Π΅ ΠΈ добавляСт transitions. +- Для ΠΌΠΎΠ½ΠΎΡ…Ρ€ΠΎΠΌΠ½ΠΎΠΉ ΠΈΠΊΠΎΠ½ΠΊΠΈ сначала управляй `color`; для ΠΌΠ½ΠΎΠ³ΠΎΡ†Π²Π΅Ρ‚Π½ΠΎΠΉ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠΉ `--icon-color-N`. +- НС ΠΎΠ±Π΅Ρ‰Π°ΠΉ Π°Π²Ρ‚ΠΎΠΌΠ°Ρ‚ΠΈΡ‡Π΅ΡΠΊΡƒΡŽ Π·Π°ΠΌΠ΅Π½Ρƒ Ρ†Π²Π΅Ρ‚ΠΎΠ² Π²Π½ΡƒΡ‚Ρ€ΠΈ Π²Π½Π΅ΡˆΠ½ΠΈΡ… stylesheets, gradients, patterns, filters ΠΈ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠΉ `url(#...)` Π±Π΅Π· ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΊΠΈ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Π°. +- CSS-ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½Ρ‹Π΅ страницы Ρ€Π°Π±ΠΎΡ‚Π°ΡŽΡ‚ ΠΏΡ€ΠΈ ``, Π½ΠΎ Π½Π΅ ΠΏΡ€ΠΎΠ½ΠΈΠΊΠ°ΡŽΡ‚ Π²Π½ΡƒΡ‚Ρ€ΡŒ `` ΠΈ `background-image`. + +## ΠŸΡ€Π΅Π²ΡŒΡŽ + +Для React ΠΈ Next.js ΠΏΠΎΠ΄ΠΊΠ»ΡŽΡ‡Π°ΠΉ `` ΠΎΡ‚Π΄Π΅Π»ΡŒΠ½ΠΎΠΉ debug-страницСй прилоТСния. ΠŸΠ΅Ρ€Π΅Π΄Π°ΠΉ Π΅ΠΌΡƒ manifests ΠΈΠ»ΠΈ lazy loaders спрайтов. Viewer ΠΏΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΈΠ²Π°Π΅Ρ‚ поиск, ΡΠ²Π΅Ρ‚Π»ΡƒΡŽ ΠΈ Ρ‚Ρ‘ΠΌΠ½ΡƒΡŽ Ρ‚Π΅ΠΌΡ‹, настройку Ρ†Π²Π΅Ρ‚ΠΎΠ² ΠΈ ΠΏΡ€ΠΈΠΌΠ΅Ρ€Ρ‹ React, SVG, IMG ΠΈ CSS. + +`SpriteViewer` являСтся клиСнтским debug-инструмСнтом ΠΈ импортируСтся ΠΈΠ· `@gromlab/svg-sprites/react`; production-ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Ρ‹ ΠΈΠΊΠΎΠ½ΠΎΠΊ ΠΎΡ‚ Π½Π΅Π³ΠΎ Π½Π΅ зависят. + +## Диагностика + +- Если имя ΠΈΠΊΠΎΠ½ΠΊΠΈ отсутствуСт Π² Π°Π²Ρ‚ΠΎΠ΄ΠΎΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ, ΠΏΡ€ΠΎΠ²Π΅Ρ€ΡŒ Π²Ρ…ΠΎΠ΄Π½ΡƒΡŽ ΠΏΠ°ΠΏΠΊΡƒ ΠΈ `inputFiles`, Π·Π°Ρ‚Π΅ΠΌ пСрСзапусти Π³Π΅Π½Π΅Ρ€Π°Ρ†ΠΈΡŽ. +- Если Π΄Π²Π° Ρ„Π°ΠΉΠ»Π° ΠΈΠΌΠ΅ΡŽΡ‚ ΠΎΠ΄ΠΈΠ½Π°ΠΊΠΎΠ²ΠΎΠ΅ имя ΠΈΠΊΠΎΠ½ΠΊΠΈ, устрани ΠΊΠΎΠ½Ρ„Π»ΠΈΠΊΡ‚ вмСсто Π²Ρ‹Π±ΠΎΡ€Π° ΠΎΠ΄Π½ΠΎΠ³ΠΎ Ρ„Π°ΠΉΠ»Π° нСявно. +- Если Π³Π΅Π½Π΅Ρ€Π°Ρ‚ΠΎΡ€ отказываСтся ΠΏΠ΅Ρ€Π΅Π·Π°ΠΏΠΈΡΡ‹Π²Π°Ρ‚ΡŒ Ρ„Π°ΠΉΠ», Π½Π΅ удаляй Π·Π°Ρ‰ΠΈΡ‚Π½Ρ‹ΠΉ marker ΠΈ Π½Π΅ ΠΎΠ±Ρ…ΠΎΠ΄ΠΈ writer: пСрСнСси ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»ΡŒΡΠΊΠΈΠΉ Ρ„Π°ΠΉΠ» ΠΈΠ»ΠΈ Π²Ρ‹Π±Π΅Ρ€ΠΈ Π΄Ρ€ΡƒΠ³ΠΎΠΉ ΠΊΠ°Ρ‚Π°Π»ΠΎΠ³ спрайта. +- Если asset Π½Π΅ загруТаСтся, сначала ΠΏΡ€ΠΎΠ²Π΅Ρ€ΡŒ соотвСтствиС CLI mode Ρ€Π΅Π°Π»ΡŒΠ½ΠΎΠΌΡƒ сборщику ΠΏΡ€ΠΎΠ΅ΠΊΡ‚Π° ΠΈ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΡƒ generated SVG Π΅Π³ΠΎ asset pipeline. +- Если ΠΏΡ€ΠΎΠ΅ΠΊΡ‚ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ старый API, ΡΠ²Π΅Ρ€ΡŒ ΡƒΡΡ‚Π°Π½ΠΎΠ²Π»Π΅Π½Π½ΡƒΡŽ Π²Π΅Ρ€ΡΠΈΡŽ ΠΏΠ°ΠΊΠ΅Ρ‚Π° ΠΈ legacy reference ΠΏΠ΅Ρ€Π΅Π΄ измСнСниями. + +## References + +- [Основная докумСнтация ΠΈ API](./references/README_RU.md) +- [React + Vite](./references/docs/ru/react-vite.md) +- [React + Webpack 5](./references/docs/ru/react-webpack.md) +- [Next.js App Router](./references/docs/ru/next-app.md) +- [Next.js Pages Router](./references/docs/ru/next-pages.md) +- [Legacy mode](./references/docs/ru/legacy.md) +- [ΠœΠΈΠ³Ρ€Π°Ρ†ΠΈΡ с 0.1.x](./references/docs/ru/migration-1.md) +- [ΠŸΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠ½Ρ‹ΠΉ API](./references/docs/ru/programmatic-api.md)