npm package: @libs-ui/services-notification
Description: Service toast notification cho Angular — hỗ trợ 4 kiểu (success, error, info, warn), queue tối đa 5, tự động dịch qua ngx-translate, và bridge sang micro-frontend qua iFrame messaging.
Latest version: 0.2.356-23

# Notification Service

Service toast notification cho Angular — hỗ trợ 4 kiểu (success, error, info, warn), queue tối đa 5, tự động dịch qua ngx-translate, và bridge sang micro-frontend qua iFrame messaging.

## Tính năng

- ✅ 4 kiểu toast: `success` (xanh), `error` (đỏ), `info` (xanh dương), `warn` (vàng)
- ✅ Queue tối đa 5 — FIFO auto-remove khi overflow
- ✅ Tích hợp ngx-translate — truyền key hoặc text đều được
- ✅ interpolateParams với XSS-safe escaping tự động
- ✅ Callback onClick / onMouseenter
- ✅ Tùy chỉnh timeRemove, positionRight
- ✅ iFrame bridge cho micro-frontend architecture
- ✅ Browser native Notification API (systemSpawnNotification)

## Cài đặt

```bash
npm install @libs-ui/services-notification
```

## Import

```typescript
import { LibsUiNotificationService } from '@libs-ui/services-notification';
```

## Quick Start

```typescript
@Component({ ... })
export class ExampleComponent {
  private notif = inject(LibsUiNotificationService);

  onSave()   { this.notif.showCompTypeTextSuccess('Lưu thành công!'); }
  onError()  { this.notif.showCompTypeTextError('Có lỗi xảy ra.'); }
  onInfo()   { this.notif.showCompTypeTextInfo('Phiên làm việc sắp hết hạn.'); }
  onWarn()   { this.notif.showCompTypeTextWarning('Dung lượng gần đầy.'); }
}
```

## Đầy đủ Config

```typescript
this.notif.showCompTypeTextSuccess('ACTION_SUCCESS', {
  title: 'Thành công',
  timeRemove: 5000, // ms (default: 3000)
  positionRight: 24, // px từ phải màn hình (default: 12)
  eventName: 'click', // 'click' | 'mouseenter'
  callback: () => this.router.navigate(['/home']),
  interpolateParams: {
    // ngx-translate params — tự động escape HTML
    name: 'Nguyễn Văn A',
  },
});
```

## ngx-translate Integration

```typescript
// Truyền translation key
this.notif.showCompTypeTextSuccess('notifications.save_success');

// Với interpolation:
this.notif.showCompTypeTextError('notifications.delete_error', {
  interpolateParams: { itemName: 'Báo cáo tháng 1' },
});
// JSON: { "notifications": { "delete_error": "Không thể xóa '{{itemName}}'" } }
```

## iFrame Bridge — Micro-frontend

```typescript
// AppComponent của Shell (parent):
export class AppComponent {
  private notif = inject(LibsUiNotificationService);
  constructor() {
    this.notif.init(['MICRO_SITE_PUSH_MESSAGE_FROM_CHILD']);
  }
}

// Trong micro-frontend (child iFrame):
// Gọi notification bình thường — service tự detect isEmbedFrame()
// và gửi PostMessage lên parent thay vì render tại chỗ
this.notif.showCompTypeTextSuccess('Upload hoàn tất!');
```

## Browser Native Notification

```typescript
// Xin quyền trước
this.notif.systemRequestPermission();

// Hiển thị native notification (sau khi granted)
this.notif
  .systemSpawnNotification('New message', {
    body: 'Bạn có tin nhắn mới từ Team',
    icon: '/assets/icon.png',
  })
  .subscribe({
    next: (e) => console.log('event:', e),
    complete: () => console.log('closed'),
  });
```

## API — Public Methods

| Method                                      | Mô tả                                                |
| ------------------------------------------- | ---------------------------------------------------- |
| `showCompTypeTextSuccess(message, config?)` | Toast màu xanh lá — thành công                       |
| `showCompTypeTextError(message, config?)`   | Toast màu đỏ — lỗi                                   |
| `showCompTypeTextInfo(message, config?)`    | Toast màu xanh dương — thông tin                     |
| `showCompTypeTextWarning(message, config?)` | Toast màu vàng — cảnh báo                            |
| `init(messageNames, parentName?)`           | Khởi tạo iFrame bridge; gọi 1 lần trong AppComponent |
| `systemRequestPermission()`                 | Xin quyền browser native notification                |
| `systemSpawnNotification(title, opts?)`     | Hiển thị native notification → `Observable`          |
| `get TranslateService`                      | Getter cho TranslateService instance                 |

## INotificationTextPublicConfig

| Field               | Type                      | Default     | Mô tả                                 |
| ------------------- | ------------------------- | ----------- | ------------------------------------- |
| `title`             | `string`                  | `undefined` | Tiêu đề trên toast                    |
| `timeRemove`        | `number (ms)`             | `3000`      | Thời gian tự động đóng                |
| `positionRight`     | `number (px)`             | `12`        | Khoảng cách từ phải                   |
| `eventName`         | `'click' \| 'mouseenter'` | `undefined` | Event trigger callback                |
| `callback`          | `() => void`              | `undefined` | Hàm gọi khi interact                  |
| `interpolateParams` | `Record<string, any>`     | `undefined` | Params cho translate (tự escape HTML) |

## Lưu ý

- **Queue MAX 5**: Nếu đang có đủ 5 toast, toast cũ nhất tự bị remove khi toast mới xuất hiện.
- **interpolateParams escaping**: Mỗi value trong `interpolateParams` tự động qua `escapeHtml()` — safe với user input.
- **iFrame detection**: Service tự phát hiện `isEmbedFrame()`. Không cần config thêm trong child app.
- **init() chỉ gọi 1 lần**: Service có guard `isInit` signal — gọi nhiều lần không bị duplicate listener.