import {Meta} from '@storybook/addon-docs/blocks'

<Meta title='@dxtmisha/ru/functional-basic/Classes/Icons - Управление Иконками'/>

# Класс Icons

Статический класс для управления реестром иконок приложения. Предоставляет механизм регистрации, ленивой загрузки и получения SVG-иконок. Иконки хранятся в глобальном объекте `window`, чтобы быть доступными между разными экземплярами библиотеки.

## Ключевые особенности

- **Глобальный реестр** — Использует `window.__UI_ICON` для хранения иконок, обеспечивая единый реестр даже при нескольких экземплярах.
- **Ленивая загрузка** — Метод `addLoad` регистрирует иконку как «загружается»; `get` будет ждать ее появления.
- **Гибкие типы** — Иконка может быть строкой, `Promise` или функцией, возвращающей `Promise`.
- **Автоматический URL** — Иконки с префиксом `@` разворачиваются в полный URL на основе базового `url`.

## Инициализация

Класс является статическим и не требует создания экземпляра. Базовый URL настраивается через `setUrl`.

```javascript
import { Icons } from '@dxtmisha/functional-basic'

// Изменить базовый путь к иконкам
Icons.setUrl('/assets/svg/')
```

## Методы

### Регистрация иконок

- `add(index: string, file: IconsItem): void` — Регистрирует иконку по имени. `file` может быть строкой-путем, `Promise` или фабричной функцией.
- `addLoad(index: string): void` — Помечает иконку как «в процессе загрузки» (маркер `--LOAD--`). `get` будет ожидать её появления.
- `addGlobal(index: string, file: string): void` — Регистрирует иконку с глобальным URL (базовый URL + `file`).
- `addByList(list: Record<string, IconsItem>): void` — Массово регистрирует иконки из объекта.

### Получение иконок

- `async get(index: string, url?: string, wait?: number): Promise<string>` — Возвращает содержимое или путь к иконке по имени. Если иконка помечена как «загружается», ожидает её появления (с таймаутом по умолчанию 3 мин).
- `is(index: string): boolean` — Проверяет, зарегистрирована ли иконка.
- `getNameList(): string[]` — Возвращает список имен всех зарегистрированных иконок.
- `getUrlGlobal(): string` — Возвращает текущий базовый URL иконок.

### Конфигурация

- `setUrl(url: string): void` — Изменяет базовый путь для хранения иконок.
- `setConfig(config: IconsConfig): void` — Обновляет конфигурацию иконок (URL и/или список иконок).

## Система загрузки

Класс `Icons` поддерживает механизм асинхронного ожидания. Это позволяет запрашивать иконку до того, как она будет фактически загружена или зарегистрирована в системе.

1.  **Регистрация ожидания**: С помощью метода `addLoad(name)` иконка помечается специальным маркером `--LOAD--`. Это указывает системе, что иконка появится позже.
2.  **Процесс ожидания**: Если вызвать `get(name)` для иконки, которая находится в состоянии загрузки, метод не вернет ошибку, а перейдет в режим ожидания. Он будет проверять реестр каждые 320 мс.
3.  **Завершение загрузки**: Как только иконка будет добавлена через `add(name, ...)`, все ожидающие вызовы `get` автоматически разрешатся и вернут содержимое этой иконки.

Этот механизм критически важен для распределенных систем, где компоненты могут запрашивать ресурсы до завершения инициализации медиа-базы.

## Типы

### `IconsItem`
Определение иконки. Может быть:
- `string` — Прямой контент SVG или путь к файлу SVG.
- `Promise<string>` — Promise, который разрешается в контент SVG (полезно для динамических импортов).
- `() => Promise<string>` — Фабричная функция, возвращающая Promise (полезно для ленивой загрузки по требованию).

### `IconsConfig`
Объект конфигурации для метода `setConfig`:
- `url?: string` — Базовый URL для хранения иконок.
- `list?: Record<string, IconsItem>` — Список иконок для регистрации.

## Пример использования

### Регистрация и использование иконок
```javascript
import { Icons } from '@dxtmisha/functional-basic'

// Регистрация в виде строки
Icons.add('arrow', '<svg>...</svg>')

// Регистрация через Promise (динамический импорт)
Icons.add('user', import('./icons/user.svg'))

// Регистрация через фабричную функцию
Icons.add('star', () => import('./icons/star.svg'))

// Получение
const svgContent = await Icons.get('arrow')

// Групповая конфигурация через setConfig
Icons.setConfig({
  url: '/custom-icons/',
  list: {
    check: '<svg>...</svg>',
    error: () => import('./icons/error.svg')
  }
})
```

### Массовая регистрация
```javascript
Icons.addByList({
  home: '<svg>...</svg>',
  search: () => import('./icons/search.svg'),
  bell: import('./icons/bell.svg')
})
```

### Отложенная загрузка
```javascript
// Пометка как загружаемой
Icons.addLoad('dynamic-icon')

// Загрузка и регистрация позже
fetch('/api/icons/dynamic').then(res => res.text()).then(svg => {
  Icons.add('dynamic-icon', svg)
})

// get() будет ждать, пока иконка появится в реестре
const svg = await Icons.get('dynamic-icon')
```
