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

<Meta title='@dxtmisha/vi/functional-basic/Classes/Icons - Quản lý Biểu tượng'/>

# Lớp Icons

Một lớp tĩnh để quản lý registry biểu tượng (icon) của ứng dụng. Cung cấp cơ chế đăng ký, tải chậm (lazy loading) và truy xuất SVG icon. Các icon được lưu trữ trong đối tượng `window` toàn cục để có thể truy cập từ nhiều phiên bản của thư viện.

## Tính năng chính

- **Registry toàn cục** — Sử dụng `window.__UI_ICON` để lưu trữ icon, đảm bảo registry duy nhất dù có nhiều phiên bản.
- **Tải chậm (Lazy Loading)** — Phương thức `addLoad` đánh dấu icon là "đang tải"; `get` sẽ chờ cho đến khi nó xuất hiện.
- **Kiểu linh hoạt** — Một icon có thể là chuỗi, `Promise`, hoặc hàm trả về `Promise`.
- **URL tự động** — Icon có tiền tố `@` được chuyển thành URL đầy đủ dựa trên `url` cơ sở.

## Khởi tạo

Lớp này là tĩnh và không yêu cầu khởi tạo đối tượng. URL cơ sở được cấu hình qua `setUrl`.

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

// Thay đổi đường dẫn cơ sở đến icon
Icons.setUrl('/assets/svg/')
```

## Phương thức

### Đăng ký icon

- `add(index: string, file: IconsItem): void` — Đăng ký icon theo tên. `file` có thể là chuỗi đường dẫn, `Promise`, hoặc hàm factory.
- `addLoad(index: string): void` — Đánh dấu icon là "đang tải" (marker `--LOAD--`). `get` sẽ chờ cho đến khi icon có mặt.
- `addGlobal(index: string, file: string): void` — Đăng ký icon với URL toàn cục (URL cơ sở + `file`).
- `addByList(list: Record<string, IconsItem>): void` — Đăng ký hàng loạt icon từ một đối tượng.

### Truy xuất icon

- `async get(index: string, url?: string, wait?: number): Promise<string>` — Trả về nội dung hoặc đường dẫn của icon theo tên. Nếu icon đang "tải", sẽ chờ cho đến khi xuất hiện (mặc định 3 phút).
- `is(index: string): boolean` — Kiểm tra xem icon đã được đăng ký chưa.
- `getNameList(): string[]` — Trả về danh sách tên của tất cả icon đã đăng ký.
- `getUrlGlobal(): string` — Trả về URL cơ sở hiện tại của icon.

### Cấu hình

- `setUrl(url: string): void` — Thay đổi đường dẫn cơ sở để lưu trữ icon.
- `setConfig(config: IconsConfig): void` — Cập nhật cấu hình biểu tượng (URL và/hoặc danh sách biểu tượng).

## Hệ thống tải

Lớp `Icons` hỗ trợ cơ chế chờ bất đồng bộ. Điều này cho phép bạn yêu cầu một biểu tượng trước khi nó thực sự được tải hoặc đăng ký trong hệ thống.

1.  **Đăng ký chờ**: Sử dụng phương thức `addLoad(name)`, một biểu tượng được đánh dấu bằng ký hiệu đặc biệt `--LOAD--`. Điều này thông báo cho hệ thống biết rằng biểu tượng sẽ có sẵn sau đó.
2.  **Quá trình chờ**: Nếu gọi `get(name)` cho một biểu tượng đang ở trạng thái tải, phương thức sẽ không trả về lỗi mà thay vào đó sẽ chuyển sang chế độ chờ. Nó sẽ kiểm tra registry sau mỗi 320 ms.
3.  **Hoàn tất**: Ngay khi biểu tượng được thêm qua `add(name, ...)`, tất cả các lệnh gọi `get` đang chờ sẽ tự động hoàn tất và trả về nội dung của biểu tượng đó.

Cơ chế này rất quan trọng đối với các hệ thống phân tán, nơi các thành phần có thể yêu cầu tài nguyên trước khi cơ sở dữ liệu truyền thông hoàn tất quá trình khởi tạo.

## Các loại dữ liệu (Types)

### `IconsItem`
Định nghĩa của một biểu tượng (icon). Có thể là:
- `string` — Nội dung SVG thô hoặc đường dẫn đến tệp SVG.
- `Promise<string>` — Một promise giải quyết thành nội dung SVG (hữu ích cho việc import động).
- `() => Promise<string>` — Một hàm factory trả về một promise (hữu ích cho việc tải lười khi cần thiết).

### `IconsConfig`
Đối tượng cấu hình cho phương thức `setConfig`:
- `url?: string` — URL cơ sở để lưu trữ biểu tượng.
- `list?: Record<string, IconsItem>` — Danh sách các biểu tượng cần đăng ký.

## Ví dụ sử dụng

### Đăng ký và sử dụng biểu tượng
```javascript
import { Icons } from '@dxtmisha/functional-basic'

// Đăng ký dưới dạng chuỗi
Icons.add('arrow', '<svg>...</svg>')

// Đăng ký qua Promise (import động)
Icons.add('user', import('./icons/user.svg'))

// Đăng ký qua hàm factory
Icons.add('star', () => import('./icons/star.svg'))

// Lấy dữ liệu
const svgContent = await Icons.get('arrow')

// Cấu hình hàng loạt qua setConfig
Icons.setConfig({
  url: '/custom-icons/',
  list: {
    check: '<svg>...</svg>',
    error: () => import('./icons/error.svg')
  }
})
```

### Đăng ký hàng loạt
```javascript
Icons.addByList({
  home: '<svg>...</svg>',
  search: () => import('./icons/search.svg'),
  bell: import('./icons/bell.svg')
})
```

### Tải lười (Lazy Loading)
```javascript
// Đánh dấu là đang tải
Icons.addLoad('dynamic-icon')

// Tải và đăng ký sau đó
fetch('/api/icons/dynamic').then(res => res.text()).then(svg => {
  Icons.add('dynamic-icon', svg)
})

// get() sẽ đợi cho đến khi biểu tượng xuất hiện trong sổ đăng ký
const svg = await Icons.get('dynamic-icon')
```
